ROOT  6.06/09
Reference Guide
TTree.cxx
Go to the documentation of this file.
1 // @(#)root/tree:$Id$
2 // Author: Rene Brun 12/01/96
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 /**
12  \defgroup tree Tree Library
13 
14  To store large quantities of same-class objects, ROOT provides the TTree and
15  TNtuple classes. The TTree class is optimized to
16  reduce disk space and enhance access speed. A TNtuple is a TTree that is limited
17  to only hold floating-point numbers; a TTree on the other hand can hold all kind
18  of data, such as objects or arrays in addition to all the simple types.
19 
20 */
21 
22 /** \class TTree
23 \ingroup tree
24 
25 A TTree object has a header with a name and a title.
26 
27 It consists of a list of independent branches (TBranch). Each branch has its own
28 definition and list of buffers. Branch buffers may be automatically written to
29 disk or kept in memory until the Tree attribute `fMaxVirtualSize` is reached.
30 Variables of one branch are written to the same buffer. A branch buffer is
31 automatically compressed if the file compression attribute is set (default).
32 
33 Branches may be written to different files (see TBranch::SetFile).
34 
35 The ROOT user can decide to make one single branch and serialize one object into
36 one single I/O buffer or to make several branches. Making one single branch and
37 one single buffer can be the right choice when one wants to process only a subset
38 of all entries in the tree. (you know for example the list of entry numbers you
39 want to process). Making several branches is particularly interesting in the
40 data analysis phase, when one wants to histogram some attributes of an object
41 (entry) without reading all the attributes.
42 ~~~ {.cpp}
43  TTree *tree = new TTree(name, title)
44 ~~~
45 Creates a Tree with name and title.
46 
47 Various kinds of branches can be added to a tree:
48 
49 - simple structures or list of variables. (may be for C or Fortran structures)
50 - any object (inheriting from TObject). (we expect this option be the most frequent)
51 - a ClonesArray. (a specialized object for collections of same class objects)
52 
53 ## Case A
54 ~~~ {.cpp}
55  TBranch *branch = tree->Branch(branchname, address, leaflist, bufsize)
56 ~~~
57 - address is the address of the first item of a structure
58 - leaflist is the concatenation of all the variable names and types
59  separated by a colon character :
60  The variable name and the variable type are separated by a
61  slash (/). The variable type must be 1 character. (Characters
62  after the first are legal and will be appended to the visible
63  name of the leaf, but have no effect.) If no type is given, the
64  type of the variable is assumed to be the same as the previous
65  variable. If the first variable does not have a type, it is
66  assumed of type F by default. The list of currently supported
67  types is given below:
68  - C : a character string terminated by the 0 character
69  - B : an 8 bit signed integer (Char_t)
70  - b : an 8 bit unsigned integer (UChar_t)
71  - S : a 16 bit signed integer (Short_t)
72  - s : a 16 bit unsigned integer (UShort_t)
73  - I : a 32 bit signed integer (Int_t)
74  - i : a 32 bit unsigned integer (UInt_t)
75  - F : a 32 bit floating point (Float_t)
76  - D : a 64 bit floating point (Double_t)
77  - L : a 64 bit signed integer (Long64_t)
78  - l : a 64 bit unsigned integer (ULong64_t)
79  - O : [the letter 'o', not a zero] a boolean (Bool_t)
80 - If the address points to a single numerical variable, the leaflist is optional:
81  int value;
82  `tree->Branch(branchname, &value);`
83 - If the address points to more than one numerical variable, we strongly recommend
84  that the variable be sorted in decreasing order of size. Any other order will
85  result in a non-portable (even between CINT and compiled code on the platform)
86  TTree (i.e. you will not be able to read it back on a platform with a different
87  padding strategy).
88 
89 ## Case B
90 ~~~ {.cpp}
91  TBranch *branch = tree->Branch(branchname, &p_object, bufsize, splitlevel)
92  TBranch *branch = tree->Branch(branchname, className, &p_object, bufsize, splitlevel)
93 ~~~
94 - p_object is a pointer to an object.
95 - If className is not specified, Branch uses the type of p_object to determine the
96  type of the object.
97 - If className is used to specify explicitly the object type, the className must
98  be of a type related to the one pointed to by the pointer. It should be either
99  a parent or derived class.
100 - if splitlevel=0, the object is serialized in the branch buffer.
101 - if splitlevel=1, this branch will automatically be split
102  into subbranches, with one subbranch for each data member or object
103  of the object itself. In case the object member is a TClonesArray,
104  the mechanism described in case C is applied to this array.
105 - if splitlevel=2 ,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  it is processed as a TObject*, only one branch.
109 
110 Note: The pointer whose address is passed to TTree::Branch must not
111  be destroyed (i.e. go out of scope) until the TTree is deleted or
112  TTree::ResetBranchAddress is called.
113 
114 Note: The pointer p_object must be initialized before calling TTree::Branch
115 - Do either:
116 ~~~ {.cpp}
117  MyDataClass* p_object = 0;
118  tree->Branch(branchname, &p_object);
119 ~~~
120 - Or:
121 ~~~ {.cpp}
122  MyDataClass* p_object = new MyDataClass;
123  tree->Branch(branchname, &p_object);
124 ~~~
125 Whether the pointer is set to zero or not, the ownership of the object
126 is not taken over by the TTree. I.e. eventhough an object will be allocated
127 by TTree::Branch if the pointer p_object is zero, the object will <b>not</b>
128 be deleted when the TTree is deleted.
129 
130 ## Case C
131 ~~~ {.cpp}
132  MyClass object;
133  TBranch *branch = tree->Branch(branchname, &object, bufsize, splitlevel)
134 ~~~
135 Note: The 2nd parameter must be the address of a valid object.
136  The object must not be destroyed (i.e. be deleted) until the TTree
137  is deleted or TTree::ResetBranchAddress is called.
138 
139 - if splitlevel=0, the object is serialized in the branch buffer.
140 - if splitlevel=1 (default), this branch will automatically be split
141  into subbranches, with one subbranch for each data member or object
142  of the object itself. In case the object member is a TClonesArray,
143  the mechanism described in case C is applied to this array.
144 - if splitlevel=2 ,this branch will automatically be split
145  into subbranches, with one subbranch for each data member or object
146  of the object itself. In case the object member is a TClonesArray,
147  it is processed as a TObject*, only one branch.
148 
149 ## Case D
150 ~~~ {.cpp}
151  TBranch *branch = tree->Branch(branchname,clonesarray, bufsize, splitlevel)
152  clonesarray is the address of a pointer to a TClonesArray.
153 ~~~
154 The TClonesArray is a direct access list of objects of the same class.
155 For example, if the TClonesArray is an array of TTrack objects,
156 this function will create one subbranch for each data member of
157 the object TTrack.
158 
159 ## Case E
160 ~~~ {.cpp}
161  TBranch *branch = tree->Branch( branchname, STLcollection, buffsize, splitlevel);
162 ~~~
163 STLcollection is the address of a pointer to std::vector, std::list,
164 std::deque, std::set or std::multiset containing pointers to objects.
165 If the splitlevel is a value bigger than 100 (TTree::kSplitCollectionOfPointers)
166 then the collection will be written in split mode, e.g. if it contains objects of
167 any types deriving from TTrack this function will sort the objects
168 based on their type and store them in separate branches in split
169 mode.
170 ~~~ {.cpp}
171  branch->SetAddress(Void *address)
172 ~~~
173 In case of dynamic structures changing with each entry for example, one must
174 redefine the branch address before filling the branch again.
175 This is done via the TBranch::SetAddress member function.
176 ~~~ {.cpp}
177  tree->Fill()
178 ~~~
179 loops on all defined branches and for each branch invokes the Fill function.
180 
181 See also the class TNtuple (a simple Tree with branches of floats)
182 and the class TNtupleD (a simple Tree with branches of doubles)
183 
184 ## Adding a Branch to an Existing Tree
185 
186 You may want to add a branch to an existing tree. For example,
187 if one variable in the tree was computed with a certain algorithm,
188 you may want to try another algorithm and compare the results.
189 One solution is to add a new branch, fill it, and save the tree.
190 The code below adds a simple branch to an existing tree.
191 Note the kOverwrite option in the Write method, it overwrites the
192 existing tree. If it is not specified, two copies of the tree headers
193 are saved.
194 ~~~ {.cpp}
195  void tree3AddBranch() {
196  TFile f("tree3.root", "update");
197 
198  Float_t new_v;
199  TTree *t3 = (TTree*)f->Get("t3");
200  TBranch *newBranch = t3->Branch("new_v", &new_v, "new_v/F");
201 
202  Long64_t nentries = t3->GetEntries(); // read the number of entries in the t3
203 
204  for (Long64_t i = 0; i < nentries; i++) {
205  new_v= gRandom->Gaus(0, 1);
206  newBranch->Fill();
207  }
208 
209  t3->Write("", TObject::kOverwrite); // save only the new version of the tree
210  }
211 ~~~
212 Adding a branch is often not possible because the tree is in a read-only
213 file and you do not have permission to save the modified tree with the
214 new branch. Even if you do have the permission, you risk losing the
215 original tree with an unsuccessful attempt to save the modification.
216 Since trees are usually large, adding a branch could extend it over the
217 2GB limit. In this case, the attempt to write the tree fails, and the
218 original data is erased.
219 In addition, adding a branch to a tree enlarges the tree and increases
220 the amount of memory needed to read an entry, and therefore decreases
221 the performance.
222 
223 For these reasons, ROOT offers the concept of friends for trees (and chains).
224 We encourage you to use TTree::AddFriend rather than adding a branch manually.
225 
226 Begin_Macro
227 ../../../tutorials/tree/tree.C
228 End_Macro
229 
230 ~~~ {.cpp}
231  // A simple example with histograms and a tree
232  //
233  // This program creates :
234  // - a one dimensional histogram
235  // - a two dimensional histogram
236  // - a profile histogram
237  // - a tree
238  //
239  // These objects are filled with some random numbers and saved on a file.
240 
241  #include "TFile.h"
242  #include "TH1.h"
243  #include "TH2.h"
244  #include "TProfile.h"
245  #include "TRandom.h"
246  #include "TTree.h"
247 
248  //__________________________________________________________________________
249  main(int argc, char **argv)
250  {
251  // Create a new ROOT binary machine independent file.
252  // Note that this file may contain any kind of ROOT objects, histograms,trees
253  // pictures, graphics objects, detector geometries, tracks, events, etc..
254  // This file is now becoming the current directory.
255  TFile hfile("htree.root","RECREATE","Demo ROOT file with histograms & trees");
256 
257  // Create some histograms and a profile histogram
258  TH1F *hpx = new TH1F("hpx","This is the px distribution",100,-4,4);
259  TH2F *hpxpy = new TH2F("hpxpy","py ps px",40,-4,4,40,-4,4);
260  TProfile *hprof = new TProfile("hprof","Profile of pz versus px",100,-4,4,0,20);
261 
262  // Define some simple structures
263  typedef struct {Float_t x,y,z;} POINT;
264  typedef struct {
265  Int_t ntrack,nseg,nvertex;
266  UInt_t flag;
267  Float_t temperature;
268  } EVENTN;
269  static POINT point;
270  static EVENTN eventn;
271 
272  // Create a ROOT Tree
273  TTree *tree = new TTree("T","An example of ROOT tree with a few branches");
274  tree->Branch("point",&point,"x:y:z");
275  tree->Branch("eventn",&eventn,"ntrack/I:nseg:nvertex:flag/i:temperature/F");
276  tree->Branch("hpx","TH1F",&hpx,128000,0);
277 
278  Float_t px,py,pz;
279  static Float_t p[3];
280 
281  // Here we start a loop on 1000 events
282  for ( Int_t i=0; i<1000; i++) {
283  gRandom->Rannor(px,py);
284  pz = px*px + py*py;
285  Float_t random = gRandom->::Rndm(1);
286 
287  // Fill histograms
288  hpx->Fill(px);
289  hpxpy->Fill(px,py,1);
290  hprof->Fill(px,pz,1);
291 
292  // Fill structures
293  p[0] = px;
294  p[1] = py;
295  p[2] = pz;
296  point.x = 10*(random-1);;
297  point.y = 5*random;
298  point.z = 20*random;
299  eventn.ntrack = Int_t(100*random);
300  eventn.nseg = Int_t(2*eventn.ntrack);
301  eventn.nvertex = 1;
302  eventn.flag = Int_t(random+0.5);
303  eventn.temperature = 20+random;
304 
305  // Fill the tree. For each event, save the 2 structures and 3 objects
306  // In this simple example, the objects hpx, hprof and hpxpy are slightly
307  // different from event to event. We expect a big compression factor!
308  tree->Fill();
309  }
310  // End of the loop
311 
312  tree->Print();
313 
314  // Save all objects in this file
315  hfile.Write();
316 
317  // Close the file. Note that this is automatically done when you leave
318  // the application.
319  hfile.Close();
320 
321  return 0;
322 }
323 ~~~
324 */
325 
326 #include "RConfig.h"
327 #include "TTree.h"
328 
329 #include "TArrayC.h"
330 #include "TBufferFile.h"
331 #include "TBaseClass.h"
332 #include "TBasket.h"
333 #include "TBranchClones.h"
334 #include "TBranchElement.h"
335 #include "TBranchObject.h"
336 #include "TBranchRef.h"
337 #include "TBrowser.h"
338 #include "TClass.h"
339 #include "TClassEdit.h"
340 #include "TClonesArray.h"
341 #include "TCut.h"
342 #include "TDataMember.h"
343 #include "TDataType.h"
344 #include "TDirectory.h"
345 #include "TError.h"
346 #include "TEntryList.h"
347 #include "TEnv.h"
348 #include "TEventList.h"
349 #include "TFile.h"
350 #include "TFolder.h"
351 #include "TFriendElement.h"
352 #include "TInterpreter.h"
353 #include "TLeaf.h"
354 #include "TLeafB.h"
355 #include "TLeafC.h"
356 #include "TLeafD.h"
357 #include "TLeafElement.h"
358 #include "TLeafF.h"
359 #include "TLeafI.h"
360 #include "TLeafL.h"
361 #include "TLeafObject.h"
362 #include "TLeafS.h"
363 #include "TList.h"
364 #include "TMath.h"
365 #include "TROOT.h"
366 #include "TRealData.h"
367 #include "TRegexp.h"
368 #include "TStreamerElement.h"
369 #include "TStreamerInfo.h"
370 #include "TStyle.h"
371 #include "TSystem.h"
372 #include "TTreeCloner.h"
373 #include "TTreeCache.h"
374 #include "TTreeCacheUnzip.h"
375 #include "TVirtualCollectionProxy.h"
377 #include "TVirtualFitter.h"
378 #include "TVirtualIndex.h"
379 #include "TVirtualPerfStats.h"
380 #include "TVirtualPad.h"
381 #include "TBranchSTL.h"
382 #include "TSchemaRuleSet.h"
383 #include "TFileMergeInfo.h"
384 #include "ROOT/StringConv.h"
385 
386 #include <cstddef>
387 #include <fstream>
388 #include <sstream>
389 #include <string>
390 #include <stdio.h>
391 #include <limits.h>
392 
393 Int_t TTree::fgBranchStyle = 1; // Use new TBranch style with TBranchElement.
394 Long64_t TTree::fgMaxTreeSize = 100000000000LL;
395 
398 ////////////////////////////////////////////////////////////////////////////////
399 ////////////////////////////////////////////////////////////////////////////////
400 ////////////////////////////////////////////////////////////////////////////////
401 
402 static char DataTypeToChar(EDataType datatype)
403 {
404  // Return the leaflist 'char' for a given datatype.
405 
406  switch(datatype) {
407  case kChar_t: return 'B';
408  case kUChar_t: return 'b';
409  case kBool_t: return 'O';
410  case kShort_t: return 'S';
411  case kUShort_t: return 's';
412  case kCounter:
413  case kInt_t: return 'I';
414  case kUInt_t: return 'i';
415  case kDouble_t:
416  case kDouble32_t: return 'D';
417  case kFloat_t:
418  case kFloat16_t: return 'F';
419  case kLong_t: return 0; // unsupported
420  case kULong_t: return 0; // unsupported?
421  case kchar: return 0; // unsupported
422  case kLong64_t: return 'L';
423  case kULong64_t: return 'l';
424 
425  case kCharStar: return 'C';
426  case kBits: return 0; //unsupported
427 
428  case kOther_t:
429  case kNoType_t:
430  default:
431  return 0;
432  }
433  return 0;
434 }
435 
436 ////////////////////////////////////////////////////////////////////////////////
437 /// \class TTree::TFriendLock
438 /// Helper class to prevent infinite recursion in the usage of TTree Friends.
439 
440 ////////////////////////////////////////////////////////////////////////////////
441 /// Record in tree that it has been used while recursively looks through the friends.
442 
444 : fTree(tree)
445 {
446  // We could also add some code to acquire an actual
447  // lock to prevent multi-thread issues
448  fMethodBit = methodbit;
449  if (fTree) {
450  fPrevious = fTree->fFriendLockStatus & fMethodBit;
451  fTree->fFriendLockStatus |= fMethodBit;
452  } else {
453  fPrevious = 0;
454  }
455 }
456 
457 ////////////////////////////////////////////////////////////////////////////////
458 /// Copy constructor.
459 
461  fTree(tfl.fTree),
462  fMethodBit(tfl.fMethodBit),
463  fPrevious(tfl.fPrevious)
464 {
465 }
466 
467 ////////////////////////////////////////////////////////////////////////////////
468 /// Assignment operator.
469 
471 {
472  if(this!=&tfl) {
473  fTree=tfl.fTree;
475  fPrevious=tfl.fPrevious;
476  }
477  return *this;
478 }
479 
480 ////////////////////////////////////////////////////////////////////////////////
481 /// Restore the state of tree the same as before we set the lock.
482 
484 {
485  if (fTree) {
486  if (!fPrevious) {
487  fTree->fFriendLockStatus &= ~(fMethodBit & kBitMask);
488  }
489  }
490 }
491 
492 ////////////////////////////////////////////////////////////////////////////////
493 /// \class TTree::TClusterIterator
494 /// Helper class to iterate over cluster of baskets.
495 
496 ////////////////////////////////////////////////////////////////////////////////
497 /// Regular constructor.
498 /// TTree is not set as const, since we might modify if it is a TChain.
499 
500 TTree::TClusterIterator::TClusterIterator(TTree *tree, Long64_t firstEntry) : fTree(tree), fClusterRange(0), fStartEntry(0), fNextEntry(0)
501 {
502  if ( fTree->GetAutoFlush() <= 0 ) {
503  // Case of old files before November 9 2009
504  fStartEntry = firstEntry;
505  } else if (fTree->fNClusterRange) {
506  // Find the correct cluster range.
507  //
508  // Since fClusterRangeEnd contains the inclusive upper end of the range, we need to search for the
509  // range that was containing the previous entry and add 1 (because BinarySearch consider the values
510  // to be the inclusive start of the bucket).
511  fClusterRange = TMath::BinarySearch(fTree->fNClusterRange, fTree->fClusterRangeEnd, firstEntry - 1) + 1;
512 
513  Long64_t entryInRange;
514  Long64_t pedestal;
515  if (fClusterRange == 0) {
516  pedestal = 0;
517  entryInRange = firstEntry;
518  } else {
519  pedestal = fTree->fClusterRangeEnd[fClusterRange-1] + 1;
520  entryInRange = firstEntry - pedestal;
521  }
522  Long64_t autoflush;
523  if (fClusterRange == fTree->fNClusterRange) {
524  autoflush = fTree->fAutoFlush;
525  } else {
526  autoflush = fTree->fClusterSize[fClusterRange];
527  }
528  if (autoflush == 0) {
529  autoflush = GetEstimatedClusterSize();
530  }
531  fStartEntry = pedestal + entryInRange - entryInRange%autoflush;
532  } else {
533  fStartEntry = firstEntry - firstEntry%fTree->GetAutoFlush();
534  }
535  fNextEntry = fStartEntry; // Position correctly for the first call to Next()
536 }
537 
538 ////////////////////////////////////////////////////////////////////////////////
539 /// In the case where the cluster size was not fixed (old files and
540 /// case where autoflush was explicitly set to zero, we need estimate
541 /// a cluster size in relation to the size of the cache.
542 
544 {
545  Long64_t zipBytes = fTree->GetZipBytes();
546  if (zipBytes == 0) {
547  return fTree->GetEntries() - 1;
548  } else {
549  Long64_t clusterEstimate = 1;
550  Long64_t cacheSize = fTree->GetCacheSize();
551  if (cacheSize == 0) {
552  // Humm ... let's double check on the file.
553  TFile *file = fTree->GetCurrentFile();
554  if (file) {
555  TFileCacheRead *cache = file->GetCacheRead(fTree);
556  if (cache) {
557  cacheSize = cache->GetBufferSize();
558  }
559  }
560  }
561  if (cacheSize > 0) {
562  clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
563  if (clusterEstimate == 0)
564  clusterEstimate = 1;
565  }
566  return clusterEstimate;
567  }
568 }
569 
570 ////////////////////////////////////////////////////////////////////////////////
571 /// Move on to the next cluster and return the starting entry
572 /// of this next cluster
573 
575 {
576  fStartEntry = fNextEntry;
577  if ( fTree->GetAutoFlush() <= 0 ) {
578  // Case of old files before November 9 2009
579  Long64_t clusterEstimate = GetEstimatedClusterSize();
580  fNextEntry = fStartEntry + clusterEstimate;
581  } else {
582  if (fClusterRange == fTree->fNClusterRange) {
583  // We are looking at the last range ; its size
584  // is defined by AutoFlush itself and goes to the GetEntries.
585  fNextEntry += fTree->GetAutoFlush();
586  } else {
587  if (fStartEntry > fTree->fClusterRangeEnd[fClusterRange]) {
588  ++fClusterRange;
589  }
590  if (fClusterRange == fTree->fNClusterRange) {
591  // We are looking at the last range which size
592  // is defined by AutoFlush itself and goes to the GetEntries.
593  fNextEntry += fTree->GetAutoFlush();
594  } else {
595  Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
596  if (clusterSize == 0) {
597  clusterSize = GetEstimatedClusterSize();
598  }
599  fNextEntry += clusterSize;
600  if (fNextEntry > fTree->fClusterRangeEnd[fClusterRange]) {
601  // The last cluster of the range was a partial cluster,
602  // so the next cluster starts at the beginning of the
603  // next range.
604  fNextEntry = fTree->fClusterRangeEnd[fClusterRange] + 1;
605  }
606  }
607  }
608  }
609  if (fNextEntry > fTree->GetEntries()) {
610  fNextEntry = fTree->GetEntries();
611  }
612  return fStartEntry;
613 }
614 
615 ////////////////////////////////////////////////////////////////////////////////
616 ////////////////////////////////////////////////////////////////////////////////
617 ////////////////////////////////////////////////////////////////////////////////
618 
619 ////////////////////////////////////////////////////////////////////////////////
620 /// Default constructor and I/O constructor.
621 ///
622 /// Note: We do *not* insert ourself into the current directory.
623 ///
624 
625 TTree::TTree()
627 , TAttLine()
628 , TAttFill()
629 , TAttMarker()
630 , fEntries(0)
631 , fTotBytes(0)
632 , fZipBytes(0)
633 , fSavedBytes(0)
634 , fFlushedBytes(0)
635 , fWeight(1)
636 , fTimerInterval(0)
637 , fScanField(25)
638 , fUpdate(0)
640 , fNClusterRange(0)
641 , fMaxClusterRange(0)
642 , fMaxEntries(0)
643 , fMaxEntryLoop(0)
644 , fMaxVirtualSize(0)
645 , fAutoSave( -300000000)
646 , fAutoFlush(-30000000)
647 , fEstimate(1000000)
648 , fClusterRangeEnd(0)
649 , fClusterSize(0)
650 , fCacheSize(0)
651 , fChainOffset(0)
652 , fReadEntry(-1)
653 , fTotalBuffers(0)
654 , fPacketSize(100)
655 , fNfill(0)
656 , fDebug(0)
657 , fDebugMin(0)
658 , fDebugMax(9999999)
659 , fMakeClass(0)
660 , fFileNumber(0)
661 , fNotify(0)
662 , fDirectory(0)
663 , fBranches()
664 , fLeaves()
665 , fAliases(0)
666 , fEventList(0)
667 , fEntryList(0)
668 , fIndexValues()
669 , fIndex()
670 , fTreeIndex(0)
671 , fFriends(0)
672 , fPerfStats(0)
673 , fUserInfo(0)
674 , fPlayer(0)
675 , fClones(0)
676 , fBranchRef(0)
678 , fTransientBuffer(0)
681 {
682  fMaxEntries = 1000000000;
683  fMaxEntries *= 1000;
684 
685  fMaxEntryLoop = 1000000000;
686  fMaxEntryLoop *= 1000;
687 
689 }
690 
691 ////////////////////////////////////////////////////////////////////////////////
692 /// Normal tree constructor.
693 ///
694 /// The tree is created in the current directory.
695 /// Use the various functions Branch below to add branches to this tree.
696 ///
697 /// If the first character of title is a "/", the function assumes a folder name.
698 /// In this case, it creates automatically branches following the folder hierarchy.
699 /// splitlevel may be used in this case to control the split level.
700 
701 TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */)
702 : TNamed(name, title)
703 , TAttLine()
704 , TAttFill()
705 , TAttMarker()
706 , fEntries(0)
707 , fTotBytes(0)
708 , fZipBytes(0)
709 , fSavedBytes(0)
710 , fFlushedBytes(0)
711 , fWeight(1)
712 , fTimerInterval(0)
713 , fScanField(25)
714 , fUpdate(0)
716 , fNClusterRange(0)
717 , fMaxClusterRange(0)
718 , fMaxEntries(0)
719 , fMaxEntryLoop(0)
720 , fMaxVirtualSize(0)
721 , fAutoSave( -300000000)
722 , fAutoFlush(-30000000)
723 , fEstimate(1000000)
724 , fClusterRangeEnd(0)
725 , fClusterSize(0)
726 , fCacheSize(0)
727 , fChainOffset(0)
728 , fReadEntry(-1)
729 , fTotalBuffers(0)
730 , fPacketSize(100)
731 , fNfill(0)
732 , fDebug(0)
733 , fDebugMin(0)
734 , fDebugMax(9999999)
735 , fMakeClass(0)
736 , fFileNumber(0)
737 , fNotify(0)
738 , fDirectory(0)
739 , fBranches()
740 , fLeaves()
741 , fAliases(0)
742 , fEventList(0)
743 , fEntryList(0)
744 , fIndexValues()
745 , fIndex()
746 , fTreeIndex(0)
747 , fFriends(0)
748 , fPerfStats(0)
749 , fUserInfo(0)
750 , fPlayer(0)
751 , fClones(0)
752 , fBranchRef(0)
754 , fTransientBuffer(0)
757 {
758  // TAttLine state.
762 
763  // TAttFill state.
766 
767  // TAttMarkerState.
771 
772  fMaxEntries = 1000000000;
773  fMaxEntries *= 1000;
774 
775  fMaxEntryLoop = 1000000000;
776  fMaxEntryLoop *= 1000;
777 
778  // Insert ourself into the current directory.
779  // FIXME: This is very annoying behaviour, we should
780  // be able to choose to not do this like we
781  // can with a histogram.
783  if (fDirectory) fDirectory->Append(this);
784 
786 
787  // If title starts with "/" and is a valid folder name, a superbranch
788  // is created.
789  // FIXME: Why?
790  if (strlen(title) > 2) {
791  if (title[0] == '/') {
792  Branch(title+1,32000,splitlevel);
793  }
794  }
795 }
796 
797 ////////////////////////////////////////////////////////////////////////////////
798 /// Destructor.
799 
801 {
802  if (fDirectory) {
803  // We are in a directory, which may possibly be a file.
804  if (fDirectory->GetList()) {
805  // Remove us from the directory listing.
806  fDirectory->Remove(this);
807  }
808  //delete the file cache if it points to this Tree
809  TFile *file = fDirectory->GetFile();
810  MoveReadCache(file,0);
811  }
812  // We don't own the leaves in fLeaves, the branches do.
813  fLeaves.Clear();
814  // I'm ready to destroy any objects allocated by
815  // SetAddress() by my branches. If I have clones,
816  // tell them to zero their pointers to this shared
817  // memory.
818  if (fClones && fClones->GetEntries()) {
819  // I have clones.
820  // I am about to delete the objects created by
821  // SetAddress() which we are sharing, so tell
822  // the clones to release their pointers to them.
823  for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
824  TTree* clone = (TTree*) lnk->GetObject();
825  // clone->ResetBranchAddresses();
826 
827  // Reset only the branch we have set the address of.
828  CopyAddresses(clone,kTRUE);
829  }
830  }
831  // Get rid of our branches, note that this will also release
832  // any memory allocated by TBranchElement::SetAddress().
833  fBranches.Delete();
834  // FIXME: We must consider what to do with the reset of these if we are a clone.
835  delete fPlayer;
836  fPlayer = 0;
837  if (fFriends) {
838  fFriends->Delete();
839  delete fFriends;
840  fFriends = 0;
841  }
842  if (fAliases) {
843  fAliases->Delete();
844  delete fAliases;
845  fAliases = 0;
846  }
847  if (fUserInfo) {
848  fUserInfo->Delete();
849  delete fUserInfo;
850  fUserInfo = 0;
851  }
852  if (fClones) {
853  // Clone trees should no longer be removed from fClones when they are deleted.
854  gROOT->GetListOfCleanups()->Remove(fClones);
855  // Note: fClones does not own its content.
856  delete fClones;
857  fClones = 0;
858  }
859  if (fEntryList) {
861  // Delete the entry list if it is marked to be deleted and it is not also
862  // owned by a directory. (Otherwise we would need to make sure that a
863  // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
864  delete fEntryList;
865  fEntryList=0;
866  }
867  }
868  delete fTreeIndex;
869  fTreeIndex = 0;
870  delete fBranchRef;
871  fBranchRef = 0;
872  delete [] fClusterRangeEnd;
873  fClusterRangeEnd = 0;
874  delete [] fClusterSize;
875  fClusterSize = 0;
876  // Must be done after the destruction of friends.
877  // Note: We do *not* own our directory.
878  fDirectory = 0;
879 
880  if (fTransientBuffer) {
881  delete fTransientBuffer;
882  fTransientBuffer = 0;
883  }
884 }
885 
886 ////////////////////////////////////////////////////////////////////////////////
887 /// Returns the transient buffer currently used by this TTree for reading/writing baskets.
888 
890 {
891  if (fTransientBuffer) {
892  if (fTransientBuffer->BufferSize() < size) {
893  fTransientBuffer->Expand(size);
894  }
895  return fTransientBuffer;
896  }
898  return fTransientBuffer;
899 }
900 
901 ////////////////////////////////////////////////////////////////////////////////
902 /// Add branch with name bname to the Tree cache.
903 /// If bname="*" all branches are added to the cache.
904 /// if subbranches is true all the branches of the subbranches are
905 /// also put to the cache.
906 ///
907 /// Returns:
908 /// - 0 branch added or already included
909 /// - -1 on error
910 
911 Int_t TTree::AddBranchToCache(const char*bname, Bool_t subbranches)
912 {
913  if (!GetTree()) {
914  if (LoadTree(0)<0) {
915  Error("AddBranchToCache","Could not load a tree");
916  return -1;
917  }
918  }
919  if (GetTree()) {
920  if (GetTree() != this) {
921  return GetTree()->AddBranchToCache(bname, subbranches);
922  }
923  } else {
924  Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
925  return -1;
926  }
927 
928  TFile *f = GetCurrentFile();
929  if (!f) {
930  Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
931  return -1;
932  }
933  TTreeCache *tc = GetReadCache(f,kTRUE);
934  if (!tc) {
935  Error("AddBranchToCache", "No cache is available, branch not added");
936  return -1;
937  }
938  return tc->AddBranch(bname,subbranches);
939 }
940 
941 ////////////////////////////////////////////////////////////////////////////////
942 /// Add branch b to the Tree cache.
943 /// if subbranches is true all the branches of the subbranches are
944 /// also put to the cache.
945 ///
946 /// Returns:
947 /// - 0 branch added or already included
948 /// - -1 on error
949 
951 {
952  if (!GetTree()) {
953  if (LoadTree(0)<0) {
954  Error("AddBranchToCache","Could not load a tree");
955  return -1;
956  }
957  }
958  if (GetTree()) {
959  if (GetTree() != this) {
960  Int_t res = GetTree()->AddBranchToCache(b, subbranches);
961  if (res<0) {
962  Error("AddBranchToCache", "Error adding branch");
963  }
964  return res;
965  }
966  } else {
967  Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
968  return -1;
969  }
970 
971  TFile *f = GetCurrentFile();
972  if (!f) {
973  Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
974  return -1;
975  }
976  TTreeCache *tc = GetReadCache(f,kTRUE);
977  if (!tc) {
978  Error("AddBranchToCache", "No cache is available, branch not added");
979  return -1;
980  }
981  return tc->AddBranch(b,subbranches);
982 }
983 
984 ////////////////////////////////////////////////////////////////////////////////
985 /// Remove the branch with name 'bname' from the Tree cache.
986 /// If bname="*" all branches are removed from the cache.
987 /// if subbranches is true all the branches of the subbranches are
988 /// also removed from the cache.
989 ///
990 /// Returns:
991 /// - 0 branch dropped or not in cache
992 /// - -1 on error
993 
994 Int_t TTree::DropBranchFromCache(const char*bname, Bool_t subbranches)
995 {
996  if (!GetTree()) {
997  if (LoadTree(0)<0) {
998  Error("DropBranchFromCache","Could not load a tree");
999  return -1;
1000  }
1001  }
1002  if (GetTree()) {
1003  if (GetTree() != this) {
1004  return GetTree()->DropBranchFromCache(bname, subbranches);
1005  }
1006  } else {
1007  Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1008  return -1;
1009  }
1010 
1011  TFile *f = GetCurrentFile();
1012  if (!f) {
1013  Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1014  return -1;
1015  }
1016  TTreeCache *tc = GetReadCache(f,kTRUE);
1017  if (!tc) {
1018  Error("DropBranchFromCache", "No cache is available, branch not dropped");
1019  return -1;
1020  }
1021  return tc->DropBranch(bname,subbranches);
1022 }
1023 
1024 ////////////////////////////////////////////////////////////////////////////////
1025 /// Remove the branch b from the Tree cache.
1026 /// if subbranches is true all the branches of the subbranches are
1027 /// also removed from the cache.
1028 ///
1029 /// Returns:
1030 /// - 0 branch dropped or not in cache
1031 /// - -1 on error
1032 
1035  if (!GetTree()) {
1036  if (LoadTree(0)<0) {
1037  Error("DropBranchFromCache","Could not load a tree");
1038  return -1;
1039  }
1040  }
1041  if (GetTree()) {
1042  if (GetTree() != this) {
1043  Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1044  if (res<0) {
1045  Error("DropBranchFromCache", "Error dropping branch");
1046  }
1047  return res;
1048  }
1049  } else {
1050  Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1051  return -1;
1052  }
1053 
1054  TFile *f = GetCurrentFile();
1055  if (!f) {
1056  Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1057  return -1;
1058  }
1059  TTreeCache *tc = GetReadCache(f,kTRUE);
1060  if (!tc) {
1061  Error("DropBranchFromCache", "No cache is available, branch not dropped");
1062  return -1;
1063  }
1064  return tc->DropBranch(b,subbranches);
1065 }
1066 
1067 ////////////////////////////////////////////////////////////////////////////////
1068 /// Add a cloned tree to our list of trees to be notified whenever we change
1069 /// our branch addresses or when we are deleted.
1070 
1071 void TTree::AddClone(TTree* clone)
1073  if (!fClones) {
1074  fClones = new TList();
1075  fClones->SetOwner(false);
1076  // So that the clones are automatically removed from the list when
1077  // they are deleted.
1078  gROOT->GetListOfCleanups()->Add(fClones);
1079  }
1080  if (!fClones->FindObject(clone)) {
1081  fClones->Add(clone);
1082  }
1083 }
1084 
1085 ////////////////////////////////////////////////////////////////////////////////
1086 /// Add a TFriendElement to the list of friends.
1087 ///
1088 /// This function:
1089 /// - opens a file if filename is specified
1090 /// - reads a Tree with name treename from the file (current directory)
1091 /// - adds the Tree to the list of friends
1092 /// see other AddFriend functions
1093 ///
1094 /// A TFriendElement TF describes a TTree object TF in a file.
1095 /// When a TFriendElement TF is added to the the list of friends of an
1096 /// existing TTree T, any variable from TF can be referenced in a query
1097 /// to T.
1098 ///
1099 /// A tree keeps a list of friends. In the context of a tree (or a chain),
1100 /// friendship means unrestricted access to the friends data. In this way
1101 /// it is much like adding another branch to the tree without taking the risk
1102 /// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1103 /// method. The tree in the diagram below has two friends (friend_tree1 and
1104 /// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1105 ///
1106 /// \image html ttree_friend1.png
1107 ///
1108 /// The AddFriend method has two parameters, the first is the tree name and the
1109 /// second is the name of the ROOT file where the friend tree is saved.
1110 /// AddFriend automatically opens the friend file. If no file name is given,
1111 /// the tree called ft1 is assumed to be in the same file as the original tree.
1112 ///
1113 /// tree.AddFriend("ft1","friendfile1.root");
1114 /// If the friend tree has the same name as the original tree, you can give it
1115 /// an alias in the context of the friendship:
1116 ///
1117 /// tree.AddFriend("tree1 = tree","friendfile1.root");
1118 /// Once the tree has friends, we can use TTree::Draw as if the friend's
1119 /// variables were in the original tree. To specify which tree to use in
1120 /// the Draw method, use the syntax:
1121 /// ~~~ {.cpp}
1122 /// <treeName>.<branchname>.<varname>
1123 /// ~~~
1124 /// If the variablename is enough to uniquely identify the variable, you can
1125 /// leave out the tree and/or branch name.
1126 /// For example, these commands generate a 3-d scatter plot of variable "var"
1127 /// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1128 /// TTree ft2.
1129 /// ~~~ {.cpp}
1130 /// tree.AddFriend("ft1","friendfile1.root");
1131 /// tree.AddFriend("ft2","friendfile2.root");
1132 /// tree.Draw("var:ft1.v1:ft2.v2");
1133 /// ~~~
1134 /// \image html ttree_friend2.png
1135 ///
1136 /// The picture illustrates the access of the tree and its friends with a
1137 /// Draw command.
1138 /// When AddFriend is called, the ROOT file is automatically opened and the
1139 /// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1140 /// the list of friends of tree.
1141 /// The number of entries in the friend must be equal or greater to the number
1142 /// of entries of the original tree. If the friend tree has fewer entries a
1143 /// warning is given and the missing entries are not included in the histogram.
1144 /// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1145 /// When the tree is written to file (TTree::Write), the friends list is saved
1146 /// with it. And when the tree is retrieved, the trees on the friends list are
1147 /// also retrieved and the friendship restored.
1148 /// When a tree is deleted, the elements of the friend list are also deleted.
1149 /// It is possible to declare a friend tree that has the same internal
1150 /// structure (same branches and leaves) as the original tree, and compare the
1151 /// same values by specifying the tree.
1152 /// ~~~ {.cpp}
1153 /// tree.Draw("var:ft1.var:ft2.var")
1154 /// ~~~
1155 
1156 TFriendElement* TTree::AddFriend(const char* treename, const char* filename)
1158  if (!fFriends) {
1159  fFriends = new TList();
1160  }
1161  TFriendElement* fe = new TFriendElement(this, treename, filename);
1162 
1163  fFriends->Add(fe);
1164  TTree* t = fe->GetTree();
1165  if (t) {
1166  if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1167  Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename, filename, t->GetEntries(), fEntries);
1168  }
1169  } else {
1170  Warning("AddFriend", "Cannot add FriendElement %s in file %s", treename, filename);
1171  }
1172  return fe;
1173 }
1174 
1175 ////////////////////////////////////////////////////////////////////////////////
1176 /// Add a TFriendElement to the list of friends.
1177 ///
1178 /// The TFile is managed by the user (e.g. the user must delete the file).
1179 /// For complete description see AddFriend(const char *, const char *).
1180 /// This function:
1181 /// - reads a Tree with name treename from the file
1182 /// - adds the Tree to the list of friends
1183 
1184 TFriendElement* TTree::AddFriend(const char* treename, TFile* file)
1186  if (!fFriends) {
1187  fFriends = new TList();
1188  }
1189  TFriendElement *fe = new TFriendElement(this, treename, file);
1190  R__ASSERT(fe);
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, file->GetName(), t->GetEntries(), fEntries);
1196  }
1197  } else {
1198  Warning("AddFriend", "unknown tree '%s' in file '%s'", treename, file->GetName());
1199  }
1200  return fe;
1201 }
1202 
1203 ////////////////////////////////////////////////////////////////////////////////
1204 /// Add a TFriendElement to the list of friends.
1205 ///
1206 /// The TTree is managed by the user (e.g., the user must delete the file).
1207 /// For a complete description see AddFriend(const char *, const char *).
1208 
1209 TFriendElement* TTree::AddFriend(TTree* tree, const char* alias, Bool_t warn)
1211  if (!tree) {
1212  return 0;
1213  }
1214  if (!fFriends) {
1215  fFriends = new TList();
1216  }
1217  TFriendElement* fe = new TFriendElement(this, tree, alias);
1218  R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1219  fFriends->Add(fe);
1220  TTree* t = fe->GetTree();
1221  if (warn && (t->GetEntries() < fEntries)) {
1222  Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1223  tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(), fEntries);
1224  }
1225  return fe;
1226 }
1227 
1228 ////////////////////////////////////////////////////////////////////////////////
1229 /// AutoSave tree header every fAutoSave bytes.
1230 ///
1231 /// When large Trees are produced, it is safe to activate the AutoSave
1232 /// procedure. Some branches may have buffers holding many entries.
1233 /// If fAutoSave is negative, AutoSave is automatically called by
1234 /// TTree::Fill when the number of bytes generated since the previous
1235 /// AutoSave is greater than -fAutoSave bytes.
1236 /// If fAutoSave is positive, AutoSave is automatically called by
1237 /// TTree::Fill every N entries.
1238 /// This function may also be invoked by the user.
1239 /// Each AutoSave generates a new key on the file.
1240 /// Once the key with the tree header has been written, the previous cycle
1241 /// (if any) is deleted.
1242 ///
1243 /// Note that calling TTree::AutoSave too frequently (or similarly calling
1244 /// TTree::SetAutoSave with a small value) is an expensive operation.
1245 /// You should make tests for your own application to find a compromise
1246 /// between speed and the quantity of information you may loose in case of
1247 /// a job crash.
1248 ///
1249 /// In case your program crashes before closing the file holding this tree,
1250 /// the file will be automatically recovered when you will connect the file
1251 /// in UPDATE mode.
1252 /// The Tree will be recovered at the status corresponding to the last AutoSave.
1253 ///
1254 /// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1255 /// This allows another process to analyze the Tree while the Tree is being filled.
1256 ///
1257 /// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1258 /// the current basket are closed-out and written to disk individually.
1259 ///
1260 /// By default the previous header is deleted after having written the new header.
1261 /// if option contains "Overwrite", the previous Tree header is deleted
1262 /// before written the new header. This option is slightly faster, but
1263 /// the default option is safer in case of a problem (disk quota exceeded)
1264 /// when writing the new header.
1265 ///
1266 /// The function returns the number of bytes written to the file.
1267 /// if the number of bytes is null, an error has occurred while writing
1268 /// the header to the file.
1269 ///
1270 /// ## How to write a Tree in one process and view it from another process
1271 ///
1272 /// The following two scripts illustrate how to do this.
1273 /// The script treew.C is executed by process1, treer.C by process2
1274 ///
1275 /// script treew.C:
1276 /// ~~~ {.cpp}
1277 /// void treew() {
1278 /// TFile f("test.root","recreate");
1279 /// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1280 /// Float_t px, py, pz;
1281 /// for ( Int_t i=0; i<10000000; i++) {
1282 /// gRandom->Rannor(px,py);
1283 /// pz = px*px + py*py;
1284 /// Float_t random = gRandom->Rndm(1);
1285 /// ntuple->Fill(px,py,pz,random,i);
1286 /// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1287 /// }
1288 /// }
1289 /// ~~~
1290 /// script treer.C:
1291 /// ~~~ {.cpp}
1292 /// void treer() {
1293 /// TFile f("test.root");
1294 /// TTree *ntuple = (TTree*)f.Get("ntuple");
1295 /// TCanvas c1;
1296 /// Int_t first = 0;
1297 /// while(1) {
1298 /// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1299 /// else ntuple->Draw("px>>+hpx","","",10000000,first);
1300 /// first = (Int_t)ntuple->GetEntries();
1301 /// c1.Update();
1302 /// gSystem->Sleep(1000); //sleep 1 second
1303 /// ntuple->Refresh();
1304 /// }
1305 /// }
1306 /// ~~~
1307 
1310  if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1311  if (gDebug > 0) {
1312  printf("AutoSave Tree:%s after %lld bytes written\n",GetName(),fTotBytes);
1313  }
1314  TString opt = option;
1315  opt.ToLower();
1316 
1317  if (opt.Contains("flushbaskets")) {
1318  if (gDebug > 0) printf("AutoSave: calling FlushBaskets \n");
1319  FlushBaskets();
1320  }
1321 
1323 
1325  Long64_t nbytes;
1326  if (opt.Contains("overwrite")) {
1327  nbytes = fDirectory->WriteTObject(this,"","overwrite");
1328  } else {
1329  nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1330  if (nbytes && key) {
1331  key->Delete();
1332  delete key;
1333  }
1334  }
1335  // save StreamerInfo
1336  TFile *file = fDirectory->GetFile();
1337  if (file) file->WriteStreamerInfo();
1338 
1339  if (opt.Contains("saveself")) {
1340  fDirectory->SaveSelf();
1341  //the following line is required in case GetUserInfo contains a user class
1342  //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1343  if (file) file->WriteHeader();
1344  }
1345 
1346  return nbytes;
1347 }
1348 
1349 namespace {
1350  // This error message is repeated several times in the code. We write it once.
1351  const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1352  " is an instance of an stl collection and does not have a compiled CollectionProxy."
1353  " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1354 }
1355 
1356 ////////////////////////////////////////////////////////////////////////////////
1357 /// Same as TTree::Branch() with added check that addobj matches className.
1358 ///
1359 /// See TTree::Branch() for other details.
1360 ///
1361 
1362 TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1364  TClass* claim = TClass::GetClass(classname);
1365  if (!ptrClass) {
1366  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1367  Error("Branch", writeStlWithoutProxyMsg,
1368  claim->GetName(), branchname, claim->GetName());
1369  return 0;
1370  }
1371  return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1372  }
1373  TClass* actualClass = 0;
1374  void** addr = (void**) addobj;
1375  if (addr) {
1376  actualClass = ptrClass->GetActualClass(*addr);
1377  }
1378  if (ptrClass && claim) {
1379  if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1380  // Note we currently do not warn in case of splicing or over-expectation).
1381  if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1382  // The type is the same according to the C++ type_info, we must be in the case of
1383  // a template of Double32_t. This is actually a correct case.
1384  } else {
1385  Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1386  claim->GetName(), branchname, ptrClass->GetName());
1387  }
1388  } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1389  if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1390  // The type is the same according to the C++ type_info, we must be in the case of
1391  // a template of Double32_t. This is actually a correct case.
1392  } else {
1393  Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1394  actualClass->GetName(), branchname, claim->GetName());
1395  }
1396  }
1397  }
1398  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1399  Error("Branch", writeStlWithoutProxyMsg,
1400  claim->GetName(), branchname, claim->GetName());
1401  return 0;
1402  }
1403  return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1404 }
1405 
1406 ////////////////////////////////////////////////////////////////////////////////
1407 /// Same as TTree::Branch but automatic detection of the class name.
1408 /// See TTree::Branch for other details.
1409 
1410 TBranch* TTree::BranchImp(const char* branchname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1412  if (!ptrClass) {
1413  Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1414  return 0;
1415  }
1416  TClass* actualClass = 0;
1417  void** addr = (void**) addobj;
1418  if (addr && *addr) {
1419  actualClass = ptrClass->GetActualClass(*addr);
1420  if (!actualClass) {
1421  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",
1422  branchname, ptrClass->GetName());
1423  actualClass = ptrClass;
1424  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1425  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());
1426  return 0;
1427  }
1428  } else {
1429  actualClass = ptrClass;
1430  }
1431  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1432  Error("Branch", writeStlWithoutProxyMsg,
1433  actualClass->GetName(), branchname, actualClass->GetName());
1434  return 0;
1435  }
1436  return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1437 }
1438 
1439 ////////////////////////////////////////////////////////////////////////////////
1440 /// Same as TTree::Branch but automatic detection of the class name.
1441 /// See TTree::Branch for other details.
1442 
1443 TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1445  TClass* claim = TClass::GetClass(classname);
1446  if (!ptrClass) {
1447  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1448  Error("Branch", writeStlWithoutProxyMsg,
1449  claim->GetName(), branchname, claim->GetName());
1450  return 0;
1451  } else if (claim == 0) {
1452  Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1453  return 0;
1454  }
1455  ptrClass = claim;
1456  }
1457  TClass* actualClass = 0;
1458  if (!addobj) {
1459  Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1460  return 0;
1461  }
1462  actualClass = ptrClass->GetActualClass(addobj);
1463  if (ptrClass && claim) {
1464  if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1465  // Note we currently do not warn in case of splicing or over-expectation).
1466  if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1467  // The type is the same according to the C++ type_info, we must be in the case of
1468  // a template of Double32_t. This is actually a correct case.
1469  } else {
1470  Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1471  claim->GetName(), branchname, ptrClass->GetName());
1472  }
1473  } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1474  if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1475  // The type is the same according to the C++ type_info, we must be in the case of
1476  // a template of Double32_t. This is actually a correct case.
1477  } else {
1478  Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1479  actualClass->GetName(), branchname, claim->GetName());
1480  }
1481  }
1482  }
1483  if (!actualClass) {
1484  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",
1485  branchname, ptrClass->GetName());
1486  actualClass = ptrClass;
1487  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1488  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());
1489  return 0;
1490  }
1491  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1492  Error("Branch", writeStlWithoutProxyMsg,
1493  actualClass->GetName(), branchname, actualClass->GetName());
1494  return 0;
1495  }
1496  return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1497 }
1498 
1499 ////////////////////////////////////////////////////////////////////////////////
1500 /// Same as TTree::Branch but automatic detection of the class name.
1501 /// See TTree::Branch for other details.
1502 
1503 TBranch* TTree::BranchImpRef(const char* branchname, TClass* ptrClass, EDataType datatype, void* addobj, Int_t bufsize, Int_t splitlevel)
1505  if (!ptrClass) {
1506  if (datatype == kOther_t || datatype == kNoType_t) {
1507  Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1508  } else {
1509  TString varname; varname.Form("%s/%c",branchname,DataTypeToChar(datatype));
1510  return Branch(branchname,addobj,varname.Data(),bufsize);
1511  }
1512  return 0;
1513  }
1514  TClass* actualClass = 0;
1515  if (!addobj) {
1516  Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1517  return 0;
1518  }
1519  actualClass = ptrClass->GetActualClass(addobj);
1520  if (!actualClass) {
1521  Warning("Branch", "The actual TClass corresponding to the object provided for the definition of the branch \"%s\" is missing.\n\tThe object will be truncated down to its %s part",
1522  branchname, ptrClass->GetName());
1523  actualClass = ptrClass;
1524  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1525  Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s", actualClass->GetName(), branchname, ptrClass->GetName());
1526  return 0;
1527  }
1528  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1529  Error("Branch", writeStlWithoutProxyMsg,
1530  actualClass->GetName(), branchname, actualClass->GetName());
1531  return 0;
1532  }
1533  return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1534 }
1535 
1536 ////////////////////////////////////////////////////////////////////////////////
1537 /// Deprecated function. Use next function instead.
1538 
1539 Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1541  return Branch((TCollection*) li, bufsize, splitlevel);
1542 }
1543 
1544 ////////////////////////////////////////////////////////////////////////////////
1545 /// Create one branch for each element in the collection.
1546 ///
1547 /// Each entry in the collection becomes a top level branch if the
1548 /// corresponding class is not a collection. If it is a collection, the entry
1549 /// in the collection becomes in turn top level branches, etc.
1550 /// The splitlevel is decreased by 1 every time a new collection is found.
1551 /// For example if list is a TObjArray*
1552 /// - if splitlevel = 1, one top level branch is created for each element
1553 /// of the TObjArray.
1554 /// - if splitlevel = 2, one top level branch is created for each array element.
1555 /// if, in turn, one of the array elements is a TCollection, one top level
1556 /// branch will be created for each element of this collection.
1557 ///
1558 /// In case a collection element is a TClonesArray, the special Tree constructor
1559 /// for TClonesArray is called.
1560 /// The collection itself cannot be a TClonesArray.
1561 ///
1562 /// The function returns the total number of branches created.
1563 ///
1564 /// If name is given, all branch names will be prefixed with name_.
1565 ///
1566 /// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1567 ///
1568 /// IMPORTANT NOTE2: The branches created by this function will have names
1569 /// corresponding to the collection or object names. It is important
1570 /// to give names to collections to avoid misleading branch names or
1571 /// identical branch names. By default collections have a name equal to
1572 /// the corresponding class name, e.g. the default name for a TList is "TList".
1573 ///
1574 /// And in general in any cases two or more master branches contain subbranches
1575 /// with identical names, one must add a "." (dot) character at the end
1576 /// of the master branch name. This will force the name of the subbranch
1577 /// to be master.subbranch instead of simply subbranch.
1578 /// This situation happens when the top level object (say event)
1579 /// has two or more members referencing the same class.
1580 /// For example, if a Tree has two branches B1 and B2 corresponding
1581 /// to objects of the same class MyClass, one can do:
1582 /// ~~~ {.cpp}
1583 /// tree.Branch("B1.","MyClass",&b1,8000,1);
1584 /// tree.Branch("B2.","MyClass",&b2,8000,1);
1585 /// ~~~
1586 /// if MyClass has 3 members a,b,c, the two instructions above will generate
1587 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1588 ///
1589 /// Example:
1590 /// ~~~ {.cpp}
1591 /// {
1592 /// TTree T("T","test list");
1593 /// TList *list = new TList();
1594 ///
1595 /// TObjArray *a1 = new TObjArray();
1596 /// a1->SetName("a1");
1597 /// list->Add(a1);
1598 /// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1599 /// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1600 /// a1->Add(ha1a);
1601 /// a1->Add(ha1b);
1602 /// TObjArray *b1 = new TObjArray();
1603 /// b1->SetName("b1");
1604 /// list->Add(b1);
1605 /// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1606 /// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1607 /// b1->Add(hb1a);
1608 /// b1->Add(hb1b);
1609 ///
1610 /// TObjArray *a2 = new TObjArray();
1611 /// a2->SetName("a2");
1612 /// list->Add(a2);
1613 /// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1614 /// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1615 /// a2->Add(ha2a);
1616 /// a2->Add(ha2b);
1617 ///
1618 /// T.Branch(list,16000,2);
1619 /// T.Print();
1620 /// }
1621 /// ~~~
1622 
1623 Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1625 
1626  if (!li) {
1627  return 0;
1628  }
1629  TObject* obj = 0;
1630  Int_t nbranches = GetListOfBranches()->GetEntries();
1631  if (li->InheritsFrom(TClonesArray::Class())) {
1632  Error("Branch", "Cannot call this constructor for a TClonesArray");
1633  return 0;
1634  }
1635  Int_t nch = strlen(name);
1636  TString branchname;
1637  TIter next(li);
1638  while ((obj = next())) {
1639  if ((splitlevel > 1) && obj->InheritsFrom(TCollection::Class()) && !obj->InheritsFrom(TClonesArray::Class())) {
1640  TCollection* col = (TCollection*) obj;
1641  if (nch) {
1642  branchname.Form("%s_%s_", name, col->GetName());
1643  } else {
1644  branchname.Form("%s_", col->GetName());
1645  }
1646  Branch(col, bufsize, splitlevel - 1, branchname);
1647  } else {
1648  if (nch && (name[nch-1] == '_')) {
1649  branchname.Form("%s%s", name, obj->GetName());
1650  } else {
1651  if (nch) {
1652  branchname.Form("%s_%s", name, obj->GetName());
1653  } else {
1654  branchname.Form("%s", obj->GetName());
1655  }
1656  }
1657  if (splitlevel > 99) {
1658  branchname += ".";
1659  }
1660  Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1661  }
1662  }
1663  return GetListOfBranches()->GetEntries() - nbranches;
1664 }
1665 
1666 ////////////////////////////////////////////////////////////////////////////////
1667 /// Create one branch for each element in the folder.
1668 /// Returns the total number of branches created.
1669 
1670 Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1672  TObject* ob = gROOT->FindObjectAny(foldername);
1673  if (!ob) {
1674  return 0;
1675  }
1676  if (ob->IsA() != TFolder::Class()) {
1677  return 0;
1678  }
1679  Int_t nbranches = GetListOfBranches()->GetEntries();
1680  TFolder* folder = (TFolder*) ob;
1681  TIter next(folder->GetListOfFolders());
1682  TObject* obj = 0;
1683  char* curname = new char[1000];
1684  char occur[20];
1685  while ((obj = next())) {
1686  snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1687  if (obj->IsA() == TFolder::Class()) {
1688  Branch(curname, bufsize, splitlevel - 1);
1689  } else {
1690  void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1691  for (Int_t i = 0; i < 1000; ++i) {
1692  if (curname[i] == 0) {
1693  break;
1694  }
1695  if (curname[i] == '/') {
1696  curname[i] = '.';
1697  }
1698  }
1699  Int_t noccur = folder->Occurence(obj);
1700  if (noccur > 0) {
1701  snprintf(occur,20, "_%d", noccur);
1702  strlcat(curname, occur,1000);
1703  }
1704  TBranchElement* br = (TBranchElement*) Bronch(curname, obj->ClassName(), add, bufsize, splitlevel - 1);
1705  if (br) br->SetBranchFolder();
1706  }
1707  }
1708  delete[] curname;
1709  return GetListOfBranches()->GetEntries() - nbranches;
1710 }
1711 
1712 ////////////////////////////////////////////////////////////////////////////////
1713 /// Create a new TTree Branch.
1714 ///
1715 /// This Branch constructor is provided to support non-objects in
1716 /// a Tree. The variables described in leaflist may be simple
1717 /// variables or structures. // See the two following
1718 /// constructors for writing objects in a Tree.
1719 ///
1720 /// By default the branch buffers are stored in the same file as the Tree.
1721 /// use TBranch::SetFile to specify a different file
1722 ///
1723 /// * address is the address of the first item of a structure.
1724 /// * leaflist is the concatenation of all the variable names and types
1725 /// separated by a colon character :
1726 /// The variable name and the variable type are separated by a slash (/).
1727 /// The variable type may be 0,1 or 2 characters. If no type is given,
1728 /// the type of the variable is assumed to be the same as the previous
1729 /// variable. If the first variable does not have a type, it is assumed
1730 /// of type F by default. The list of currently supported types is given below:
1731 /// - C : a character string terminated by the 0 character
1732 /// - B : an 8 bit signed integer (Char_t)
1733 /// - b : an 8 bit unsigned integer (UChar_t)
1734 /// - S : a 16 bit signed integer (Short_t)
1735 /// - s : a 16 bit unsigned integer (UShort_t)
1736 /// - I : a 32 bit signed integer (Int_t)
1737 /// - i : a 32 bit unsigned integer (UInt_t)
1738 /// - F : a 32 bit floating point (Float_t)
1739 /// - D : a 64 bit floating point (Double_t)
1740 /// - L : a 64 bit signed integer (Long64_t)
1741 /// - l : a 64 bit unsigned integer (ULong64_t)
1742 /// - O : [the letter 'o', not a zero] a boolean (Bool_t)
1743 ///
1744 /// Arrays of values are supported with the following syntax:
1745 /// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1746 /// if nelem is a leaf name, it is used as the variable size of the array,
1747 /// otherwise return 0.
1748 /// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1749 /// it is used as the fixed size of the array.
1750 /// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1751 /// where nelem and nelem2 are non-negative integer) then
1752 /// it is used as a 2 dimensional array of fixed size.
1753 ///
1754 /// Any of other form is not supported.
1755 ///
1756 /// Note that the TTree will assume that all the item are contiguous in memory.
1757 /// On some platform, this is not always true of the member of a struct or a class,
1758 /// due to padding and alignment. Sorting your data member in order of decreasing
1759 /// sizeof usually leads to their being contiguous in memory.
1760 ///
1761 /// * bufsize is the buffer size in bytes for this branch
1762 /// The default value is 32000 bytes and should be ok for most cases.
1763 /// You can specify a larger value (e.g. 256000) if your Tree is not split
1764 /// and each entry is large (Megabytes)
1765 /// A small value for bufsize is optimum if you intend to access
1766 /// the entries in the Tree randomly and your Tree is in split mode.
1767 
1768 TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1770  TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1771  if (branch->IsZombie()) {
1772  delete branch;
1773  branch = 0;
1774  return 0;
1775  }
1776  fBranches.Add(branch);
1777  return branch;
1778 }
1779 
1780 ////////////////////////////////////////////////////////////////////////////////
1781 /// Create a new branch with the object of class classname at address addobj.
1782 ///
1783 /// WARNING:
1784 ///
1785 /// Starting with Root version 3.01, the Branch function uses the new style
1786 /// branches (TBranchElement). To get the old behaviour, you can:
1787 /// - call BranchOld or
1788 /// - call TTree::SetBranchStyle(0)
1789 ///
1790 /// Note that with the new style, classname does not need to derive from TObject.
1791 /// It must derived from TObject if the branch style has been set to 0 (old)
1792 ///
1793 /// Note: See the comments in TBranchElement::SetAddress() for a more
1794 /// detailed discussion of the meaning of the addobj parameter in
1795 /// the case of new-style branches.
1796 ///
1797 /// Use splitlevel < 0 instead of splitlevel=0 when the class
1798 /// has a custom Streamer
1799 ///
1800 /// Note: if the split level is set to the default (99), TTree::Branch will
1801 /// not issue a warning if the class can not be split.
1802 
1803 TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1805  if (fgBranchStyle == 1) {
1806  return Bronch(name, classname, addobj, bufsize, splitlevel);
1807  } else {
1808  if (splitlevel < 0) {
1809  splitlevel = 0;
1810  }
1811  return BranchOld(name, classname, addobj, bufsize, splitlevel);
1812  }
1813 }
1814 
1815 ////////////////////////////////////////////////////////////////////////////////
1816 /// Create a new TTree BranchObject.
1817 ///
1818 /// Build a TBranchObject for an object of class classname.
1819 /// addobj is the address of a pointer to an object of class classname.
1820 /// IMPORTANT: classname must derive from TObject.
1821 /// The class dictionary must be available (ClassDef in class header).
1822 ///
1823 /// This option requires access to the library where the corresponding class
1824 /// is defined. Accessing one single data member in the object implies
1825 /// reading the full object.
1826 /// See the next Branch constructor for a more efficient storage
1827 /// in case the entry consists of arrays of identical objects.
1828 ///
1829 /// By default the branch buffers are stored in the same file as the Tree.
1830 /// use TBranch::SetFile to specify a different file
1831 ///
1832 /// IMPORTANT NOTE about branch names:
1833 ///
1834 /// In case two or more master branches contain subbranches with
1835 /// identical names, one must add a "." (dot) character at the end
1836 /// of the master branch name. This will force the name of the subbranch
1837 /// to be master.subbranch instead of simply subbranch.
1838 /// This situation happens when the top level object (say event)
1839 /// has two or more members referencing the same class.
1840 /// For example, if a Tree has two branches B1 and B2 corresponding
1841 /// to objects of the same class MyClass, one can do:
1842 /// ~~~ {.cpp}
1843 /// tree.Branch("B1.","MyClass",&b1,8000,1);
1844 /// tree.Branch("B2.","MyClass",&b2,8000,1);
1845 /// ~~~
1846 /// if MyClass has 3 members a,b,c, the two instructions above will generate
1847 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1848 ///
1849 /// bufsize is the buffer size in bytes for this branch
1850 /// The default value is 32000 bytes and should be ok for most cases.
1851 /// You can specify a larger value (e.g. 256000) if your Tree is not split
1852 /// and each entry is large (Megabytes)
1853 /// A small value for bufsize is optimum if you intend to access
1854 /// the entries in the Tree randomly and your Tree is in split mode.
1855 
1856 TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
1858  TClass* cl = TClass::GetClass(classname);
1859  if (!cl) {
1860  Error("BranchOld", "Cannot find class: '%s'", classname);
1861  return 0;
1862  }
1863  if (!cl->IsTObject()) {
1864  if (fgBranchStyle == 0) {
1865  Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1866  "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
1867  "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
1868  } else {
1869  Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1870  "\tYou can not use BranchOld to store objects of this type.",classname);
1871  }
1872  return 0;
1873  }
1874  TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
1875  fBranches.Add(branch);
1876  if (!splitlevel) {
1877  return branch;
1878  }
1879  // We are going to fully split the class now.
1880  TObjArray* blist = branch->GetListOfBranches();
1881  const char* rdname = 0;
1882  const char* dname = 0;
1883  TString branchname;
1884  char** apointer = (char**) addobj;
1885  TObject* obj = (TObject*) *apointer;
1886  Bool_t delobj = kFALSE;
1887  if (!obj) {
1888  obj = (TObject*) cl->New();
1889  delobj = kTRUE;
1890  }
1891  // Build the StreamerInfo if first time for the class.
1892  BuildStreamerInfo(cl, obj);
1893  // Loop on all public data members of the class and its base classes.
1894  Int_t lenName = strlen(name);
1895  Int_t isDot = 0;
1896  if (name[lenName-1] == '.') {
1897  isDot = 1;
1898  }
1899  TBranch* branch1 = 0;
1900  TRealData* rd = 0;
1901  TRealData* rdi = 0;
1902  TIter nexti(cl->GetListOfRealData());
1903  TIter next(cl->GetListOfRealData());
1904  // Note: This loop results in a full split because the
1905  // real data list includes all data members of
1906  // data members.
1907  while ((rd = (TRealData*) next())) {
1908  if (rd->TestBit(TRealData::kTransient)) continue;
1909 
1910  // Loop over all data members creating branches for each one.
1911  TDataMember* dm = rd->GetDataMember();
1912  if (!dm->IsPersistent()) {
1913  // Do not process members with an "!" as the first character in the comment field.
1914  continue;
1915  }
1916  if (rd->IsObject()) {
1917  // We skip data members of class type.
1918  // But we do build their real data, their
1919  // streamer info, and write their streamer
1920  // info to the current directory's file.
1921  // Oh yes, and we also do this for all of
1922  // their base classes.
1923  TClass* clm = TClass::GetClass(dm->GetFullTypeName());
1924  if (clm) {
1925  BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
1926  }
1927  continue;
1928  }
1929  rdname = rd->GetName();
1930  dname = dm->GetName();
1931  if (cl->CanIgnoreTObjectStreamer()) {
1932  // Skip the TObject base class data members.
1933  // FIXME: This prevents a user from ever
1934  // using these names themself!
1935  if (!strcmp(dname, "fBits")) {
1936  continue;
1937  }
1938  if (!strcmp(dname, "fUniqueID")) {
1939  continue;
1940  }
1941  }
1942  TDataType* dtype = dm->GetDataType();
1943  Int_t code = 0;
1944  if (dtype) {
1945  code = dm->GetDataType()->GetType();
1946  }
1947  // Encode branch name. Use real data member name
1948  branchname = rdname;
1949  if (isDot) {
1950  if (dm->IsaPointer()) {
1951  // FIXME: This is wrong! The asterisk is not usually in the front!
1952  branchname.Form("%s%s", name, &rdname[1]);
1953  } else {
1954  branchname.Form("%s%s", name, &rdname[0]);
1955  }
1956  }
1957  // FIXME: Change this to a string stream.
1958  TString leaflist;
1959  Int_t offset = rd->GetThisOffset();
1960  char* pointer = ((char*) obj) + offset;
1961  if (dm->IsaPointer()) {
1962  // We have a pointer to an object or a pointer to an array of basic types.
1963  TClass* clobj = 0;
1964  if (!dm->IsBasic()) {
1965  clobj = TClass::GetClass(dm->GetTypeName());
1966  }
1967  if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
1968  // We have a pointer to a clones array.
1969  char* cpointer = (char*) pointer;
1970  char** ppointer = (char**) cpointer;
1971  TClonesArray* li = (TClonesArray*) *ppointer;
1972  if (splitlevel != 2) {
1973  if (isDot) {
1974  branch1 = new TBranchClones(branch,branchname, pointer, bufsize);
1975  } else {
1976  // FIXME: This is wrong! The asterisk is not usually in the front!
1977  branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
1978  }
1979  blist->Add(branch1);
1980  } else {
1981  if (isDot) {
1982  branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
1983  } else {
1984  // FIXME: This is wrong! The asterisk is not usually in the front!
1985  branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
1986  }
1987  blist->Add(branch1);
1988  }
1989  } else if (clobj) {
1990  // We have a pointer to an object.
1991  //
1992  // It must be a TObject object.
1993  if (!clobj->IsTObject()) {
1994  continue;
1995  }
1996  branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
1997  if (isDot) {
1998  branch1->SetName(branchname);
1999  } else {
2000  // FIXME: This is wrong! The asterisk is not usually in the front!
2001  // Do not use the first character (*).
2002  branch1->SetName(&branchname.Data()[1]);
2003  }
2004  blist->Add(branch1);
2005  } else {
2006  // We have a pointer to an array of basic types.
2007  //
2008  // Check the comments in the text of the code for an index specification.
2009  const char* index = dm->GetArrayIndex();
2010  if (index[0]) {
2011  // We are a pointer to a varying length array of basic types.
2012  //check that index is a valid data member name
2013  //if member is part of an object (e.g. fA and index=fN)
2014  //index must be changed from fN to fA.fN
2015  TString aindex (rd->GetName());
2016  Ssiz_t rdot = aindex.Last('.');
2017  if (rdot>=0) {
2018  aindex.Remove(rdot+1);
2019  aindex.Append(index);
2020  }
2021  nexti.Reset();
2022  while ((rdi = (TRealData*) nexti())) {
2023  if (rdi->TestBit(TRealData::kTransient)) continue;
2024 
2025  if (!strcmp(rdi->GetName(), index)) {
2026  break;
2027  }
2028  if (!strcmp(rdi->GetName(), aindex)) {
2029  index = rdi->GetName();
2030  break;
2031  }
2032  }
2033 
2034  char vcode = DataTypeToChar((EDataType)code);
2035  // Note that we differentiate between strings and
2036  // char array by the fact that there is NO specified
2037  // size for a string (see next if (code == 1)
2038 
2039  if (vcode) {
2040  leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2041  } else {
2042  Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2043  leaflist = "";
2044  }
2045  } else {
2046  // We are possibly a character string.
2047  if (code == 1) {
2048  // We are a character string.
2049  leaflist.Form("%s/%s", dname, "C");
2050  } else {
2051  // Invalid array specification.
2052  // FIXME: We need an error message here.
2053  continue;
2054  }
2055  }
2056  // There are '*' in both the branchname and leaflist, remove them.
2057  TString bname( branchname );
2058  bname.ReplaceAll("*","");
2059  leaflist.ReplaceAll("*","");
2060  // Add the branch to the tree and indicate that the address
2061  // is that of a pointer to be dereferenced before using.
2062  branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2063  TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2065  leaf->SetAddress((void**) pointer);
2066  blist->Add(branch1);
2067  }
2068  } else if (dm->IsBasic()) {
2069  // We have a basic type.
2070 
2071  char vcode = DataTypeToChar((EDataType)code);
2072  if (vcode) {
2073  leaflist.Form("%s/%c", rdname, vcode);
2074  } else {
2075  Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2076  leaflist = "";
2077  }
2078  branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2079  branch1->SetTitle(rdname);
2080  blist->Add(branch1);
2081  } else {
2082  // We have a class type.
2083  // Note: This cannot happen due to the rd->IsObject() test above.
2084  // FIXME: Put an error message here just in case.
2085  }
2086  if (branch1) {
2087  branch1->SetOffset(offset);
2088  } else {
2089  Warning("BranchOld", "Cannot process member: '%s'", rdname);
2090  }
2091  }
2092  if (delobj) {
2093  delete obj;
2094  obj = 0;
2095  }
2096  return branch;
2097 }
2098 
2099 ////////////////////////////////////////////////////////////////////////////////
2100 /// Build the optional branch supporting the TRefTable.
2101 /// This branch will keep all the information to find the branches
2102 /// containing referenced objects.
2103 ///
2104 /// At each Tree::Fill, the branch numbers containing the
2105 /// referenced objects are saved to the TBranchRef basket.
2106 /// When the Tree header is saved (via TTree::Write), the branch
2107 /// is saved keeping the information with the pointers to the branches
2108 /// having referenced objects.
2109 
2112  if (!fBranchRef) {
2113  fBranchRef = new TBranchRef(this);
2114  }
2115  return fBranchRef;
2116 }
2117 
2118 ////////////////////////////////////////////////////////////////////////////////
2119 /// Create a new TTree BranchElement.
2120 ///
2121 /// ## WARNING about this new function
2122 ///
2123 /// This function is designed to replace the internal
2124 /// implementation of the old TTree::Branch (whose implementation
2125 /// has been moved to BranchOld).
2126 ///
2127 /// NOTE: The 'Bronch' method supports only one possible calls
2128 /// signature (where the object type has to be specified
2129 /// explicitly and the address must be the address of a pointer).
2130 /// For more flexibility use 'Branch'. Use Bronch only in (rare)
2131 /// cases (likely to be legacy cases) where both the new and old
2132 /// implementation of Branch needs to be used at the same time.
2133 ///
2134 /// This function is far more powerful than the old Branch
2135 /// function. It supports the full C++, including STL and has
2136 /// the same behaviour in split or non-split mode. classname does
2137 /// not have to derive from TObject. The function is based on
2138 /// the new TStreamerInfo.
2139 ///
2140 /// Build a TBranchElement for an object of class classname.
2141 ///
2142 /// addr is the address of a pointer to an object of class
2143 /// classname. The class dictionary must be available (ClassDef
2144 /// in class header).
2145 ///
2146 /// Note: See the comments in TBranchElement::SetAddress() for a more
2147 /// detailed discussion of the meaning of the addr parameter.
2148 ///
2149 /// This option requires access to the library where the
2150 /// corresponding class is defined. Accessing one single data
2151 /// member in the object implies reading the full object.
2152 ///
2153 /// By default the branch buffers are stored in the same file as the Tree.
2154 /// use TBranch::SetFile to specify a different file
2155 ///
2156 /// IMPORTANT NOTE about branch names:
2157 ///
2158 /// In case two or more master branches contain subbranches with
2159 /// identical names, one must add a "." (dot) character at the end
2160 /// of the master branch name. This will force the name of the subbranch
2161 /// to be master.subbranch instead of simply subbranch.
2162 /// This situation happens when the top level object (say event)
2163 /// has two or more members referencing the same class.
2164 /// For example, if a Tree has two branches B1 and B2 corresponding
2165 /// to objects of the same class MyClass, one can do:
2166 /// ~~~ {.cpp}
2167 /// tree.Branch("B1.","MyClass",&b1,8000,1);
2168 /// tree.Branch("B2.","MyClass",&b2,8000,1);
2169 /// ~~~
2170 /// if MyClass has 3 members a,b,c, the two instructions above will generate
2171 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2172 ///
2173 /// bufsize is the buffer size in bytes for this branch
2174 /// The default value is 32000 bytes and should be ok for most cases.
2175 /// You can specify a larger value (e.g. 256000) if your Tree is not split
2176 /// and each entry is large (Megabytes)
2177 /// A small value for bufsize is optimum if you intend to access
2178 /// the entries in the Tree randomly and your Tree is in split mode.
2179 ///
2180 /// Use splitlevel < 0 instead of splitlevel=0 when the class
2181 /// has a custom Streamer
2182 ///
2183 /// Note: if the split level is set to the default (99), TTree::Branch will
2184 /// not issue a warning if the class can not be split.
2185 
2186 TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2188  return BronchExec(name, classname, addr, kTRUE, bufsize, splitlevel);
2189 }
2190 
2191 ////////////////////////////////////////////////////////////////////////////////
2192 /// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2193 
2194 TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, Bool_t isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2196  TClass* cl = TClass::GetClass(classname);
2197  if (!cl) {
2198  Error("Bronch", "Cannot find class:%s", classname);
2199  return 0;
2200  }
2201 
2202  //if splitlevel <= 0 and class has a custom Streamer, we must create
2203  //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2204  //with the custom Streamer. The penalty is that one cannot process
2205  //this Tree without the class library containing the class.
2206 
2207  char* objptr = 0;
2208  if (!isptrptr) {
2209  objptr = (char*)addr;
2210  } else if (addr) {
2211  objptr = *((char**) addr);
2212  }
2213 
2214  if (cl == TClonesArray::Class()) {
2215  TClonesArray* clones = (TClonesArray*) objptr;
2216  if (!clones) {
2217  Error("Bronch", "Pointer to TClonesArray is null");
2218  return 0;
2219  }
2220  if (!clones->GetClass()) {
2221  Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2222  return 0;
2223  }
2224  if (!clones->GetClass()->HasDataMemberInfo()) {
2225  Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2226  return 0;
2227  }
2228  bool hasCustomStreamer = clones->GetClass()->TestBit(TClass::kHasCustomStreamerMember);
2229  if (splitlevel > 0) {
2230  if (hasCustomStreamer)
2231  Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2232  } else {
2233  if (hasCustomStreamer) clones->BypassStreamer(kFALSE);
2234  TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2235  fBranches.Add(branch);
2236  return branch;
2237  }
2238  }
2239 
2240  if (cl->GetCollectionProxy()) {
2241  TVirtualCollectionProxy* collProxy = cl->GetCollectionProxy();
2242  //if (!collProxy) {
2243  // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2244  //}
2245  TClass* inklass = collProxy->GetValueClass();
2246  if (!inklass && (collProxy->GetType() == 0)) {
2247  Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2248  return 0;
2249  }
2250  if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == 0)) {
2251  ROOT::ESTLType stl = cl->GetCollectionType();
2252  if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2253  if (!inklass->HasDataMemberInfo()) {
2254  Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2255  return 0;
2256  }
2257  if (inklass->TestBit(TClass::kHasCustomStreamerMember)) {
2258  Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2259  }
2260  }
2261  }
2262  //-------------------------------------------------------------------------
2263  // If the splitting switch is enabled, the split level is big enough and
2264  // the collection contains pointers we can split it
2265  //////////////////////////////////////////////////////////////////////////
2266 
2267  TBranch *branch;
2268  if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2269  branch = new TBranchSTL( this, name, collProxy, bufsize, splitlevel );
2270  else
2271  branch = new TBranchElement(this, name, collProxy, bufsize, splitlevel);
2272  fBranches.Add(branch);
2273  if (isptrptr) {
2274  branch->SetAddress(addr);
2275  } else {
2276  branch->SetObject(addr);
2277  }
2278  return branch;
2279  }
2280 
2281  Bool_t hasCustomStreamer = kFALSE;
2282  if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2283  Error("Bronch", "Cannot find dictionary for class: %s", classname);
2284  return 0;
2285  }
2286 
2288  // Not an STL container and the linkdef file had a "-" after the class name.
2289  hasCustomStreamer = kTRUE;
2290  }
2291 
2292  if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2293  TBranchObject* branch = new TBranchObject(this, name, classname, addr, bufsize, 0, /*compress=*/ -1, isptrptr);
2294  fBranches.Add(branch);
2295  return branch;
2296  }
2297 
2298  if (cl == TClonesArray::Class()) {
2299  // Special case of TClonesArray.
2300  // No dummy object is created.
2301  // The streamer info is not rebuilt unoptimized.
2302  // No dummy top-level branch is created.
2303  // No splitting is attempted.
2304  TBranchElement* branch = new TBranchElement(this, name, (TClonesArray*) objptr, bufsize, splitlevel%kSplitCollectionOfPointers);
2305  fBranches.Add(branch);
2306  if (isptrptr) {
2307  branch->SetAddress(addr);
2308  } else {
2309  branch->SetObject(addr);
2310  }
2311  return branch;
2312  }
2313 
2314  //
2315  // If we are not given an object to use as an i/o buffer
2316  // then create a temporary one which we will delete just
2317  // before returning.
2318  //
2319 
2320  Bool_t delobj = kFALSE;
2321 
2322  if (!objptr) {
2323  objptr = (char*) cl->New();
2324  delobj = kTRUE;
2325  }
2326 
2327  //
2328  // Avoid splitting unsplittable classes.
2329  //
2330 
2331  if ((splitlevel > 0) && !cl->CanSplit()) {
2332  if (splitlevel != 99) {
2333  Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2334  }
2335  splitlevel = 0;
2336  }
2337 
2338  //
2339  // Make sure the streamer info is built and fetch it.
2340  //
2341  // If we are splitting, then make sure the streamer info
2342  // is built unoptimized (data members are not combined).
2343  //
2344 
2345  TStreamerInfo* sinfo = BuildStreamerInfo(cl, objptr, splitlevel==0);
2346  if (!sinfo) {
2347  Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2348  return 0;
2349  }
2350 
2351  //
2352  // Do we have a final dot in our name?
2353  //
2354 
2355  // Note: The branch constructor which takes a folder as input
2356  // creates top-level branch names with dots in them to
2357  // indicate the folder hierarchy.
2358  char* dot = (char*) strchr(name, '.');
2359  Int_t nch = strlen(name);
2360  Bool_t dotlast = kFALSE;
2361  if (nch && (name[nch-1] == '.')) {
2362  dotlast = kTRUE;
2363  }
2364 
2365  //
2366  // Create a dummy top level branch object.
2367  //
2368 
2369  Int_t id = -1;
2370  if (splitlevel > 0) {
2371  id = -2;
2372  }
2373  TBranchElement* branch = new TBranchElement(this, name, sinfo, id, objptr, bufsize, splitlevel);
2374  fBranches.Add(branch);
2375 
2376  //
2377  // Do splitting, if requested.
2378  //
2379 
2380  if (splitlevel%kSplitCollectionOfPointers > 0) {
2381  // Loop on all public data members of the class and its base classes and create branches for each one.
2382  TObjArray* blist = branch->GetListOfBranches();
2383  TIter next(sinfo->GetElements());
2384  TStreamerElement* element = 0;
2385  TString bname;
2386  for (id = 0; (element = (TStreamerElement*) next()); ++id) {
2387  if (element->IsA() == TStreamerArtificial::Class()) {
2388  continue;
2389  }
2390  if (element->TestBit(TStreamerElement::kRepeat)) {
2391  continue;
2392  }
2393  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
2394  continue;
2395  }
2396  char* pointer = (char*) (objptr + element->GetOffset());
2397  // FIXME: This is not good enough, an STL container can be
2398  // a base, and the test will fail.
2399  // See TBranchElement::InitializeOffsets() for the
2400  // correct test.
2401  Bool_t isBase = (element->IsA() == TStreamerBase::Class());
2402  if (isBase) {
2403  TClass* clbase = element->GetClassPointer();
2404  if ((clbase == TObject::Class()) && cl->CanIgnoreTObjectStreamer()) {
2405  // Note: TStreamerInfo::Compile() leaves this element
2406  // out of the optimized info, although it does
2407  // exists in the non-compiled and non-optimized info.
2408  // FIXME: The test that TStreamerInfo::Compile() uses
2409  // is element->GetType() < 0, so that is what
2410  // we should do as well.
2411  continue;
2412  }
2413  if (clbase->GetListOfRealData()->GetSize() == 0) {
2414  // Do not create a branch for empty bases.
2415  continue;
2416  }
2417  }
2418  if (dot) {
2419  if (dotlast) {
2420  bname.Form("%s%s", name, element->GetFullName());
2421  } else {
2422  // FIXME: We are in the case where we have a top-level
2423  // branch name that was created by the branch
2424  // constructor which takes a folder as input.
2425  // The internal dots in the name are in place of
2426  // of the original slashes and represent the
2427  // folder hierarchy.
2428  if (isBase) {
2429  // FIXME: This is very strange, this is the only case where
2430  // we create a branch for a base class that does
2431  // not have the base class name in the branch name.
2432  // FIXME: This is also quite bad since classes with two
2433  // or more base classes end up with sub-branches
2434  // that have the same name.
2435  bname = name;
2436  } else {
2437  bname.Form("%s.%s", name, element->GetFullName());
2438  }
2439  }
2440  } else {
2441  // Note: For a base class element, this results in the branchname
2442  // being the name of the base class.
2443  bname.Form("%s", element->GetFullName());
2444  }
2445 
2446  if( splitlevel > kSplitCollectionOfPointers && element->GetClass() &&
2447  element->GetClass()->GetCollectionProxy() &&
2448  element->GetClass()->GetCollectionProxy()->HasPointers() )
2449  {
2450  TBranchSTL* brSTL = new TBranchSTL( branch, bname, element->GetClass()->GetCollectionProxy(), bufsize, splitlevel-1, sinfo, id );
2451  blist->Add(brSTL);
2452  }
2453  else
2454  {
2455  TBranchElement* bre = new TBranchElement(branch, bname, sinfo, id, pointer, bufsize, splitlevel - 1);
2456  bre->SetParentClass(cl);
2457  blist->Add(bre);
2458  }
2459  }
2460  }
2461 
2462  //
2463  // Setup our offsets into the user's i/o buffer.
2464  //
2465 
2466  if (isptrptr) {
2467  branch->SetAddress(addr);
2468  } else {
2469  branch->SetObject(addr);
2470  }
2471 
2472  if (delobj) {
2473  cl->Destructor(objptr);
2474  objptr = 0;
2475  }
2476 
2477  return branch;
2478 }
2479 
2480 ////////////////////////////////////////////////////////////////////////////////
2481 /// Browse content of the TTree.
2482 
2483 void TTree::Browse(TBrowser* b)
2485  fBranches.Browse(b);
2486  if (fUserInfo) {
2487  if (strcmp("TList",fUserInfo->GetName())==0) {
2488  fUserInfo->SetName("UserInfo");
2489  b->Add(fUserInfo);
2490  fUserInfo->SetName("TList");
2491  } else {
2492  b->Add(fUserInfo);
2493  }
2494  }
2495 }
2496 
2497 ////////////////////////////////////////////////////////////////////////////////
2498 /// Build a Tree Index (default is TTreeIndex).
2499 /// See a description of the parameters and functionality in
2500 /// TTreeIndex::TTreeIndex().
2501 ///
2502 /// The return value is the number of entries in the Index (< 0 indicates failure).
2503 ///
2504 /// A TTreeIndex object pointed by fTreeIndex is created.
2505 /// This object will be automatically deleted by the TTree destructor.
2506 /// See also comments in TTree::SetTreeIndex().
2507 
2508 Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2510  fTreeIndex = GetPlayer()->BuildIndex(this, majorname, minorname);
2511  if (fTreeIndex->IsZombie()) {
2512  delete fTreeIndex;
2513  fTreeIndex = 0;
2514  return 0;
2515  }
2516  return fTreeIndex->GetN();
2517 }
2518 
2519 ////////////////////////////////////////////////////////////////////////////////
2520 /// Build StreamerInfo for class cl.
2521 /// pointer is an optional argument that may contain a pointer to an object of cl.
2522 
2523 TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, Bool_t canOptimize /* = kTRUE */ )
2525  if (!cl) {
2526  return 0;
2527  }
2528  cl->BuildRealData(pointer);
2530 
2531  // Create StreamerInfo for all base classes.
2532  TBaseClass* base = 0;
2533  TIter nextb(cl->GetListOfBases());
2534  while((base = (TBaseClass*) nextb())) {
2535  if (base->IsSTLContainer()) {
2536  continue;
2537  }
2538  TClass* clm = TClass::GetClass(base->GetName());
2539  BuildStreamerInfo(clm, pointer, canOptimize);
2540  }
2541  if (sinfo && fDirectory) {
2542  sinfo->ForceWriteInfo(fDirectory->GetFile());
2543  }
2544  return sinfo;
2545 }
2546 
2547 ////////////////////////////////////////////////////////////////////////////////
2548 /// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2549 /// Create a new file. If the original file is named "myfile.root",
2550 /// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2551 ///
2552 /// Returns a pointer to the new file.
2553 ///
2554 /// Currently, the automatic change of file is restricted
2555 /// to the case where the tree is in the top level directory.
2556 /// The file should not contain sub-directories.
2557 ///
2558 /// Before switching to a new file, the tree header is written
2559 /// to the current file, then the current file is closed.
2560 ///
2561 /// To process the multiple files created by ChangeFile, one must use
2562 /// a TChain.
2563 ///
2564 /// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2565 /// By default a Root session starts with fFileNumber=0. One can set
2566 /// fFileNumber to a different value via TTree::SetFileNumber.
2567 /// In case a file named "_N" already exists, the function will try
2568 /// a file named "__N", then "___N", etc.
2569 ///
2570 /// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2571 /// The default value of fgMaxTreeSize is 100 Gigabytes.
2572 ///
2573 /// If the current file contains other objects like TH1 and TTree,
2574 /// these objects are automatically moved to the new file.
2575 ///
2576 /// IMPORTANT NOTE:
2577 ///
2578 /// Be careful when writing the final Tree header to the file!
2579 ///
2580 /// Don't do:
2581 /// ~~~ {.cpp}
2582 /// TFile *file = new TFile("myfile.root","recreate");
2583 /// TTree *T = new TTree("T","title");
2584 /// T->Fill(); //loop
2585 /// file->Write();
2586 /// file->Close();
2587 ///~~~
2588 /// but do the following:
2589 ///~~~ {.cpp}
2590 /// TFile *file = new TFile("myfile.root","recreate");
2591 /// TTree *T = new TTree("T","title");
2592 /// T->Fill(); //loop
2593 /// file = T->GetCurrentFile(); //to get the pointer to the current file
2594 /// file->Write();
2595 /// file->Close();
2596 /// ~~~
2597 
2600  file->cd();
2601  Write();
2602  Reset();
2603  char* fname = new char[2000];
2604  ++fFileNumber;
2605  char uscore[10];
2606  for (Int_t i = 0; i < 10; ++i) {
2607  uscore[i] = 0;
2608  }
2609  Int_t nus = 0;
2610  // Try to find a suitable file name that does not already exist.
2611  while (nus < 10) {
2612  uscore[nus] = '_';
2613  fname[0] = 0;
2614  strlcpy(fname, file->GetName(),2000);
2615 
2616  if (fFileNumber > 1) {
2617  char* cunder = strrchr(fname, '_');
2618  if (cunder) {
2619  snprintf(cunder,2000-Int_t(cunder-fname), "%s%d", uscore, fFileNumber);
2620  const char* cdot = strrchr(file->GetName(), '.');
2621  if (cdot) {
2622  strlcat(fname, cdot,2000);
2623  }
2624  } else {
2625  char fcount[10];
2626  snprintf(fcount,10, "%s%d", uscore, fFileNumber);
2627  strlcat(fname, fcount,2000);
2628  }
2629  } else {
2630  char* cdot = strrchr(fname, '.');
2631  if (cdot) {
2632  snprintf(cdot,2000-Int_t(fname-cdot), "%s%d", uscore, fFileNumber);
2633  strlcat(fname, strrchr(file->GetName(), '.'),2000);
2634  } else {
2635  char fcount[10];
2636  snprintf(fcount,10, "%s%d", uscore, fFileNumber);
2637  strlcat(fname, fcount,2000);
2638  }
2639  }
2640  if (gSystem->AccessPathName(fname)) {
2641  break;
2642  }
2643  ++nus;
2644  Warning("ChangeFile", "file %s already exist, trying with %d underscores", fname, nus+1);
2645  }
2646  Int_t compress = file->GetCompressionSettings();
2647  TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2648  if (newfile == 0) {
2649  Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2650  } else {
2651  Printf("Fill: Switching to new file: %s", fname);
2652  }
2653  // The current directory may contain histograms and trees.
2654  // These objects must be moved to the new file.
2655  TBranch* branch = 0;
2656  TObject* obj = 0;
2657  while ((obj = file->GetList()->First())) {
2658  file->Remove(obj);
2659  // Histogram: just change the directory.
2660  if (obj->InheritsFrom("TH1")) {
2661  gROOT->ProcessLine(TString::Format("((%s*)0x%lx)->SetDirectory((TDirectory*)0x%lx);", obj->ClassName(), (Long_t) obj, (Long_t) newfile));
2662  continue;
2663  }
2664  // Tree: must save all trees in the old file, reset them.
2665  if (obj->InheritsFrom(TTree::Class())) {
2666  TTree* t = (TTree*) obj;
2667  if (t != this) {
2668  t->AutoSave();
2669  t->Reset();
2670  t->fFileNumber = fFileNumber;
2671  }
2672  t->SetDirectory(newfile);
2673  TIter nextb(t->GetListOfBranches());
2674  while ((branch = (TBranch*)nextb())) {
2675  branch->SetFile(newfile);
2676  }
2677  if (t->GetBranchRef()) {
2678  t->GetBranchRef()->SetFile(newfile);
2679  }
2680  continue;
2681  }
2682  // Not a TH1 or a TTree, move object to new file.
2683  if (newfile) newfile->Append(obj);
2684  file->Remove(obj);
2685  }
2686  delete file;
2687  file = 0;
2688  delete[] fname;
2689  fname = 0;
2690  return newfile;
2691 }
2692 
2693 ////////////////////////////////////////////////////////////////////////////////
2694 /// Check whether or not the address described by the last 3 parameters
2695 /// matches the content of the branch. If a Data Model Evolution conversion
2696 /// is involved, reset the fInfo of the branch.
2697 /// The return values are:
2698 //
2699 /// - kMissingBranch (-5) : Missing branch
2700 /// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2701 /// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2702 /// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2703 /// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2704 /// - kMatch (0) : perfect match
2705 /// - kMatchConversion (1) : match with (I/O) conversion
2706 /// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2707 /// - kMakeClass (3) : MakeClass mode so we can not check.
2708 /// - kVoidPtr (4) : void* passed so no check was made.
2709 /// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2710 
2711 Int_t TTree::CheckBranchAddressType(TBranch* branch, TClass* ptrClass, EDataType datatype, Bool_t isptr)
2713  if (GetMakeClass()) {
2714  // If we are in MakeClass mode so we do not really use classes.
2715  return kMakeClass;
2716  }
2717 
2718  // Let's determine what we need!
2719  TClass* expectedClass = 0;
2720  EDataType expectedType = kOther_t;
2721  if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2722  // Something went wrong, the warning message has already be issued.
2723  return kInternalError;
2724  }
2725  if (expectedClass && datatype == kOther_t && ptrClass == 0) {
2726  if (branch->InheritsFrom( TBranchElement::Class() )) {
2727  TBranchElement* bEl = (TBranchElement*)branch;
2728  bEl->SetTargetClass( expectedClass->GetName() );
2729  }
2730  if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2731  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2732  "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2733  "Please generate the dictionary for this class (%s)",
2734  branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2736  }
2737  if (!expectedClass->IsLoaded()) {
2738  // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2739  // (we really don't know). So let's express that.
2740  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2741  "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."
2742  "Please generate the dictionary for this class (%s)",
2743  branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2744  } else {
2745  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2746  "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2747  }
2748  return kClassMismatch;
2749  }
2750  if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2751  // Top Level branch
2752  if (!isptr) {
2753  Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2754  }
2755  }
2756  if (expectedType == kFloat16_t) {
2757  expectedType = kFloat_t;
2758  }
2759  if (expectedType == kDouble32_t) {
2760  expectedType = kDouble_t;
2761  }
2762  if (datatype == kFloat16_t) {
2763  datatype = kFloat_t;
2764  }
2765  if (datatype == kDouble32_t) {
2766  datatype = kDouble_t;
2767  }
2768 
2769  /////////////////////////////////////////////////////////////////////////////
2770  // Deal with the class renaming
2771  /////////////////////////////////////////////////////////////////////////////
2772 
2773  if( expectedClass && ptrClass &&
2774  expectedClass != ptrClass &&
2775  branch->InheritsFrom( TBranchElement::Class() ) &&
2776  ptrClass->GetSchemaRules() &&
2777  ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2778  TBranchElement* bEl = (TBranchElement*)branch;
2779 
2780  if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2781  if (gDebug > 7)
2782  Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2783  "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2784 
2785  bEl->SetTargetClass( ptrClass->GetName() );
2786  return kMatchConversion;
2787 
2788  } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2789  !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2790  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());
2791 
2792  bEl->SetTargetClass( expectedClass->GetName() );
2793  return kClassMismatch;
2794  }
2795  else {
2796 
2797  bEl->SetTargetClass( ptrClass->GetName() );
2798  return kMatchConversion;
2799  }
2800 
2801  } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2802 
2803  if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2804  branch->InheritsFrom( TBranchElement::Class() ) &&
2805  expectedClass->GetCollectionProxy()->GetValueClass() &&
2806  ptrClass->GetCollectionProxy()->GetValueClass() )
2807  {
2808  // In case of collection, we know how to convert them, if we know how to convert their content.
2809  // NOTE: we need to extend this to std::pair ...
2810 
2811  TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2812  TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2813 
2814  if (inmemValueClass->GetSchemaRules() &&
2815  inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2816  {
2817  TBranchElement* bEl = (TBranchElement*)branch;
2818  bEl->SetTargetClass( ptrClass->GetName() );
2820  }
2821  }
2822 
2823  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());
2824  if (branch->InheritsFrom( TBranchElement::Class() )) {
2825  TBranchElement* bEl = (TBranchElement*)branch;
2826  bEl->SetTargetClass( expectedClass->GetName() );
2827  }
2828  return kClassMismatch;
2829 
2830  } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2831  if (datatype != kChar_t) {
2832  // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2833  Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2834  TDataType::GetTypeName(datatype), datatype, TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2835  return kMismatch;
2836  }
2837  } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2838  (ptrClass && (expectedType != kOther_t && expectedType != kNoType_t && datatype != kInt_t)) ) {
2839  // Sometime a null pointer can look an int, avoid complaining in that case.
2840  if (expectedClass) {
2841  Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
2842  TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
2843  if (branch->InheritsFrom( TBranchElement::Class() )) {
2844  TBranchElement* bEl = (TBranchElement*)branch;
2845  bEl->SetTargetClass( expectedClass->GetName() );
2846  }
2847  } else {
2848  // 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
2849  // a struct).
2850  bool good = false;
2851  if (ptrClass->IsLoaded()) {
2852  TIter next(ptrClass->GetListOfRealData());
2853  TRealData *rdm;
2854  while ((rdm = (TRealData*)next())) {
2855  if (rdm->GetThisOffset() == 0) {
2856  break;
2857  }
2858  }
2859  } else {
2860  TIter next(ptrClass->GetListOfDataMembers());
2861  TDataMember *dm;
2862  while ((dm = (TDataMember*)next())) {
2863  if (dm->GetOffset() == 0) {
2864  TDataType *dmtype = dm->GetDataType();
2865  if (dmtype) {
2866  EDataType etype = (EDataType)dmtype->GetType();
2867  good = (etype == expectedType);
2868  }
2869  break;
2870  }
2871  }
2872  }
2873  if (!good) {
2874  Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2875  ptrClass->GetName(), TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2876  }
2877  }
2878  return kMismatch;
2879  }
2880  if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2881  Error("SetBranchAddress", writeStlWithoutProxyMsg,
2882  expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
2883  if (branch->InheritsFrom( TBranchElement::Class() )) {
2884  TBranchElement* bEl = (TBranchElement*)branch;
2885  bEl->SetTargetClass( expectedClass->GetName() );
2886  }
2888  }
2889  if (expectedClass && branch->InheritsFrom( TBranchElement::Class() )) {
2890  TBranchElement* bEl = (TBranchElement*)branch;
2891  bEl->SetTargetClass( expectedClass->GetName() );
2892  }
2893  return kMatch;
2894 }
2895 
2896 ////////////////////////////////////////////////////////////////////////////////
2897 /// Create a clone of this tree and copy nentries.
2898 ///
2899 /// By default copy all entries.
2900 /// The compression level of the cloned tree is set to the destination
2901 /// file's compression level.
2902 ///
2903 /// NOTE: Only active branches are copied.
2904 /// NOTE: If the TTree is a TChain, the structure of the first TTree
2905 /// is used for the copy.
2906 ///
2907 /// IMPORTANT: The cloned tree stays connected with this tree until
2908 /// this tree is deleted. In particular, any changes in
2909 /// branch addresses in this tree are forwarded to the
2910 /// clone trees, unless a branch in a clone tree has had
2911 /// its address changed, in which case that change stays in
2912 /// effect. When this tree is deleted, all the addresses of
2913 /// the cloned tree are reset to their default values.
2914 ///
2915 /// If 'option' contains the word 'fast' and nentries is -1, the
2916 /// cloning will be done without unzipping or unstreaming the baskets
2917 /// (i.e., a direct copy of the raw bytes on disk).
2918 ///
2919 /// When 'fast' is specified, 'option' can also contain a sorting
2920 /// order for the baskets in the output file.
2921 ///
2922 /// There are currently 3 supported sorting order:
2923 ///
2924 /// - SortBasketsByOffset (the default)
2925 /// - SortBasketsByBranch
2926 /// - SortBasketsByEntry
2927 ///
2928 /// When using SortBasketsByOffset the baskets are written in the
2929 /// output file in the same order as in the original file (i.e. the
2930 /// baskets are sorted by their offset in the original file; Usually
2931 /// this also means that the baskets are sorted by the index/number of
2932 /// the _last_ entry they contain)
2933 ///
2934 /// When using SortBasketsByBranch all the baskets of each individual
2935 /// branches are stored contiguously. This tends to optimize reading
2936 /// speed when reading a small number (1->5) of branches, since all
2937 /// their baskets will be clustered together instead of being spread
2938 /// across the file. However it might decrease the performance when
2939 /// reading more branches (or the full entry).
2940 ///
2941 /// When using SortBasketsByEntry the baskets with the lowest starting
2942 /// entry are written first. (i.e. the baskets are sorted by the
2943 /// index/number of the first entry they contain). This means that on
2944 /// the file the baskets will be in the order in which they will be
2945 /// needed when reading the whole tree sequentially.
2946 ///
2947 /// For examples of CloneTree, see tutorials:
2948 ///
2949 /// - copytree:
2950 /// A macro to copy a subset of a TTree to a new TTree.
2951 /// The input file has been generated by the program in
2952 /// $ROOTSYS/test/Event with: Event 1000 1 1 1
2953 ///
2954 /// - copytree2:
2955 /// A macro to copy a subset of a TTree to a new TTree.
2956 /// One branch of the new Tree is written to a separate file.
2957 /// The input file has been generated by the program in
2958 /// $ROOTSYS/test/Event with: Event 1000 1 1 1
2959 
2960 TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
2962  // Options
2963  Bool_t fastClone = kFALSE;
2964 
2965  TString opt = option;
2966  opt.ToLower();
2967  if (opt.Contains("fast")) {
2968  fastClone = kTRUE;
2969  }
2970 
2971  // If we are a chain, switch to the first tree.
2972  if ((fEntries > 0) && (LoadTree(0) < 0)) {
2973  // FIXME: We need an error message here.
2974  return 0;
2975  }
2976 
2977  // Note: For a tree we get the this pointer, for
2978  // a chain we get the chain's current tree.
2979  TTree* thistree = GetTree();
2980 
2981  // Note: For a chain, the returned clone will be
2982  // a clone of the chain's first tree.
2983  TTree* newtree = (TTree*) thistree->Clone();
2984  if (!newtree) {
2985  return 0;
2986  }
2987 
2988  // The clone should not delete any objects allocated by SetAddress().
2989  TObjArray* branches = newtree->GetListOfBranches();
2990  Int_t nb = branches->GetEntriesFast();
2991  for (Int_t i = 0; i < nb; ++i) {
2992  TBranch* br = (TBranch*) branches->UncheckedAt(i);
2993  if (br->InheritsFrom(TBranchElement::Class())) {
2994  ((TBranchElement*) br)->ResetDeleteObject();
2995  }
2996  }
2997 
2998  // Add the new tree to the list of clones so that
2999  // we can later inform it of changes to branch addresses.
3000  thistree->AddClone(newtree);
3001  if (thistree != this) {
3002  // In case this object is a TChain, add the clone
3003  // also to the TChain's list of clones.
3004  AddClone(newtree);
3005  }
3006 
3007  newtree->Reset();
3008 
3009  TDirectory* ndir = newtree->GetDirectory();
3010  TFile* nfile = 0;
3011  if (ndir) {
3012  nfile = ndir->GetFile();
3013  }
3014  Int_t newcomp = -1;
3015  if (nfile) {
3016  newcomp = nfile->GetCompressionSettings();
3017  }
3018 
3019  //
3020  // Delete non-active branches from the clone.
3021  //
3022  // Note: If we are a chain, this does nothing
3023  // since chains have no leaves.
3024  TObjArray* leaves = newtree->GetListOfLeaves();
3025  Int_t nleaves = leaves->GetEntriesFast();
3026  for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3027  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3028  if (!leaf) {
3029  continue;
3030  }
3031  TBranch* branch = leaf->GetBranch();
3032  if (branch && (newcomp > -1)) {
3033  branch->SetCompressionSettings(newcomp);
3034  }
3035  if (!branch || !branch->TestBit(kDoNotProcess)) {
3036  continue;
3037  }
3038  // size might change at each iteration of the loop over the leaves.
3039  nb = branches->GetEntriesFast();
3040  for (Long64_t i = 0; i < nb; ++i) {
3041  TBranch* br = (TBranch*) branches->UncheckedAt(i);
3042  if (br == branch) {
3043  branches->RemoveAt(i);
3044  delete br;
3045  br = 0;
3046  branches->Compress();
3047  break;
3048  }
3049  TObjArray* lb = br->GetListOfBranches();
3050  Int_t nb1 = lb->GetEntriesFast();
3051  for (Int_t j = 0; j < nb1; ++j) {
3052  TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3053  if (!b1) {
3054  continue;
3055  }
3056  if (b1 == branch) {
3057  lb->RemoveAt(j);
3058  delete b1;
3059  b1 = 0;
3060  lb->Compress();
3061  break;
3062  }
3063  TObjArray* lb1 = b1->GetListOfBranches();
3064  Int_t nb2 = lb1->GetEntriesFast();
3065  for (Int_t k = 0; k < nb2; ++k) {
3066  TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3067  if (!b2) {
3068  continue;
3069  }
3070  if (b2 == branch) {
3071  lb1->RemoveAt(k);
3072  delete b2;
3073  b2 = 0;
3074  lb1->Compress();
3075  break;
3076  }
3077  }
3078  }
3079  }
3080  }
3081  leaves->Compress();
3082 
3083  // Copy MakeClass status.
3084  newtree->SetMakeClass(fMakeClass);
3085 
3086  // Copy branch addresses.
3087  CopyAddresses(newtree);
3088 
3089  //
3090  // Copy entries if requested.
3091  //
3092 
3093  if (nentries != 0) {
3094  if (fastClone && (nentries < 0)) {
3095  if ( newtree->CopyEntries( this, -1, option ) < 0 ) {
3096  // There was a problem!
3097  Error("CloneTTree", "TTree has not been cloned\n");
3098  delete newtree;
3099  newtree = 0;
3100  return 0;
3101  }
3102  } else {
3103  newtree->CopyEntries( this, nentries, option );
3104  }
3105  }
3106 
3107  return newtree;
3108 }
3109 
3110 ////////////////////////////////////////////////////////////////////////////////
3111 /// Set branch addresses of passed tree equal to ours.
3112 /// If undo is true, reset the branch address instead of copying them.
3113 /// This insures 'separation' of a cloned tree from its original
3114 
3115 void TTree::CopyAddresses(TTree* tree, Bool_t undo)
3117  // Copy branch addresses starting from branches.
3118  TObjArray* branches = GetListOfBranches();
3119  Int_t nbranches = branches->GetEntriesFast();
3120  for (Int_t i = 0; i < nbranches; ++i) {
3121  TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3122  if (branch->TestBit(kDoNotProcess)) {
3123  continue;
3124  }
3125  if (undo) {
3126  TBranch* br = tree->GetBranch(branch->GetName());
3127  tree->ResetBranchAddress(br);
3128  } else {
3129  char* addr = branch->GetAddress();
3130  if (!addr) {
3131  if (branch->IsA() == TBranch::Class()) {
3132  // If the branch was created using a leaflist, the branch itself may not have
3133  // an address but the leaf might already.
3134  TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3135  if (!firstleaf || firstleaf->GetValuePointer()) {
3136  // Either there is no leaf (and thus no point in copying the address)
3137  // or the leaf has an address but we can not copy it via the branche
3138  // this will be copied via the next loop (over the leaf).
3139  continue;
3140  }
3141  }
3142  // Note: This may cause an object to be allocated.
3143  branch->SetAddress(0);
3144  addr = branch->GetAddress();
3145  }
3146  // FIXME: The GetBranch() function is braindead and may
3147  // not find the branch!
3148  TBranch* br = tree->GetBranch(branch->GetName());
3149  if (br) {
3150  br->SetAddress(addr);
3151  // The copy does not own any object allocated by SetAddress().
3152  if (br->InheritsFrom(TBranchElement::Class())) {
3153  ((TBranchElement*) br)->ResetDeleteObject();
3154  }
3155  } else {
3156  Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3157  }
3158  }
3159  }
3160 
3161  // Copy branch addresses starting from leaves.
3162  TObjArray* tleaves = tree->GetListOfLeaves();
3163  Int_t ntleaves = tleaves->GetEntriesFast();
3164  for (Int_t i = 0; i < ntleaves; ++i) {
3165  TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3166  TBranch* tbranch = tleaf->GetBranch();
3167  TBranch* branch = GetBranch(tbranch->GetName());
3168  if (!branch) {
3169  continue;
3170  }
3171  TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3172  if (!leaf) {
3173  continue;
3174  }
3175  if (branch->TestBit(kDoNotProcess)) {
3176  continue;
3177  }
3178  if (undo) {
3179  // Now we know whether the address has been transfered
3180  tree->ResetBranchAddress(tbranch);
3181  } else {
3182  if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3183  // We should attempts to set the address of the branch.
3184  // something like:
3185  //(TBranchElement*)branch->GetMother()->SetAddress(0)
3186  //plus a few more subtilities (see TBranchElement::GetEntry).
3187  //but for now we go the simplest route:
3188  //
3189  // Note: This may result in the allocation of an object.
3190  branch->SetupAddresses();
3191  }
3192  if (branch->GetAddress()) {
3193  tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3194  TBranch* br = tree->GetBranch(branch->GetName());
3195  if (br) {
3196  // The copy does not own any object allocated by SetAddress().
3197  // FIXME: We do too much here, br may not be a top-level branch.
3198  if (br->InheritsFrom(TBranchElement::Class())) {
3199  ((TBranchElement*) br)->ResetDeleteObject();
3200  }
3201  } else {
3202  Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3203  }
3204  } else {
3205  tleaf->SetAddress(leaf->GetValuePointer());
3206  }
3207  }
3208  }
3209 
3210  if (undo &&
3211  ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3212  ) {
3213  tree->ResetBranchAddresses();
3214  }
3215 }
3216 
3217 namespace {
3218 
3219  enum EOnIndexError { kDrop, kKeep, kBuild };
3221  static Bool_t R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3222  {
3223  // Return true if we should continue to handle indices, false otherwise.
3224 
3225  Bool_t withIndex = kTRUE;
3226 
3227  if ( newtree->GetTreeIndex() ) {
3228  if ( oldtree->GetTree()->GetTreeIndex() == 0 ) {
3229  switch (onIndexError) {
3230  case kDrop:
3231  delete newtree->GetTreeIndex();
3232  newtree->SetTreeIndex(0);
3233  withIndex = kFALSE;
3234  break;
3235  case kKeep:
3236  // Nothing to do really.
3237  break;
3238  case kBuild:
3239  // Build the index then copy it
3240  if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3241  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3242  // Clean up
3243  delete oldtree->GetTree()->GetTreeIndex();
3244  oldtree->GetTree()->SetTreeIndex(0);
3245  }
3246  break;
3247  }
3248  } else {
3249  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3250  }
3251  } else if ( oldtree->GetTree()->GetTreeIndex() != 0 ) {
3252  // We discover the first index in the middle of the chain.
3253  switch (onIndexError) {
3254  case kDrop:
3255  // Nothing to do really.
3256  break;
3257  case kKeep: {
3258  TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3259  index->SetTree(newtree);
3260  newtree->SetTreeIndex(index);
3261  break;
3262  }
3263  case kBuild:
3264  if (newtree->GetEntries() == 0) {
3265  // Start an index.
3266  TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3267  index->SetTree(newtree);
3268  newtree->SetTreeIndex(index);
3269  } else {
3270  // Build the index so far.
3271  if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3272  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3273  }
3274  }
3275  break;
3276  }
3277  } else if ( onIndexError == kDrop ) {
3278  // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3279  // index
3280  withIndex = kFALSE;
3281  }
3282  return withIndex;
3283  }
3284 }
3285 
3286 ////////////////////////////////////////////////////////////////////////////////
3287 /// Copy nentries from given tree to this tree.
3288 /// This routines assumes that the branches that intended to be copied are
3289 /// already connected. The typical case is that this tree was created using
3290 /// tree->CloneTree(0).
3291 ///
3292 /// By default copy all entries.
3293 ///
3294 /// Returns number of bytes copied to this tree.
3295 ///
3296 /// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3297 /// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3298 /// raw bytes on disk).
3299 ///
3300 /// When 'fast' is specified, 'option' can also contains a sorting order for the
3301 /// baskets in the output file.
3302 ///
3303 /// There are currently 3 supported sorting order:
3304 ///
3305 /// - SortBasketsByOffset (the default)
3306 /// - SortBasketsByBranch
3307 /// - SortBasketsByEntry
3308 ///
3309 /// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3310 ///
3311 /// If the tree or any of the underlying tree of the chain has an index, that index and any
3312 /// index in the subsequent underlying TTree objects will be merged.
3313 ///
3314 /// There are currently three 'options' to control this merging:
3315 /// - NoIndex : all the TTreeIndex object are dropped.
3316 /// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3317 /// they are all dropped.
3318 /// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3319 /// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3320 /// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3321 
3322 Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3324  if (!tree) {
3325  return 0;
3326  }
3327  // Options
3328  TString opt = option;
3329  opt.ToLower();
3330  Bool_t fastClone = opt.Contains("fast");
3331  Bool_t withIndex = !opt.Contains("noindex");
3332  EOnIndexError onIndexError;
3333  if (opt.Contains("asisindex")) {
3334  onIndexError = kKeep;
3335  } else if (opt.Contains("buildindex")) {
3336  onIndexError = kBuild;
3337  } else if (opt.Contains("dropindex")) {
3338  onIndexError = kDrop;
3339  } else {
3340  onIndexError = kBuild;
3341  }
3342  Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3343  Int_t cacheSize = -1;
3344  if (cacheSizeLoc != TString::kNPOS) {
3345  // If the parse faile, cacheSize stays at -1.
3346  Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3347  TSubString cacheSizeStr( opt(cacheSizeLoc+10,cacheSizeEnd) );
3348  auto parseResult = ROOT::FromHumanReadableSize(cacheSizeStr,cacheSize);
3349  if (parseResult == ROOT::EFromHumanReadableSize::kParseFail) {
3350  Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3351  } else if (parseResult == ROOT::EFromHumanReadableSize::kOverflow) {
3352  double m;
3353  const char *munit = nullptr;
3354  ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3355 
3356  Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3357  }
3358  }
3359  if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %d\n",cacheSize);
3360 
3361  Long64_t nbytes = 0;
3362  Long64_t treeEntries = tree->GetEntriesFast();
3363  if (nentries < 0) {
3364  nentries = treeEntries;
3365  } else if (nentries > treeEntries) {
3366  nentries = treeEntries;
3367  }
3368 
3369  if (fastClone && (nentries < 0 || nentries == tree->GetEntriesFast())) {
3370  // Quickly copy the basket without decompression and streaming.
3371  Long64_t totbytes = GetTotBytes();
3372  for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3373  if (tree->LoadTree(i) < 0) {
3374  break;
3375  }
3376  if ( withIndex ) {
3377  withIndex = R__HandleIndex( onIndexError, this, tree );
3378  }
3379  if (this->GetDirectory()) {
3380  TFile* file2 = this->GetDirectory()->GetFile();
3381  if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3382  if (this->GetDirectory() == (TDirectory*) file2) {
3383  this->ChangeFile(file2);
3384  }
3385  }
3386  }
3387  TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3388  if (cloner.IsValid()) {
3389  this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3390  if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3391  cloner.Exec();
3392  } else {
3393  if (i == 0) {
3394  Warning("CopyEntries","%s",cloner.GetWarning());
3395  // If the first cloning does not work, something is really wrong
3396  // (since apriori the source and target are exactly the same structure!)
3397  return -1;
3398  } else {
3399  if (cloner.NeedConversion()) {
3400  TTree *localtree = tree->GetTree();
3401  Long64_t tentries = localtree->GetEntries();
3402  for (Long64_t ii = 0; ii < tentries; ii++) {
3403  if (localtree->GetEntry(ii) <= 0) {
3404  break;
3405  }
3406  this->Fill();
3407  }
3408  if (this->GetTreeIndex()) {
3409  this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), kTRUE);
3410  }
3411  } else {
3412  Warning("CopyEntries","%s",cloner.GetWarning());
3413  if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3414  Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3415  } else {
3416  Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3417  }
3418  }
3419  }
3420  }
3421 
3422  }
3423  if (this->GetTreeIndex()) {
3424  this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3425  }
3426  nbytes = GetTotBytes() - totbytes;
3427  } else {
3428  if (nentries < 0) {
3429  nentries = treeEntries;
3430  } else if (nentries > treeEntries) {
3431  nentries = treeEntries;
3432  }
3433  Int_t treenumber = -1;
3434  for (Long64_t i = 0; i < nentries; i++) {
3435  if (tree->LoadTree(i) < 0) {
3436  break;
3437  }
3438  if (treenumber != tree->GetTreeNumber()) {
3439  if ( withIndex ) {
3440  withIndex = R__HandleIndex( onIndexError, this, tree );
3441  }
3442  treenumber = tree->GetTreeNumber();
3443  }
3444  if (tree->GetEntry(i) <= 0) {
3445  break;
3446  }
3447  nbytes += this->Fill();
3448  }
3449  if (this->GetTreeIndex()) {
3450  this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3451  }
3452  }
3453  return nbytes;
3454 }
3455 
3456 ////////////////////////////////////////////////////////////////////////////////
3457 /// Copy a tree with selection.
3458 ///
3459 /// IMPORTANT:
3460 ///
3461 /// The returned copied tree stays connected with the original tree
3462 /// until the original tree is deleted. In particular, any changes
3463 /// to the branch addresses in the original tree are also made to
3464 /// the copied tree. Any changes made to the branch addresses of the
3465 /// copied tree are overridden anytime the original tree changes its
3466 /// branch addresses. When the original tree is deleted, all the
3467 /// branch addresses of the copied tree are set to zero.
3468 ///
3469 /// For examples of CopyTree, see the tutorials:
3470 ///
3471 /// - copytree:
3472 /// Example macro to copy a subset of a tree to a new tree.
3473 /// The input file was generated by running the program in
3474 /// $ROOTSYS/test/Event in this way:
3475 /// ~~~ {.cpp}
3476 /// ./Event 1000 1 1 1
3477 /// ~~~
3478 /// - copytree2
3479 /// Example macro to copy a subset of a tree to a new tree.
3480 /// One branch of the new tree is written to a separate file.
3481 /// The input file was generated by running the program in
3482 /// $ROOTSYS/test/Event in this way:
3483 /// ~~~ {.cpp}
3484 /// ./Event 1000 1 1 1
3485 /// ~~~
3486 /// - copytree3
3487 /// Example macro to copy a subset of a tree to a new tree.
3488 /// Only selected entries are copied to the new tree.
3489 /// NOTE that only the active branches are copied.
3490 
3491 TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3493  GetPlayer();
3494  if (fPlayer) {
3495  return fPlayer->CopyTree(selection, option, nentries, firstentry);
3496  }
3497  return 0;
3498 }
3499 
3500 ////////////////////////////////////////////////////////////////////////////////
3501 /// Create a basket for this tree and given branch.
3502 
3505  if (!branch) {
3506  return 0;
3507  }
3508  return new TBasket(branch->GetName(), GetName(), branch);
3509 }
3510 
3511 ////////////////////////////////////////////////////////////////////////////////
3512 /// Delete this tree from memory or/and disk.
3513 ///
3514 /// - if option == "all" delete Tree object from memory AND from disk
3515 /// all baskets on disk are deleted. All keys with same name
3516 /// are deleted.
3517 /// - if option =="" only Tree object in memory is deleted.
3518 
3519 void TTree::Delete(Option_t* option /* = "" */)
3521  TFile *file = GetCurrentFile();
3522 
3523  // delete all baskets and header from file
3524  if (file && !strcmp(option,"all")) {
3525  if (!file->IsWritable()) {
3526  Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3527  return;
3528  }
3529 
3530  //find key and import Tree header in memory
3531  TKey *key = fDirectory->GetKey(GetName());
3532  if (!key) return;
3533 
3534  TDirectory *dirsav = gDirectory;
3535  file->cd();
3536 
3537  //get list of leaves and loop on all the branches baskets
3539  TLeaf *leaf;
3540  char header[16];
3541  Int_t ntot = 0;
3542  Int_t nbask = 0;
3543  Int_t nbytes,objlen,keylen;
3544  while ((leaf = (TLeaf*)next())) {
3545  TBranch *branch = leaf->GetBranch();
3546  Int_t nbaskets = branch->GetMaxBaskets();
3547  for (Int_t i=0;i<nbaskets;i++) {
3548  Long64_t pos = branch->GetBasketSeek(i);
3549  if (!pos) continue;
3550  TFile *branchFile = branch->GetFile();
3551  if (!branchFile) continue;
3552  branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3553  if (nbytes <= 0) continue;
3554  branchFile->MakeFree(pos,pos+nbytes-1);
3555  ntot += nbytes;
3556  nbask++;
3557  }
3558  }
3559 
3560  // delete Tree header key and all keys with the same name
3561  // A Tree may have been saved many times. Previous cycles are invalid.
3562  while (key) {
3563  ntot += key->GetNbytes();
3564  key->Delete();
3565  delete key;
3566  key = fDirectory->GetKey(GetName());
3567  }
3568  if (dirsav) dirsav->cd();
3569  if (gDebug) printf(" Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3570  }
3571 
3572  if (fDirectory) {
3573  fDirectory->Remove(this);
3574  //delete the file cache if it points to this Tree
3575  MoveReadCache(file,0);
3576  fDirectory = 0;
3578  }
3579 
3580  // Delete object from CINT symbol table so it can not be used anymore.
3581  gCling->DeleteGlobal(this);
3582 
3583  // Warning: We have intentional invalidated this object while inside a member function!
3584  delete this;
3585 }
3586 
3587  ///////////////////////////////////////////////////////////////////////////////
3588  /// Called by TKey and TObject::Clone to automatically add us to a directory
3589  /// when we are read from a file.
3590 
3593  if (fDirectory == dir) return;
3594  if (fDirectory) {
3595  fDirectory->Remove(this);
3596  // Delete or move the file cache if it points to this Tree
3597  TFile *file = fDirectory->GetFile();
3598  MoveReadCache(file,dir);
3599  }
3600  fDirectory = dir;
3601  TBranch* b = 0;
3603  while((b = (TBranch*) next())) {
3604  b->UpdateFile();
3605  }
3606  if (fBranchRef) {
3608  }
3609  if (fDirectory) fDirectory->Append(this);
3610 }
3611 
3612 ////////////////////////////////////////////////////////////////////////////////
3613 /// Draw expression varexp for specified entries.
3614 /// Returns -1 in case of error or number of selected events in case of success.
3615 ///
3616 /// This function accepts TCut objects as arguments.
3617 /// Useful to use the string operator +
3618 ///
3619 /// Example:
3620 ///
3621 /// ntuple.Draw("x",cut1+cut2+cut3);
3622 
3623 Long64_t TTree::Draw(const char* varexp, const TCut& selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
3625  return TTree::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
3626 }
3627 
3628 ////////////////////////////////////////////////////////////////////////////////
3629 /// Draw expression varexp for specified entries.
3630 /// Returns -1 in case of error or number of selected events in case of success.
3631 ///
3632 /// varexp is an expression of the general form
3633 /// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3634 /// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3635 /// on the y-axis versus "e2" on the x-axis
3636 /// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3637 /// versus "e2" versus "e3" on the x-, y-, z-axis, respectively.
3638 /// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3639 /// versus "e2" versus "e3" and "e4" mapped on the color number.
3640 /// (to create histograms in the 2, 3, and 4 dimensional case, see section "Saving
3641 /// the result of Draw to an histogram")
3642 ///
3643 /// Example:
3644 /// - varexp = x simplest case: draw a 1-Dim distribution of column named x
3645 /// - varexp = sqrt(x) : draw distribution of sqrt(x)
3646 /// - varexp = x*y/z
3647 /// - varexp = y:sqrt(x) 2-Dim distribution of y versus sqrt(x)
3648 /// - varexp = px:py:pz:2.5*E produces a 3-d scatter-plot of px vs py ps pz
3649 /// and the color number of each marker will be 2.5*E.
3650 /// If the color number is negative it is set to 0.
3651 /// If the color number is greater than the current number of colors
3652 /// it is set to the highest color number.The default number of
3653 /// colors is 50. see TStyle::SetPalette for setting a new color palette.
3654 ///
3655 /// Note that the variables e1, e2 or e3 may contain a selection.
3656 /// example, if e1= x*(y<0), the value histogrammed will be x if y<0
3657 /// and will be 0 otherwise.
3658 ///
3659 /// The expressions can use all the operations and build-in functions
3660 /// supported by TFormula (See TFormula::Analyze), including free
3661 /// standing function taking numerical arguments (TMath::Bessel).
3662 /// In addition, you can call member functions taking numerical
3663 /// arguments. For example:
3664 /// ~~~ {.cpp}
3665 /// TMath::BreitWigner(fPx,3,2)
3666 /// event.GetHistogram().GetXaxis().GetXmax()
3667 /// ~~~
3668 /// Note: You can only pass expression that depend on the TTree's data
3669 /// to static functions and you can only call non-static member function
3670 /// with 'fixed' parameters.
3671 ///
3672 /// selection is an expression with a combination of the columns.
3673 /// In a selection all the C++ operators are authorized.
3674 /// The value corresponding to the selection expression is used as a weight
3675 /// to fill the histogram.
3676 /// If the expression includes only boolean operations, the result
3677 /// is 0 or 1. If the result is 0, the histogram is not filled.
3678 /// In general, the expression may be of the form:
3679 /// ~~~ {.cpp}
3680 /// value*(boolean expression)
3681 /// ~~~
3682 /// if boolean expression is true, the histogram is filled with
3683 /// a `weight = value`.
3684 ///
3685 /// Examples:
3686 /// - selection1 = "x<y && sqrt(z)>3.2"
3687 /// - selection2 = "(x+y)*(sqrt(z)>3.2)"
3688 ///
3689 /// - selection1 returns a weight = 0 or 1
3690 /// - selection2 returns a weight = x+y if sqrt(z)>3.2
3691 /// returns a weight = 0 otherwise.
3692 ///
3693 /// option is the drawing option.
3694 /// - See TH1::Draw for the list of all drawing options.
3695 /// - If option COL is specified when varexp has three fields:
3696 ///~~~ {.cpp}
3697 /// tree.Draw("e1:e2:e3","","col");
3698 ///~~~
3699 /// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the color
3700 /// table. The colors for e3 are evaluated once in linear scale before
3701 /// painting. Therefore changing the pad to log scale along Z as no effect
3702 /// on the colors.
3703 /// - If option contains the string "goff", no graphics is generated.
3704 ///
3705 /// `nentries` is the number of entries to process (default is all)
3706 /// first is the first entry to process (default is 0)
3707 ///
3708 /// This function returns the number of selected entries. It returns -1
3709 /// if an error occurs.
3710 ///
3711 /// ## Drawing expressions using arrays and array elements
3712 ///
3713 /// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3714 /// or a TClonesArray.
3715 /// In a TTree::Draw expression you can now access fMatrix using the following
3716 /// syntaxes:
3717 ///
3718 /// | String passed | What is used for each entry of the tree
3719 /// |-----------------|--------------------------------------------------------|
3720 /// | `fMatrix` | the 9 elements of fMatrix |
3721 /// | `fMatrix[][]` | the 9 elements of fMatrix |
3722 /// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3723 /// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3724 /// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3725 /// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3726 ///
3727 /// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3728 ///
3729 /// In summary, if a specific index is not specified for a dimension, TTree::Draw
3730 /// will loop through all the indices along this dimension. Leaving off the
3731 /// last (right most) dimension of specifying then with the two characters '[]'
3732 /// is equivalent. For variable size arrays (and TClonesArray) the range
3733 /// of the first dimension is recalculated for each entry of the tree.
3734 /// You can also specify the index as an expression of any other variables from the
3735 /// tree.
3736 ///
3737 /// TTree::Draw also now properly handling operations involving 2 or more arrays.
3738 ///
3739 /// Let assume a second matrix fResults[5][2], here are a sample of some
3740 /// of the possible combinations, the number of elements they produce and
3741 /// the loop used:
3742 ///
3743 /// | expression | element(s) | Loop |
3744 /// |----------------------------------|------------|--------------------------|
3745 /// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
3746 /// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
3747 /// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
3748 /// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
3749 /// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
3750 /// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
3751 /// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
3752 /// | `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.|
3753 ///
3754 ///
3755 /// In summary, TTree::Draw loops through all unspecified dimensions. To
3756 /// figure out the range of each loop, we match each unspecified dimension
3757 /// from left to right (ignoring ALL dimensions for which an index has been
3758 /// specified), in the equivalent loop matched dimensions use the same index
3759 /// and are restricted to the smallest range (of only the matched dimensions).
3760 /// When involving variable arrays, the range can of course be different
3761 /// for each entry of the tree.
3762 ///
3763 /// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
3764 /// ~~~ {.cpp}
3765 /// for (Int_t i0; i < min(3,2); i++) {
3766 /// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
3767 /// }
3768 /// ~~~
3769 /// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
3770 /// ~~~ {.cpp}
3771 /// for (Int_t i0; i < min(3,5); i++) {
3772 /// for (Int_t i1; i1 < 2; i1++) {
3773 /// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
3774 /// }
3775 /// }
3776 /// ~~~
3777 /// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
3778 /// ~~~ {.cpp}
3779 /// for (Int_t i0; i < min(3,5); i++) {
3780 /// for (Int_t i1; i1 < min(3,2); i1++) {
3781 /// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
3782 /// }
3783 /// }
3784 /// ~~~
3785 /// So the loop equivalent to "fMatrix[][fResults[][]]" is:
3786 /// ~~~ {.cpp}
3787 /// for (Int_t i0; i0 < 3; i0++) {
3788 /// for (Int_t j2; j2 < 5; j2++) {
3789 /// for (Int_t j3; j3 < 2; j3++) {
3790 /// i1 = fResults[j2][j3];
3791 /// use the value of fMatrix[i0][i1]
3792 /// }
3793 /// }
3794 /// ~~~
3795 /// ## Retrieving the result of Draw
3796 ///
3797 /// By default the temporary histogram created is called "htemp", but only in
3798 /// the one dimensional Draw("e1") it contains the TTree's data points. For
3799 /// a two dimensional Draw, the data is filled into a TGraph which is named
3800 /// "Graph". They can be retrieved by calling
3801 /// ~~~ {.cpp}
3802 /// TH1F *htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
3803 /// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3804 /// ~~~
3805 /// For a three and four dimensional Draw the TPolyMarker3D is unnamed, and
3806 /// cannot be retrieved.
3807 ///
3808 /// gPad always contains a TH1 derived object called "htemp" which allows to
3809 /// access the axes:
3810 /// ~~~ {.cpp}
3811 /// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3812 /// TH2F *htemp = (TH2F*)gPad->GetPrimitive("htemp"); // empty, but has axes
3813 /// TAxis *xaxis = htemp->GetXaxis();
3814 /// ~~~
3815 /// ## Saving the result of Draw to an histogram
3816 ///
3817 /// If varexp0 contains >>hnew (following the variable(s) name(s),
3818 /// the new histogram created is called hnew and it is kept in the current
3819 /// directory (and also the current pad). This works for all dimensions.
3820 ///
3821 /// Example:
3822 /// ~~~ {.cpp}
3823 /// tree.Draw("sqrt(x)>>hsqrt","y>0")
3824 /// ~~~
3825 /// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
3826 /// directory. To retrieve it do:
3827 /// ~~~ {.cpp}
3828 /// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
3829 /// ~~~
3830 /// The binning information is taken from the environment variables
3831 /// ~~~ {.cpp}
3832 /// Hist.Binning.?D.?
3833 /// ~~~
3834 /// In addition, the name of the histogram can be followed by up to 9
3835 /// numbers between '(' and ')', where the numbers describe the
3836 /// following:
3837 ///
3838 /// - 1 - bins in x-direction
3839 /// - 2 - lower limit in x-direction
3840 /// - 3 - upper limit in x-direction
3841 /// - 4-6 same for y-direction
3842 /// - 7-9 same for z-direction
3843 ///
3844 /// When a new binning is used the new value will become the default.
3845 /// Values can be skipped.
3846 ///
3847 /// Example:
3848 /// ~~~ {.cpp}
3849 /// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
3850 /// // plot sqrt(x) between 10 and 20 using 500 bins
3851 /// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
3852 /// // plot sqrt(x) against sin(y)
3853 /// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
3854 /// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
3855 /// ~~~
3856 /// By default, the specified histogram is reset.
3857 /// To continue to append data to an existing histogram, use "+" in front
3858 /// of the histogram name.
3859 ///
3860 /// A '+' in front of the histogram name is ignored, when the name is followed by
3861 /// binning information as described in the previous paragraph.
3862 /// ~~~ {.cpp}
3863 /// tree.Draw("sqrt(x)>>+hsqrt","y>0")
3864 /// ~~~
3865 /// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
3866 /// and 3-D histograms.
3867 ///
3868 /// ## Accessing collection objects
3869 ///
3870 /// TTree::Draw default's handling of collections is to assume that any
3871 /// request on a collection pertain to it content. For example, if fTracks
3872 /// is a collection of Track objects, the following:
3873 /// ~~~ {.cpp}
3874 /// tree->Draw("event.fTracks.fPx");
3875 /// ~~~
3876 /// will plot the value of fPx for each Track objects inside the collection.
3877 /// Also
3878 /// ~~~ {.cpp}
3879 /// tree->Draw("event.fTracks.size()");
3880 /// ~~~
3881 /// would plot the result of the member function Track::size() for each
3882 /// Track object inside the collection.
3883 /// To access information about the collection itself, TTree::Draw support
3884 /// the '@' notation. If a variable which points to a collection is prefixed
3885 /// or postfixed with '@', the next part of the expression will pertain to
3886 /// the collection object. For example:
3887 /// ~~~ {.cpp}
3888 /// tree->Draw("event.@fTracks.size()");
3889 /// ~~~
3890 /// will plot the size of the collection referred to by `fTracks` (i.e the number
3891 /// of Track objects).
3892 ///
3893 /// ## Drawing 'objects'
3894 ///
3895 /// When a class has a member function named AsDouble or AsString, requesting
3896 /// to directly draw the object will imply a call to one of the 2 functions.
3897 /// If both AsDouble and AsString are present, AsDouble will be used.
3898 /// AsString can return either a char*, a std::string or a TString.s
3899 /// For example, the following
3900 /// ~~~ {.cpp}
3901 /// tree->Draw("event.myTTimeStamp");
3902 /// ~~~
3903 /// will draw the same histogram as
3904 /// ~~~ {.cpp}
3905 /// tree->Draw("event.myTTimeStamp.AsDouble()");
3906 /// ~~~
3907 /// In addition, when the object is a type TString or std::string, TTree::Draw
3908 /// will call respectively `TString::Data` and `std::string::c_str()`
3909 ///
3910 /// If the object is a TBits, the histogram will contain the index of the bit
3911 /// that are turned on.
3912 ///
3913 /// ## Retrieving information about the tree itself.
3914 ///
3915 /// You can refer to the tree (or chain) containing the data by using the
3916 /// string 'This'.
3917 /// You can then could any TTree methods. For example:
3918 /// ~~~ {.cpp}
3919 /// tree->Draw("This->GetReadEntry()");
3920 /// ~~~
3921 /// will display the local entry numbers be read.
3922 /// ~~~ {.cpp}
3923 /// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
3924 /// ~~~
3925 /// will display the name of the first 'user info' object.
3926 ///
3927 /// ## Special functions and variables
3928 ///
3929 /// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
3930 /// to access the entry number being read. For example to draw every
3931 /// other entry use:
3932 /// ~~~ {.cpp}
3933 /// tree.Draw("myvar","Entry$%2==0");
3934 /// ~~~
3935 /// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
3936 /// - `LocalEntry$` : return the current entry number in the current tree of a
3937 /// chain (`== GetTree()->GetReadEntry()`)
3938 /// - `Entries$` : return the total number of entries (== TTree::GetEntries())
3939 /// - `LocalEntries$` : return the total number of entries in the current tree
3940 /// of a chain (== GetTree()->TTree::GetEntries())
3941 /// - `Length$` : return the total number of element of this formula for this
3942 /// entry (`==TTreeFormula::GetNdata()`)
3943 /// - `Iteration$` : return the current iteration over this formula for this
3944 /// entry (i.e. varies from 0 to `Length$`).
3945 /// - `Length$(formula )` : return the total number of element of the formula
3946 /// given as a parameter.
3947 /// - `Sum$(formula )` : return the sum of the value of the elements of the
3948 /// formula given as a parameter. For example the mean for all the elements in
3949 /// one entry can be calculated with:
3950 /// `Sum$(formula )/Length$(formula )`
3951 /// - `Min$(formula )` : return the minimun (within one TTree entry) of the value of the
3952 /// elements of the formula given as a parameter.
3953 /// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
3954 /// elements of the formula given as a parameter.
3955 /// - `MinIf$(formula,condition)`
3956 /// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
3957 /// of the value of the elements of the formula given as a parameter
3958 /// if they match the condition. If no element matches the condition,
3959 /// the result is zero. To avoid the resulting peak at zero, use the
3960 /// pattern:
3961 /// ~~~ {.cpp}
3962 /// tree->Draw("MinIf$(formula,condition)","condition");
3963 /// ~~~
3964 /// which will avoid calculation `MinIf$` for the entries that have no match
3965 /// for the condition.
3966 /// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
3967 /// for the current iteration otherwise return the value of "alternate".
3968 /// For example, with arr1[3] and arr2[2]
3969 /// ~~~ {.cpp}
3970 /// tree->Draw("arr1+Alt$(arr2,0)");
3971 /// ~~~
3972 /// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
3973 /// Or with a variable size array arr3
3974 /// ~~~ {.cpp}
3975 /// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
3976 /// ~~~
3977 /// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
3978 /// As a comparison
3979 /// ~~~ {.cpp}
3980 /// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
3981 /// ~~~
3982 /// will draw the sum arr3 for the index 0 to 2 only if the
3983 /// actual_size_of_arr3 is greater or equal to 3.
3984 /// Note that the array in 'primary' is flattened/linearized thus using
3985 /// Alt$ with multi-dimensional arrays of different dimensions in unlikely
3986 /// to yield the expected results. To visualize a bit more what elements
3987 /// would be matched by TTree::Draw, TTree::Scan can be used:
3988 /// ~~~ {.cpp}
3989 /// tree->Scan("arr1:Alt$(arr2,0)");
3990 /// ~~~
3991 /// will print on one line the value of arr1 and (arr2,0) that will be
3992 /// matched by
3993 /// ~~~ {.cpp}
3994 /// tree->Draw("arr1-Alt$(arr2,0)");
3995 /// ~~~
3996 /// The ternary operator is not directly supported in TTree::Draw however, to plot the
3997 /// equivalent of `var2<20 ? -99 : var1`, you can use:
3998 /// ~~~ {.cpp}
3999 /// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4000 /// ~~~
4001 /// ## Drawing a user function accessing the TTree data directly
4002 ///
4003 /// If the formula contains a file name, TTree::MakeProxy will be used
4004 /// to load and execute this file. In particular it will draw the
4005 /// result of a function with the same name as the file. The function
4006 /// will be executed in a context where the name of the branches can
4007 /// be used as a C++ variable.
4008 ///
4009 /// For example draw px using the file hsimple.root (generated by the
4010 /// hsimple.C tutorial), we need a file named hsimple.cxx:
4011 /// ~~~ {.cpp}
4012 /// double hsimple() {
4013 /// return px;
4014 /// }
4015 /// ~~~
4016 /// MakeProxy can then be used indirectly via the TTree::Draw interface
4017 /// as follow:
4018 /// ~~~ {.cpp}
4019 /// new TFile("hsimple.root")
4020 /// ntuple->Draw("hsimple.cxx");
4021 /// ~~~
4022 /// A more complete example is available in the tutorials directory:
4023 /// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4024 /// which reimplement the selector found in `h1analysis.C`
4025 ///
4026 /// The main features of this facility are:
4027 ///
4028 /// * on-demand loading of branches
4029 /// * ability to use the 'branchname' as if it was a data member
4030 /// * protection against array out-of-bound
4031 /// * ability to use the branch data as object (when the user code is available)
4032 ///
4033 /// See TTree::MakeProxy for more details.
4034 ///
4035 /// ## Making a Profile histogram
4036 ///
4037 /// In case of a 2-Dim expression, one can generate a TProfile histogram
4038 /// instead of a TH2F histogram by specifying option=prof or option=profs
4039 /// or option=profi or option=profg ; the trailing letter select the way
4040 /// the bin error are computed, See TProfile2D::SetErrorOption for
4041 /// details on the differences.
4042 /// The option=prof is automatically selected in case of y:x>>pf
4043 /// where pf is an existing TProfile histogram.
4044 ///
4045 /// ## Making a 2D Profile histogram
4046 ///
4047 /// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4048 /// instead of a TH3F histogram by specifying option=prof or option=profs.
4049 /// or option=profi or option=profg ; the trailing letter select the way
4050 /// the bin error are computed, See TProfile2D::SetErrorOption for
4051 /// details on the differences.
4052 /// The option=prof is automatically selected in case of z:y:x>>pf
4053 /// where pf is an existing TProfile2D histogram.
4054 ///
4055 /// ## Making a 5D plot using GL
4056 ///
4057 /// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4058 /// using OpenGL. See $ROOTSYS/tutorials/tree/staff.C as example.
4059 ///
4060 /// ## Making a parallel coordinates plot
4061 ///
4062 /// In case of a 2-Dim or more expression with the option=para, one can generate
4063 /// a parallel coordinates plot. With that option, the number of dimensions is
4064 /// arbitrary. Giving more than 4 variables without the option=para or
4065 /// option=candle or option=goff will produce an error.
4066 ///
4067 /// ## Making a candle sticks chart
4068 ///
4069 /// In case of a 2-Dim or more expression with the option=candle, one can generate
4070 /// a candle sticks chart. With that option, the number of dimensions is
4071 /// arbitrary. Giving more than 4 variables without the option=para or
4072 /// option=candle or option=goff will produce an error.
4073 ///
4074 /// ## Normalizing the output histogram to 1
4075 ///
4076 /// When option contains "norm" the output histogram is normalized to 1.
4077 ///
4078 /// ## Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4079 ///
4080 /// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4081 /// instead of histogramming one variable.
4082 /// If varexp0 has the form >>elist , a TEventList object named "elist"
4083 /// is created in the current directory. elist will contain the list
4084 /// of entry numbers satisfying the current selection.
4085 /// If option "entrylist" is used, a TEntryList object is created
4086 /// If the selection contains arrays, vectors or any container class and option
4087 /// "entrylistarray" is used, a TEntryListArray object is created
4088 /// containing also the subentries satisfying the selection, i.e. the indices of
4089 /// the branches which hold containers classes.
4090 /// Example:
4091 /// ~~~ {.cpp}
4092 /// tree.Draw(">>yplus","y>0")
4093 /// ~~~
4094 /// will create a TEventList object named "yplus" in the current directory.
4095 /// In an interactive session, one can type (after TTree::Draw)
4096 /// ~~~ {.cpp}
4097 /// yplus.Print("all")
4098 /// ~~~
4099 /// to print the list of entry numbers in the list.
4100 /// ~~~ {.cpp}
4101 /// tree.Draw(">>yplus", "y>0", "entrylist")
4102 /// ~~~
4103 /// will create a TEntryList object names "yplus" in the current directory
4104 /// ~~~ {.cpp}
4105 /// tree.Draw(">>yplus", "y>0", "entrylistarray")
4106 /// ~~~
4107 /// will create a TEntryListArray object names "yplus" in the current directory
4108 ///
4109 /// By default, the specified entry list is reset.
4110 /// To continue to append data to an existing list, use "+" in front
4111 /// of the list name;
4112 /// ~~~ {.cpp}
4113 /// tree.Draw(">>+yplus","y>0")
4114 /// ~~~
4115 /// will not reset yplus, but will enter the selected entries at the end
4116 /// of the existing list.
4117 ///
4118 /// ## Using a TEventList, TEntryList or TEntryListArray as Input
4119 ///
4120 /// Once a TEventList or a TEntryList object has been generated, it can be used as input
4121 /// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4122 /// current event list
4123 ///
4124 /// Example 1:
4125 /// ~~~ {.cpp}
4126 /// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4127 /// tree->SetEventList(elist);
4128 /// tree->Draw("py");
4129 /// ~~~
4130 /// Example 2:
4131 /// ~~~ {.cpp}
4132 /// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4133 /// tree->SetEntryList(elist);
4134 /// tree->Draw("py");
4135 /// ~~~
4136 /// If a TEventList object is used as input, a new TEntryList object is created
4137 /// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4138 /// for this transformation. This new object is owned by the chain and is deleted
4139 /// with it, unless the user extracts it by calling GetEntryList() function.
4140 /// See also comments to SetEventList() function of TTree and TChain.
4141 ///
4142 /// If arrays are used in the selection criteria and TEntryListArray is not used,
4143 /// all the entries that have at least one element of the array that satisfy the selection
4144 /// are entered in the list.
4145 ///
4146 /// Example:
4147 /// ~~~ {.cpp}
4148 /// tree.Draw(">>pyplus","fTracks.fPy>0");
4149 /// tree->SetEventList(pyplus);
4150 /// tree->Draw("fTracks.fPy");
4151 /// ~~~
4152 /// will draw the fPy of ALL tracks in event with at least one track with
4153 /// a positive fPy.
4154 ///
4155 /// To select only the elements that did match the original selection
4156 /// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4157 ///
4158 /// Example:
4159 /// ~~~ {.cpp}
4160 /// tree.Draw(">>pyplus","fTracks.fPy>0");
4161 /// pyplus->SetReapplyCut(kTRUE);
4162 /// tree->SetEventList(pyplus);
4163 /// tree->Draw("fTracks.fPy");
4164 /// ~~~
4165 /// will draw the fPy of only the tracks that have a positive fPy.
4166 ///
4167 /// To draw only the elements that match a selection in case of arrays,
4168 /// you can also use TEntryListArray (faster in case of a more general selection).
4169 ///
4170 /// Example:
4171 /// ~~~ {.cpp}
4172 /// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4173 /// tree->SetEntryList(pyplus);
4174 /// tree->Draw("fTracks.fPy");
4175 /// ~~~
4176 /// will draw the fPy of only the tracks that have a positive fPy,
4177 /// but without redoing the selection.
4178 ///
4179 /// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4180 ///
4181 /// ## How to obtain more info from TTree::Draw
4182 ///
4183 /// Once TTree::Draw has been called, it is possible to access useful
4184 /// information still stored in the TTree object via the following functions:
4185 ///
4186 /// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4187 /// - GetV1() // returns a pointer to the double array of V1
4188 /// - GetV2() // returns a pointer to the double array of V2
4189 /// - GetV3() // returns a pointer to the double array of V3
4190 /// - GetV4() // returns a pointer to the double array of V4
4191 /// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4192 ///
4193 /// where V1,V2,V3 correspond to the expressions in
4194 /// ~~~ {.cpp}
4195 /// TTree::Draw("V1:V2:V3:V4",selection);
4196 /// ~~~
4197 /// If the expression has more than 4 component use GetVal(index)
4198 ///
4199 /// Example:
4200 /// ~~~ {.cpp}
4201 /// Root > ntuple->Draw("py:px","pz>4");
4202 /// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4203 /// ntuple->GetV2(), ntuple->GetV1());
4204 /// Root > gr->Draw("ap"); //draw graph in current pad
4205 /// ~~~
4206 /// creates a TGraph object with a number of points corresponding to the
4207 /// number of entries selected by the expression "pz>4", the x points of the graph
4208 /// being the px values of the Tree and the y points the py values.
4209 ///
4210 /// Important note: By default TTree::Draw creates the arrays obtained
4211 /// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4212 /// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4213 /// values calculated.
4214 /// By default fEstimate=1000000 and can be modified
4215 /// via TTree::SetEstimate. To keep in memory all the results (in case
4216 /// where there is only one result per entry), use
4217 /// ~~~ {.cpp}
4218 /// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4219 /// ~~~
4220 /// You must call SetEstimate if the expected number of selected rows
4221 /// you need to look at is greater than 1000000.
4222 ///
4223 /// You can use the option "goff" to turn off the graphics output
4224 /// of TTree::Draw in the above example.
4225 ///
4226 /// ## Automatic interface to TTree::Draw via the TTreeViewer
4227 ///
4228 /// A complete graphical interface to this function is implemented
4229 /// in the class TTreeViewer.
4230 /// To start the TTreeViewer, three possibilities:
4231 /// - select TTree context menu item "StartViewer"
4232 /// - type the command "TTreeViewer TV(treeName)"
4233 /// - execute statement "tree->StartViewer();"
4234 
4235 Long64_t TTree::Draw(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
4237  GetPlayer();
4238  if (fPlayer)
4239  return fPlayer->DrawSelect(varexp,selection,option,nentries,firstentry);
4240  return -1;
4241 }
4242 
4243 ////////////////////////////////////////////////////////////////////////////////
4244 /// Remove some baskets from memory.
4245 
4246 void TTree::DropBaskets()
4248  TBranch* branch = 0;
4250  for (Int_t i = 0; i < nb; ++i) {
4251  branch = (TBranch*) fBranches.UncheckedAt(i);
4252  branch->DropBaskets("all");
4253  }
4254 }
4255 
4256 ////////////////////////////////////////////////////////////////////////////////
4257 /// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4258 
4261  // Be careful not to remove current read/write buffers.
4262  Int_t ndrop = 0;
4263  Int_t nleaves = fLeaves.GetEntriesFast();
4264  for (Int_t i = 0; i < nleaves; ++i) {
4265  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4266  TBranch* branch = (TBranch*) leaf->GetBranch();
4267  Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4268  for (Int_t j = 0; j < nbaskets - 1; ++j) {
4269  if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4270  continue;
4271  }
4272  TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4273  if (basket) {
4274  ndrop += basket->DropBuffers();
4276  return;
4277  }
4278  }
4279  }
4280  }
4281 }
4282 
4283 ////////////////////////////////////////////////////////////////////////////////
4284 /// Fill all branches.
4285 ///
4286 /// This function loops on all the branches of this tree. For
4287 /// each branch, it copies to the branch buffer (basket) the current
4288 /// values of the leaves data types. If a leaf is a simple data type,
4289 /// a simple conversion to a machine independent format has to be done.
4290 ///
4291 /// This machine independent version of the data is copied into a
4292 /// basket (each branch has its own basket). When a basket is full
4293 /// (32k worth of data by default), it is then optionally compressed
4294 /// and written to disk (this operation is also called committing or
4295 /// 'flushing' the basket). The committed baskets are then
4296 /// immediately removed from memory.
4297 ///
4298 /// The function returns the number of bytes committed to the
4299 /// individual branches.
4300 ///
4301 /// If a write error occurs, the number of bytes returned is -1.
4302 ///
4303 /// If no data are written, because, e.g., the branch is disabled,
4304 /// the number of bytes returned is 0.
4305 ///
4306 /// __The baskets are flushed and the Tree header saved at regular intervals__
4307 ///
4308 /// At regular intervals, when the amount of data written so far is
4309 /// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4310 /// This makes future reading faster as it guarantees that baskets belonging to nearby
4311 /// entries will be on the same disk region.
4312 /// When the first call to flush the baskets happen, we also take this opportunity
4313 /// to optimize the baskets buffers.
4314 /// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4315 /// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4316 /// in case the program writing the Tree crashes.
4317 /// The decisions to FlushBaskets and Auto Save can be made based either on the number
4318 /// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4319 /// written (fAutoFlush and fAutoSave positive).
4320 /// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4321 /// base on the number of events written instead of the number of bytes written.
4322 ///
4323 /// Note that calling FlushBaskets too often increases the IO time.
4324 ///
4325 /// Note that calling AutoSave too often increases the IO time and also the file size.
4326 
4329  Int_t nbytes = 0;
4330  Int_t nerror = 0;
4332  if (nb == 1) {
4333  // Case of one single super branch. Automatically update
4334  // all the branch addresses if a new object was created.
4335  TBranch* branch = (TBranch*) fBranches.UncheckedAt(0);
4336  branch->UpdateAddress();
4337  }
4338  if (fBranchRef) {
4339  fBranchRef->Clear();
4340  }
4341  for (Int_t i = 0; i < nb; ++i) {
4342  // Loop over all branches, filling and accumulating bytes written and error counts.
4343  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
4344  if (branch->TestBit(kDoNotProcess)) {
4345  continue;
4346  }
4347  Int_t nwrite = branch->Fill();
4348  if (nwrite < 0) {
4349  if (nerror < 2) {
4350  Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4351  " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4352  " Instead of doing:\n"
4353  " TTree *T = new TTree(...)\n"
4354  " TFile *f = new TFile(...)\n"
4355  " you should do:\n"
4356  " TFile *f = new TFile(...)\n"
4357  " TTree *T = new TTree(...)",
4358  GetName(), branch->GetName(), nwrite,fEntries+1);
4359  } else {
4360  Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,fEntries+1);
4361  }
4362  ++nerror;
4363  } else {
4364  nbytes += nwrite;
4365  }
4366  }
4367  if (fBranchRef) {
4368  fBranchRef->Fill();
4369  }
4370  ++fEntries;
4371  if (fEntries > fMaxEntries) {
4372  KeepCircular();
4373  }
4374  if (gDebug > 0) printf("TTree::Fill - A: %d %lld %lld %lld %lld %lld %lld \n",
4376 
4377  if (fAutoFlush != 0 || fAutoSave != 0) {
4378  // Is it time to flush or autosave baskets?
4379  if (fFlushedBytes == 0) {
4380  // Decision can be based initially either on the number of bytes
4381  // or the number of entries written.
4382  if ((fAutoFlush<0 && fZipBytes > -fAutoFlush) ||
4383  (fAutoSave <0 && fZipBytes > -fAutoSave ) ||
4384  (fAutoFlush>0 && fEntries%TMath::Max((Long64_t)1,fAutoFlush) == 0) ||
4385  (fAutoSave >0 && fEntries%TMath::Max((Long64_t)1,fAutoSave) == 0) ) {
4386 
4387  //First call FlushBasket to make sure that fTotBytes is up to date.
4388  FlushBaskets();
4389  OptimizeBaskets(fTotBytes,1,"");
4390  if (gDebug > 0) Info("TTree::Fill","OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",fEntries,fZipBytes,fFlushedBytes);
4392  fAutoFlush = fEntries; // Use test on entries rather than bytes
4393 
4394  // subsequently in run
4395  if (fAutoSave < 0) {
4396  // Set fAutoSave to the largest integer multiple of
4397  // fAutoFlush events such that fAutoSave*fFlushedBytes
4398  // < (minus the input value of fAutoSave)
4399  if (fZipBytes != 0) {
4401  } else if (fTotBytes != 0) {
4403  } else {
4404  TBufferFile b(TBuffer::kWrite, 10000);
4405  TTree::Class()->WriteBuffer(b, (TTree*) this);
4406  Long64_t total = b.Length();
4408  }
4409  } else if(fAutoSave > 0) {
4411  }
4412  if (fAutoSave!=0 && fEntries >= fAutoSave) AutoSave(); // FlushBaskets not called in AutoSave
4413  if (gDebug > 0) Info("TTree::Fill","First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4414  }
4415  } else if (fNClusterRange && fAutoFlush && ( (fEntries-fClusterRangeEnd[fNClusterRange-1]) % fAutoFlush == 0) ) {
4416  if (fAutoSave != 0 && fEntries%fAutoSave == 0) {
4417  //We are at an AutoSave point. AutoSave flushes baskets and saves the Tree header
4418  AutoSave("flushbaskets");
4419  if (gDebug > 0) Info("TTree::Fill","AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n",fEntries,fZipBytes,fSavedBytes);
4420  } else {
4421  //We only FlushBaskets
4422  FlushBaskets();
4423  if (gDebug > 0) Info("TTree::Fill","FlushBasket called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",fEntries,fZipBytes,fFlushedBytes);
4424  }
4426  } else if (fNClusterRange == 0 && fEntries > 1 && fAutoFlush && fEntries%fAutoFlush == 0) {
4427  if (fAutoSave != 0 && fEntries%fAutoSave == 0) {
4428  //We are at an AutoSave point. AutoSave flushes baskets and saves the Tree header
4429  AutoSave("flushbaskets");
4430  if (gDebug > 0) Info("TTree::Fill","AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n",fEntries,fZipBytes,fSavedBytes);
4431  } else {
4432  //We only FlushBaskets
4433  FlushBaskets();
4434  if (gDebug > 0) Info("TTree::Fill","FlushBasket called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",fEntries,fZipBytes,fFlushedBytes);
4435  }
4437  }
4438  }
4439  // Check that output file is still below the maximum size.
4440  // If above, close the current file and continue on a new file.
4441  // Currently, the automatic change of file is restricted
4442  // to the case where the tree is in the top level directory.
4443  if (!fDirectory) {
4444  return nbytes;
4445  }
4446  TFile* file = fDirectory->GetFile();
4447  if (file && (file->GetEND() > fgMaxTreeSize)) {
4448  if (fDirectory == (TDirectory*) file) {
4449  ChangeFile(file);
4450  }
4451  }
4452  if (nerror) {
4453  return -1;
4454  }
4455  return nbytes;
4456 }
4457 
4458 ////////////////////////////////////////////////////////////////////////////////
4459 /// Search in the array for a branch matching the branch name,
4460 /// with the branch possibly expressed as a 'full' path name (with dots).
4461 
4462 static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4463  if (list==0 || branchname == 0 || branchname[0] == '\0') return 0;
4464 
4465  Int_t nbranches = list->GetEntries();
4466 
4467  UInt_t brlen = strlen(branchname);
4468 
4469  for(Int_t index = 0; index < nbranches; ++index) {
4470  TBranch *where = (TBranch*)list->UncheckedAt(index);
4471 
4472  const char *name = where->GetName();
4473  UInt_t len = strlen(name);
4474  if (len && name[len-1]==']') {
4475  const char *dim = strchr(name,'[');
4476  if (dim) {
4477  len = dim - name;
4478  }
4479  }
4480  if (brlen == len && strncmp(branchname,name,len)==0) {
4481  return where;
4482  }
4483  TBranch *next = 0;
4484  if ((brlen >= len) && (branchname[len] == '.')
4485  && strncmp(name, branchname, len) == 0) {
4486  // The prefix subbranch name match the branch name.
4487 
4488  next = where->FindBranch(branchname);
4489  if (!next) {
4490  next = where->FindBranch(branchname+len+1);
4491  }
4492  if (next) return next;
4493  }
4494  const char *dot = strchr((char*)branchname,'.');
4495  if (dot) {
4496  if (len==(size_t)(dot-branchname) &&
4497  strncmp(branchname,name,dot-branchname)==0 ) {
4498  return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4499  }
4500  }
4501  }
4502  return 0;
4503 }
4504 
4505 ////////////////////////////////////////////////////////////////////////////////
4506 /// Return the branch that correspond to the path 'branchname', which can
4507 /// include the name of the tree or the omitted name of the parent branches.
4508 /// In case of ambiguity, returns the first match.
4509 
4510 TBranch* TTree::FindBranch(const char* branchname)
4512  // We already have been visited while recursively looking
4513  // through the friends tree, let return
4515  return 0;
4516  }
4517 
4518  TBranch* branch = 0;
4519  // If the first part of the name match the TTree name, look for the right part in the
4520  // list of branches.
4521  // This will allow the branchname to be preceded by
4522  // the name of this tree.
4523  if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4524  branch = R__FindBranchHelper( GetListOfBranches(), branchname + fName.Length() + 1);
4525  if (branch) return branch;
4526  }
4527  // If we did not find it, let's try to find the full name in the list of branches.
4528  branch = R__FindBranchHelper(GetListOfBranches(), branchname);
4529  if (branch) return branch;
4530 
4531  // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4533  while ((branch = (TBranch*) next())) {
4534  TBranch* nestedbranch = branch->FindBranch(branchname);
4535  if (nestedbranch) {
4536  return nestedbranch;
4537  }
4538  }
4539 
4540  // Search in list of friends.
4541  if (!fFriends) {
4542  return 0;
4543  }
4544  TFriendLock lock(this, kFindBranch);
4545  TIter nextf(fFriends);
4546  TFriendElement* fe = 0;
4547  while ((fe = (TFriendElement*) nextf())) {
4548  TTree* t = fe->GetTree();
4549  if (!t) {
4550  continue;
4551  }
4552  // If the alias is present replace it with the real name.
4553  const char *subbranch = strstr(branchname, fe->GetName());
4554  if (subbranch != branchname) {
4555  subbranch = 0;
4556  }
4557  if (subbranch) {
4558  subbranch += strlen(fe->GetName());
4559  if (*subbranch != '.') {
4560  subbranch = 0;
4561  } else {
4562  ++subbranch;
4563  }
4564  }
4565  std::ostringstream name;
4566  if (subbranch) {
4567  name << t->GetName() << "." << subbranch;
4568  } else {
4569  name << branchname;
4570  }
4571  branch = t->FindBranch(name.str().c_str());
4572  if (branch) {
4573  return branch;
4574  }
4575  }
4576  return 0;
4577 }
4578 
4579 ////////////////////////////////////////////////////////////////////////////////
4580 /// Find leaf..
4581 
4582 TLeaf* TTree::FindLeaf(const char* searchname)
4584  // We already have been visited while recursively looking
4585  // through the friends tree, let's return.
4586  if (kFindLeaf & fFriendLockStatus) {
4587  return 0;
4588  }
4589 
4590  // This will allow the branchname to be preceded by
4591  // the name of this tree.
4592  char* subsearchname = (char*) strstr(searchname, GetName());
4593  if (subsearchname != searchname) {
4594  subsearchname = 0;
4595  }
4596  if (subsearchname) {
4597  subsearchname += strlen(GetName());
4598  if (*subsearchname != '.') {
4599  subsearchname = 0;
4600  } else {
4601  ++subsearchname;
4602  if (subsearchname[0]==0) {
4603  subsearchname = 0;
4604  }
4605  }
4606  }
4607 
4608  TString leafname;
4609  TString leaftitle;
4610  TString longname;
4611  TString longtitle;
4612 
4613  // For leaves we allow for one level up to be prefixed to the name.
4615  TLeaf* leaf = 0;
4616  while ((leaf = (TLeaf*) next())) {
4617  leafname = leaf->GetName();
4618  Ssiz_t dim = leafname.First('[');
4619  if (dim >= 0) leafname.Remove(dim);
4620 
4621  if (leafname == searchname) {
4622  return leaf;
4623  }
4624  if (subsearchname && leafname == subsearchname) {
4625  return leaf;
4626  }
4627  // The TLeafElement contains the branch name
4628  // in its name, let's use the title.
4629  leaftitle = leaf->GetTitle();
4630  dim = leaftitle.First('[');
4631  if (dim >= 0) leaftitle.Remove(dim);
4632 
4633  if (leaftitle == searchname) {
4634  return leaf;
4635  }
4636  if (subsearchname && leaftitle == subsearchname) {
4637  return leaf;
4638  }
4639  TBranch* branch = leaf->GetBranch();
4640  if (branch) {
4641  longname.Form("%s.%s",branch->GetName(),leafname.Data());
4642  dim = longname.First('[');
4643  if (dim>=0) longname.Remove(dim);
4644  if (longname == searchname) {
4645  return leaf;
4646  }
4647  if (subsearchname && longname == subsearchname) {
4648  return leaf;
4649  }
4650  longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
4651  dim = longtitle.First('[');
4652  if (dim>=0) longtitle.Remove(dim);
4653  if (longtitle == searchname) {
4654  return leaf;
4655  }
4656  if (subsearchname && longtitle == subsearchname) {
4657  return leaf;
4658  }
4659  // The following is for the case where the branch is only
4660  // a sub-branch. Since we do not see it through
4661  // TTree::GetListOfBranches, we need to see it indirectly.
4662  // This is the less sturdy part of this search ... it may
4663  // need refining ...
4664  if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
4665  return leaf;
4666  }
4667  if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
4668  return leaf;
4669  }
4670  }
4671  }
4672  // Search in list of friends.
4673  if (!fFriends) {
4674  return 0;
4675  }
4676  TFriendLock lock(this, kFindLeaf);
4677  TIter nextf(fFriends);
4678  TFriendElement* fe = 0;
4679  while ((fe = (TFriendElement*) nextf())) {
4680  TTree* t = fe->GetTree();
4681  if (!t) {
4682  continue;
4683  }
4684  // If the alias is present replace it with the real name.
4685  subsearchname = (char*) strstr(searchname, fe->GetName());
4686  if (subsearchname != searchname) {
4687  subsearchname = 0;
4688  }
4689  if (subsearchname) {
4690  subsearchname += strlen(fe->GetName());
4691  if (*subsearchname != '.') {
4692  subsearchname = 0;
4693  } else {
4694  ++subsearchname;
4695  }
4696  }
4697  if (subsearchname) {
4698  leafname.Form("%s.%s",t->GetName(),subsearchname);
4699  } else {
4700  leafname = searchname;
4701  }
4702  leaf = t->FindLeaf(leafname);
4703  if (leaf) {
4704  return leaf;
4705  }
4706  }
4707  return 0;
4708 }
4709 
4710 ////////////////////////////////////////////////////////////////////////////////
4711 /// Fit a projected item(s) from a tree.
4712 ///
4713 /// funcname is a TF1 function.
4714 ///
4715 /// See TTree::Draw() for explanations of the other parameters.
4716 ///
4717 /// By default the temporary histogram created is called htemp.
4718 /// If varexp contains >>hnew , the new histogram created is called hnew
4719 /// and it is kept in the current directory.
4720 ///
4721 /// The function returns the number of selected entries.
4722 ///
4723 /// Example:
4724 /// ~~~ {.cpp}
4725 /// tree.Fit(pol4,sqrt(x)>>hsqrt,y>0)
4726 /// ~~~
4727 /// will fit sqrt(x) and save the histogram as "hsqrt" in the current
4728 /// directory.
4729 ///
4730 /// See also TTree::UnbinnedFit
4731 ///
4732 /// ## Return status
4733 ///
4734 /// The function returns the status of the histogram fit (see TH1::Fit)
4735 /// If no entries were selected, the function returns -1;
4736 /// (i.e. fitResult is null is the fit is OK)
4737 
4738 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)
4740  GetPlayer();
4741  if (fPlayer) {
4742  return fPlayer->Fit(funcname, varexp, selection, option, goption, nentries, firstentry);
4743  }
4744  return -1;
4745 }
4746 
4747 ////////////////////////////////////////////////////////////////////////////////
4748 /// Write to disk all the basket that have not yet been individually written.
4749 ///
4750 /// Return the number of bytes written or -1 in case of write error.
4751 
4752 Int_t TTree::FlushBaskets() const
4754  if (!fDirectory) return 0;
4755  Int_t nbytes = 0;
4756  Int_t nerror = 0;
4757  TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
4758  Int_t nb = lb->GetEntriesFast();
4759  for (Int_t j = 0; j < nb; j++) {
4760  TBranch* branch = (TBranch*) lb->UncheckedAt(j);
4761  if (branch) {
4762  Int_t nwrite = branch->FlushBaskets();
4763  if (nwrite<0) {
4764  ++nerror;
4765  } else {
4766  nbytes += nwrite;
4767  }
4768  }
4769  }
4770  if (nerror) {
4771  return -1;
4772  } else {
4773  return nbytes;
4774  }
4775 }
4776 
4777 ////////////////////////////////////////////////////////////////////////////////
4778 /// Returns the expanded value of the alias. Search in the friends if any.
4779 
4780 const char* TTree::GetAlias(const char* aliasName) const
4782  // We already have been visited while recursively looking
4783  // through the friends tree, let's return.
4784  if (kGetAlias & fFriendLockStatus) {
4785  return 0;
4786  }
4787  if (fAliases) {
4788  TObject* alias = fAliases->FindObject(aliasName);
4789  if (alias) {
4790  return alias->GetTitle();
4791  }
4792  }
4793  if (!fFriends) {
4794  return 0;
4795  }
4796  TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
4797  TIter nextf(fFriends);
4798  TFriendElement* fe = 0;
4799  while ((fe = (TFriendElement*) nextf())) {
4800  TTree* t = fe->GetTree();
4801  if (t) {
4802  const char* alias = t->GetAlias(aliasName);
4803  if (alias) {
4804  return alias;
4805  }
4806  const char* subAliasName = strstr(aliasName, fe->GetName());
4807  if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
4808  alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
4809  if (alias) {
4810  return alias;
4811  }
4812  }
4813  }
4814  }
4815  return 0;
4816 }
4817 
4818 ////////////////////////////////////////////////////////////////////////////////
4819 /// Return pointer to the branch with the given name in this tree or its friends.
4820 
4821 TBranch* TTree::GetBranch(const char* name)
4823  if (name == 0) return 0;
4824 
4825  // We already have been visited while recursively
4826  // looking through the friends tree, let's return.
4827  if (kGetBranch & fFriendLockStatus) {
4828  return 0;
4829  }
4830 
4831  // Search using branches.
4833  for (Int_t i = 0; i < nb; i++) {
4834  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
4835  if (!strcmp(branch->GetName(), name)) {
4836  return branch;
4837  }
4838  TObjArray* lb = branch->GetListOfBranches();
4839  Int_t nb1 = lb->GetEntriesFast();
4840  for (Int_t j = 0; j < nb1; j++) {
4841  TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
4842  if (!strcmp(b1->GetName(), name)) {
4843  return b1;
4844  }
4845  TObjArray* lb1 = b1->GetListOfBranches();
4846  Int_t nb2 = lb1->GetEntriesFast();
4847  for (Int_t k = 0; k < nb2; k++) {
4848  TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
4849  if (!strcmp(b2->GetName(), name)) {
4850  return b2;
4851  }
4852  }
4853  }
4854  }
4855 
4856  // Search using leaves.
4857  TObjArray* leaves = GetListOfLeaves();
4858  Int_t nleaves = leaves->GetEntriesFast();
4859  for (Int_t i = 0; i < nleaves; i++) {
4860  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
4861  TBranch* branch = leaf->GetBranch();
4862  if (!strcmp(branch->GetName(), name)) {
4863  return branch;
4864  }
4865  }
4866 
4867  if (!fFriends) {
4868  return 0;
4869  }
4870 
4871  // Search in list of friends.
4872  TFriendLock lock(this, kGetBranch);
4873  TIter next(fFriends);
4874  TFriendElement* fe = 0;
4875  while ((fe = (TFriendElement*) next())) {
4876  TTree* t = fe->GetTree();
4877  if (t) {
4878  TBranch* branch = t->GetBranch(name);
4879  if (branch) {
4880  return branch;
4881  }
4882  }
4883  }
4884 
4885  // Second pass in the list of friends when
4886  // the branch name is prefixed by the tree name.
4887  next.Reset();
4888  while ((fe = (TFriendElement*) next())) {
4889  TTree* t = fe->GetTree();
4890  if (!t) {
4891  continue;
4892  }
4893  char* subname = (char*) strstr(name, fe->GetName());
4894  if (subname != name) {
4895  continue;
4896  }
4897  Int_t l = strlen(fe->GetName());
4898  subname += l;
4899  if (*subname != '.') {
4900  continue;
4901  }
4902  subname++;
4903  TBranch* branch = t->GetBranch(subname);
4904  if (branch) {
4905  return branch;
4906  }
4907  }
4908  return 0;
4909 }
4910 
4911 ////////////////////////////////////////////////////////////////////////////////
4912 /// Return status of branch with name branchname.
4913 ///
4914 /// - 0 if branch is not activated
4915 /// - 1 if branch is activated
4916 
4917 Bool_t TTree::GetBranchStatus(const char* branchname) const
4919  TBranch* br = const_cast<TTree*>(this)->GetBranch(branchname);
4920  if (br) {
4921  return br->TestBit(kDoNotProcess) == 0;
4922  }
4923  return 0;
4924 }
4925 
4926 ////////////////////////////////////////////////////////////////////////////////
4927 /// Static function returning the current branch style.
4928 ///
4929 /// - style = 0 old Branch
4930 /// - style = 1 new Bronch
4931 
4934  return fgBranchStyle;
4935 }
4936 
4937 ////////////////////////////////////////////////////////////////////////////////
4938 /// Used for automatic sizing of the cache.
4939 ///
4940 /// Estimates a suitable size for the tree cache based on AutoFlush.
4941 /// A cache sizing factor is taken from the configuration. If this yields zero
4942 /// and withDefault is true the historical algorithm for default size is used.
4943 
4944 Long64_t TTree::GetCacheAutoSize(Bool_t withDefault /* = kFALSE */ ) const
4946  const char *stcs;
4947  Double_t cacheFactor = 0.0;
4948  if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) {
4949  cacheFactor = gEnv->GetValue("TTreeCache.Size", 1.0);
4950  } else {
4951  cacheFactor = TString(stcs).Atof();
4952  }
4953 
4954  if (cacheFactor < 0.0) {
4955  // ignore negative factors
4956  cacheFactor = 0.0;
4957  }
4958 
4959  Long64_t cacheSize = 0;
4960 
4961  if (fAutoFlush < 0) cacheSize = Long64_t(-cacheFactor*fAutoFlush);
4962  else if (fAutoFlush == 0) cacheSize = 0;
4963  else cacheSize = Long64_t(cacheFactor*1.5*fAutoFlush*fZipBytes/(fEntries+1));
4964 
4965  if (cacheSize >= (INT_MAX / 4)) {
4966  cacheSize = INT_MAX / 4;
4967  }
4968 
4969  if (cacheSize < 0) {
4970  cacheSize = 0;
4971  }
4972 
4973  if (cacheSize == 0 && withDefault) {
4974  if (fAutoFlush < 0) cacheSize = -fAutoFlush;
4975  else if (fAutoFlush == 0) cacheSize = 0;
4976  else cacheSize = Long64_t(1.5*fAutoFlush*fZipBytes/(fEntries+1));
4977  }
4978 
4979  return cacheSize;
4980 }
4981 
4982 ////////////////////////////////////////////////////////////////////////////////
4983 /// Return an iterator over the cluster of baskets starting at firstentry.
4984 ///
4985 /// This iterator is not yet supported for TChain object.
4986 /// ~~~ {.cpp}
4987 /// TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
4988 /// Long64_t clusterStart;
4989 /// while( (clusterStart = clusterIter()) < tree->GetEntries() ) {
4990 /// printf("The cluster starts at %lld and ends at %lld (inclusive)\n",clusterStart,clusterIter.GetNextEntry()-1);
4991 /// }
4992 /// ~~~
4993 
4996  // create cache if wanted
4998 
4999  return TClusterIterator(this,firstentry);
5000 }
5001 
5002 ////////////////////////////////////////////////////////////////////////////////
5003 /// Return pointer to the current file.
5004 
5007  if (!fDirectory || fDirectory==gROOT) {
5008  return 0;
5009  }
5010  return fDirectory->GetFile();
5011 }
5012 
5013 ////////////////////////////////////////////////////////////////////////////////
5014 /// Return the number of entries matching the selection.
5015 /// Return -1 in case of errors.
5016 ///
5017 /// If the selection uses any arrays or containers, we return the number
5018 /// of entries where at least one element match the selection.
5019 /// GetEntries is implemented using the selector class TSelectorEntries,
5020 /// which can be used directly (see code in TTreePlayer::GetEntries) for
5021 /// additional option.
5022 /// If SetEventList was used on the TTree or TChain, only that subset
5023 /// of entries will be considered.
5024 
5025 Long64_t TTree::GetEntries(const char *selection)
5027  GetPlayer();
5028  if (fPlayer) {
5029  return fPlayer->GetEntries(selection);
5030  }
5031  return -1;
5032 }
5033 
5034 ////////////////////////////////////////////////////////////////////////////////
5035 /// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5036 /// any branch in the list of friend trees.
5037 
5040  if (fEntries) return fEntries;
5041  if (!fFriends) return 0;
5043  if (!fr) return 0;
5044  TTree *t = fr->GetTree();
5045  if (t==0) return 0;
5046  return t->GetEntriesFriend();
5047 }
5048 
5049 ////////////////////////////////////////////////////////////////////////////////
5050 /// Read all branches of entry and return total number of bytes read.
5051 ///
5052 /// - `getall = 0` : get only active branches
5053 /// - `getall = 1` : get all branches
5054 ///
5055 /// The function returns the number of bytes read from the input buffer.
5056 /// If entry does not exist the function returns 0.
5057 /// If an I/O error occurs, the function returns -1.
5058 ///
5059 /// If the Tree has friends, also read the friends entry.
5060 ///
5061 /// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5062 /// For example, if you have a Tree with several hundred branches, and you
5063 /// are interested only by branches named "a" and "b", do
5064 /// ~~~ {.cpp}
5065 /// mytree.SetBranchStatus("*",0); //disable all branches
5066 /// mytree.SetBranchStatus("a",1);
5067 /// mytree.SetBranchStatus("b",1);
5068 /// ~~~
5069 /// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5070 ///
5071 /// __WARNING!!__
5072 /// If your Tree has been created in split mode with a parent branch "parent.",
5073 /// ~~~ {.cpp}
5074 /// mytree.SetBranchStatus("parent",1);
5075 /// ~~~
5076 /// will not activate the sub-branches of "parent". You should do:
5077 /// ~~~ {.cpp}
5078 /// mytree.SetBranchStatus("parent*",1);
5079 /// ~~~
5080 /// Without the trailing dot in the branch creation you have no choice but to
5081 /// call SetBranchStatus explicitly for each of the sub branches.
5082 ///
5083 /// An alternative is to call directly
5084 /// ~~~ {.cpp}
5085 /// brancha.GetEntry(i)
5086 /// branchb.GetEntry(i);
5087 /// ~~~
5088 /// ## IMPORTANT NOTE
5089 ///
5090 /// By default, GetEntry reuses the space allocated by the previous object
5091 /// for each branch. You can force the previous object to be automatically
5092 /// deleted if you call mybranch.SetAutoDelete(kTRUE) (default is kFALSE).
5093 ///
5094 /// Example:
5095 ///
5096 /// Consider the example in $ROOTSYS/test/Event.h
5097 /// The top level branch in the tree T is declared with:
5098 /// ~~~ {.cpp}
5099 /// Event *event = 0; //event must be null or point to a valid object
5100 /// //it must be initialized
5101 /// T.SetBranchAddress("event",&event);
5102 /// ~~~
5103 /// When reading the Tree, one can choose one of these 3 options:
5104 ///
5105 /// ## OPTION 1
5106 /// ~~~ {.cpp}
5107 /// for (Long64_t i=0;i<nentries;i++) {
5108 /// T.GetEntry(i);
5109 /// // the object event has been filled at this point
5110 /// }
5111 /// ~~~
5112 /// The default (recommended). At the first entry an object of the class
5113 /// Event will be created and pointed by event. At the following entries,
5114 /// event will be overwritten by the new data. All internal members that are
5115 /// TObject* are automatically deleted. It is important that these members
5116 /// be in a valid state when GetEntry is called. Pointers must be correctly
5117 /// initialized. However these internal members will not be deleted if the
5118 /// characters "->" are specified as the first characters in the comment
5119 /// field of the data member declaration.
5120 ///
5121 /// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5122 /// In this case, it is assumed that the pointer is never null (case of
5123 /// pointer TClonesArray *fTracks in the Event example). If "->" is not
5124 /// specified, the pointer member is read via buf >> pointer. In this case
5125 /// the pointer may be null. Note that the option with "->" is faster to
5126 /// read or write and it also consumes less space in the file.
5127 ///
5128 /// ## OPTION 2
5129 ///
5130 /// The option AutoDelete is set
5131 /// ~~~ {.cpp}
5132 /// TBranch *branch = T.GetBranch("event");
5133 /// branch->SetAddress(&event);
5134 /// branch->SetAutoDelete(kTRUE);
5135 /// for (Long64_t i=0;i<nentries;i++) {
5136 /// T.GetEntry(i);
5137 /// // the object event has been filled at this point
5138 /// }
5139 /// ~~~
5140 /// In this case, at each iteration, the object event is deleted by GetEntry
5141 /// and a new instance of Event is created and filled.
5142 ///
5143 /// ## OPTION 3
5144 /// ~~~ {.cpp}
5145 /// Same as option 1, but you delete yourself the event.
5146 ///
5147 /// for (Long64_t i=0;i<nentries;i++) {
5148 /// delete event;
5149 /// event = 0; // EXTREMELY IMPORTANT
5150 /// T.GetEntry(i);
5151 /// // the object event has been filled at this point
5152 /// }
5153 /// ~~~
5154 /// It is strongly recommended to use the default option 1. It has the
5155 /// additional advantage that functions like TTree::Draw (internally calling
5156 /// TTree::GetEntry) will be functional even when the classes in the file are
5157 /// not available.
5158 ///
5159 /// Note: See the comments in TBranchElement::SetAddress() for the
5160 /// object ownership policy of the underlying (user) data.
5161 
5164 
5165  // We already have been visited while recursively looking
5166  // through the friends tree, let return
5167  if (kGetEntry & fFriendLockStatus) return 0;
5168 
5169  if (entry < 0 || entry >= fEntries) return 0;
5170  Int_t i;
5171  Int_t nbytes = 0;
5172  fReadEntry = entry;
5173  TBranch *branch;
5174 
5175  // create cache if wanted
5177 
5178  Int_t nbranches = fBranches.GetEntriesFast();
5179  Int_t nb=0;
5180  for (i=0;i<nbranches;i++) {
5181  branch = (TBranch*)fBranches.UncheckedAt(i);
5182  nb = branch->GetEntry(entry, getall);
5183  if (nb < 0) return nb;
5184  nbytes += nb;
5185  }
5186 
5187  // GetEntry in list of friends
5188  if (!fFriends) return nbytes;
5189  TFriendLock lock(this,kGetEntry);
5190  TIter nextf(fFriends);
5191  TFriendElement *fe;
5192  while ((fe = (TFriendElement*)nextf())) {
5193  TTree *t = fe->GetTree();
5194  if (t) {
5196  nb = t->GetEntry(t->GetReadEntry(),getall);
5197  } else {
5198  if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5199  nb = t->GetEntry(t->GetReadEntry(),getall);
5200  } else nb = 0;
5201  }
5202  if (nb < 0) return nb;
5203  nbytes += nb;
5204  }
5205  }
5206  return nbytes;
5207 }
5208 
5209 ////////////////////////////////////////////////////////////////////////////////
5210 ///Returns the entry list, set to this tree
5211 
5214  return fEntryList;
5215 }
5216 
5217 ////////////////////////////////////////////////////////////////////////////////
5218 /// Return entry number corresponding to entry.
5219 ///
5220 /// if no TEntryList set returns entry
5221 /// else returns the entry number corresponding to the list index=entry
5222 
5225  if (!fEntryList) {
5226  return entry;
5227  }
5228 
5229  return fEntryList->GetEntry(entry);
5230 }
5231 
5232 ////////////////////////////////////////////////////////////////////////////////
5233 /// Return entry number corresponding to major and minor number.
5234 /// Note that this function returns only the entry number, not the data
5235 /// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5236 /// the BuildIndex function has created a table of Long64_t* of sorted values
5237 /// corresponding to val = major<<31 + minor;
5238 /// The function performs binary search in this sorted table.
5239 /// If it finds a pair that matches val, it returns directly the
5240 /// index in the table.
5241 /// If an entry corresponding to major and minor is not found, the function
5242 /// returns the index of the major,minor pair immediately lower than the
5243 /// requested value, ie it will return -1 if the pair is lower than
5244 /// the first entry in the index.
5245 ///
5246 /// See also GetEntryNumberWithIndex
5247 
5250  if (!fTreeIndex) {
5251  return -1;
5252  }
5253  return fTreeIndex->GetEntryNumberWithBestIndex(major, minor);
5254 }
5255 
5256 ////////////////////////////////////////////////////////////////////////////////
5257 /// Return entry number corresponding to major and minor number.
5258 /// Note that this function returns only the entry number, not the data
5259 /// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5260 /// the BuildIndex function has created a table of Long64_t* of sorted values
5261 /// corresponding to val = major<<31 + minor;
5262 /// The function performs binary search in this sorted table.
5263 /// If it finds a pair that matches val, it returns directly the
5264 /// index in the table, otherwise it returns -1.
5265 ///
5266 /// See also GetEntryNumberWithBestIndex
5267 
5270  if (!fTreeIndex) {
5271  return -1;
5272  }
5273  return fTreeIndex->GetEntryNumberWithIndex(major, minor);
5274 }
5275 
5276 ////////////////////////////////////////////////////////////////////////////////
5277 /// Read entry corresponding to major and minor number.
5278 ///
5279 /// The function returns the total number of bytes read.
5280 /// If the Tree has friend trees, the corresponding entry with
5281 /// the index values (major,minor) is read. Note that the master Tree
5282 /// and its friend may have different entry serial numbers corresponding
5283 /// to (major,minor).
5284 
5287  // We already have been visited while recursively looking
5288  // through the friends tree, let's return.
5290  return 0;
5291  }
5292  Long64_t serial = GetEntryNumberWithIndex(major, minor);
5293  if (serial < 0) {
5294  return -1;
5295  }
5296  // create cache if wanted
5298 
5299  Int_t i;
5300  Int_t nbytes = 0;
5301  fReadEntry = serial;
5302  TBranch *branch;
5303  Int_t nbranches = fBranches.GetEntriesFast();
5304  Int_t nb;
5305  for (i = 0; i < nbranches; ++i) {
5306  branch = (TBranch*)fBranches.UncheckedAt(i);
5307  nb = branch->GetEntry(serial);
5308  if (nb < 0) return nb;
5309  nbytes += nb;
5310  }
5311  // GetEntry in list of friends
5312  if (!fFriends) return nbytes;
5313  TFriendLock lock(this,kGetEntryWithIndex);
5314  TIter nextf(fFriends);
5315  TFriendElement* fe = 0;
5316  while ((fe = (TFriendElement*) nextf())) {
5317  TTree *t = fe->GetTree();
5318  if (t) {
5319  serial = t->GetEntryNumberWithIndex(major,minor);
5320  if (serial <0) return -nbytes;
5321  nb = t->GetEntry(serial);
5322  if (nb < 0) return nb;
5323  nbytes += nb;
5324  }
5325  }
5326  return nbytes;
5327 }
5328 
5329 ////////////////////////////////////////////////////////////////////////////////
5330 /// Return a pointer to the TTree friend whose name or alias is 'friendname.
5331 
5332 TTree* TTree::GetFriend(const char *friendname) const
5334 
5335  // We already have been visited while recursively
5336  // looking through the friends tree, let's return.
5337  if (kGetFriend & fFriendLockStatus) {
5338  return 0;
5339  }
5340  if (!fFriends) {
5341  return 0;
5342  }
5343  TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
5344  TIter nextf(fFriends);
5345  TFriendElement* fe = 0;
5346  while ((fe = (TFriendElement*) nextf())) {
5347  if (strcmp(friendname,fe->GetName())==0
5348  || strcmp(friendname,fe->GetTreeName())==0) {
5349  return fe->GetTree();
5350  }
5351  }
5352  // After looking at the first level,
5353  // let's see if it is a friend of friends.
5354  nextf.Reset();
5355  fe = 0;
5356  while ((fe = (TFriendElement*) nextf())) {
5357  TTree *res = fe->GetTree()->GetFriend(friendname);
5358  if (res) {
5359  return res;
5360  }
5361  }
5362  return 0;
5363 }
5364 
5365 ////////////////////////////////////////////////////////////////////////////////
5366 /// If the 'tree' is a friend, this method returns its alias name.
5367 ///
5368 /// This alias is an alternate name for the tree.
5369 ///
5370 /// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
5371 /// to specify in which particular tree the branch or leaf can be found if
5372 /// the friend trees have branches or leaves with the same name as the master
5373 /// tree.
5374 ///
5375 /// It can also be used in conjunction with an alias created using
5376 /// TTree::SetAlias in a TTreeFormula, e.g.:
5377 /// ~~~ {.cpp}
5378 /// maintree->Draw("treealias.fPx - treealias.myAlias");
5379 /// ~~~
5380 /// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
5381 /// was created using TTree::SetAlias on the friend tree.
5382 ///
5383 /// However, note that 'treealias.myAlias' will be expanded literally,
5384 /// without remembering that it comes from the aliased friend and thus
5385 /// the branch name might not be disambiguated properly, which means
5386 /// that you may not be able to take advantage of this feature.
5387 ///
5388 
5389 const char* TTree::GetFriendAlias(TTree* tree) const
5391  if ((tree == this) || (tree == GetTree())) {
5392  return 0;
5393  }
5394 
5395  // We already have been visited while recursively
5396  // looking through the friends tree, let's return.
5398  return 0;
5399  }
5400  if (!fFriends) {
5401  return 0;
5402  }
5403  TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
5404  TIter nextf(fFriends);
5405  TFriendElement* fe = 0;
5406  while ((fe = (TFriendElement*) nextf())) {
5407  TTree* t = fe->GetTree();
5408  if (t == tree) {
5409  return fe->GetName();
5410  }
5411  // Case of a chain:
5412  if (t->GetTree() == tree) {
5413  return fe->GetName();
5414  }
5415  }
5416  // After looking at the first level,
5417  // let's see if it is a friend of friends.
5418  nextf.Reset();
5419  fe = 0;
5420  while ((fe = (TFriendElement*) nextf())) {
5421  const char* res = fe->GetTree()->GetFriendAlias(tree);
5422  if (res) {
5423  return res;
5424  }
5425  }
5426  return 0;
5427 }
5428 
5429 ////////////////////////////////////////////////////////////////////////////////
5430 /// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
5431 
5434  return new TTreeFriendLeafIter(this, dir);
5435 }
5436 
5437 ////////////////////////////////////////////////////////////////////////////////
5438 /// Return pointer to the 1st Leaf named name in any Branch of this
5439 /// Tree or any branch in the list of friend trees.
5440 ///
5441 /// The leaf name can contain the name of a friend tree with the
5442 /// syntax: friend_dir_and_tree.full_leaf_name
5443 /// the friend_dir_and_tree can be of the form:
5444 /// ~~~ {.cpp}
5445 /// TDirectoryName/TreeName
5446 /// ~~~
5447 
5448 TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
5450  TLeaf *leaf = 0;
5451  if (branchname) {
5452  TBranch *branch = FindBranch(branchname);
5453  if (branch) {
5454  leaf = branch->GetLeaf(leafname);
5455  if (leaf) {
5456  return leaf;
5457  }
5458  }
5459  }
5460  TIter nextl(GetListOfLeaves());
5461  while ((leaf = (TLeaf*)nextl())) {
5462  if (strcmp(leaf->GetName(),leafname)) continue;
5463  if (branchname) {
5464  UInt_t nbch = strlen(branchname);
5465  TBranch *br = leaf->GetBranch();
5466  const char* brname = br->GetName();
5467  TBranch *mother = br->GetMother();
5468  if (strncmp(brname,branchname,nbch)) {
5469  if (mother != br) {
5470  const char *mothername = mother->GetName();
5471  UInt_t motherlen = strlen(mothername);
5472  if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
5473  // 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.
5474  if (strncmp(brname,branchname+motherlen+1,nbch-motherlen-1)) {
5475  // No it does not
5476  continue;
5477  } // else we have match so we can proceed.
5478  } else {
5479  // no match
5480  continue;
5481  }
5482  } else {
5483  continue;
5484  }
5485  }
5486  // The start of the branch name is identical to the content
5487  // of 'aname' before the first '/'.
5488  // Let's make sure that it is not longer (we are trying
5489  // to avoid having jet2/value match the branch jet23
5490  if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
5491  continue;
5492  }
5493  }
5494  return leaf;
5495  }
5496  if (!fFriends) return 0;
5497  TFriendLock lock(this,kGetLeaf);
5498  TIter next(fFriends);
5499  TFriendElement *fe;
5500  while ((fe = (TFriendElement*)next())) {
5501  TTree *t = fe->GetTree();
5502  if (t) {
5503  leaf = t->GetLeaf(leafname);
5504  if (leaf) return leaf;
5505  }
5506  }
5507 
5508  //second pass in the list of friends when the leaf name
5509  //is prefixed by the tree name
5510  TString strippedArg;
5511  next.Reset();
5512  while ((fe = (TFriendElement*)next())) {
5513  TTree *t = fe->GetTree();
5514  if (t==0) continue;
5515  char *subname = (char*)strstr(leafname,fe->GetName());
5516  if (subname != leafname) continue;
5517  Int_t l = strlen(fe->GetName());
5518  subname += l;
5519  if (*subname != '.') continue;
5520  subname++;
5521  strippedArg += subname;
5522  leaf = t->GetLeaf(branchname,subname);
5523  if (leaf) return leaf;
5524  }
5525  return 0;
5526 }
5527 
5528 ////////////////////////////////////////////////////////////////////////////////
5529 /// Return pointer to the 1st Leaf named name in any Branch of this
5530 /// Tree or any branch in the list of friend trees.
5531 ///
5532 /// The leaf name can contain the name of a friend tree with the
5533 /// syntax: friend_dir_and_tree.full_leaf_name
5534 /// the friend_dir_and_tree can be of the form:
5535 ///
5536 /// TDirectoryName/TreeName
5537 
5538 TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
5540  if (leafname == 0) return 0;
5541 
5542  // We already have been visited while recursively looking
5543  // through the friends tree, let return
5544  if (kGetLeaf & fFriendLockStatus) {
5545  return 0;
5546  }
5547 
5548  return GetLeafImpl(branchname,leafname);
5549 }
5550 
5551 ////////////////////////////////////////////////////////////////////////////////
5552 /// Return pointer to the 1st Leaf named name in any Branch of this
5553 /// Tree or any branch in the list of friend trees.
5554 ///
5555 /// aname may be of the form branchname/leafname
5556 
5557 TLeaf* TTree::GetLeaf(const char* aname)
5559  if (aname == 0) return 0;
5560 
5561  // We already have been visited while recursively looking
5562  // through the friends tree, let return
5563  if (kGetLeaf & fFriendLockStatus) {
5564  return 0;
5565  }
5566  char* slash = (char*) strrchr(aname, '/');
5567  char* name = 0;
5568  UInt_t nbch = 0;
5569  if (slash) {
5570  name = slash + 1;
5571  nbch = slash - aname;
5572  TString brname(aname,nbch);
5573  return GetLeafImpl(brname.Data(),name);
5574  } else {
5575  return GetLeafImpl(0,aname);
5576  }
5577 }
5578 
5579 ////////////////////////////////////////////////////////////////////////////////
5580 /// Return maximum of column with name columname.
5581 /// if the Tree has an associated TEventList or TEntryList, the maximum
5582 /// is computed for the entries in this list.
5583 
5584 Double_t TTree::GetMaximum(const char* columname)
5586  TLeaf* leaf = this->GetLeaf(columname);
5587  if (!leaf) {
5588  return 0;
5589  }
5590 
5591  // create cache if wanted
5593 
5594  TBranch* branch = leaf->GetBranch();
5595  Double_t cmax = -DBL_MAX;
5596  for (Long64_t i = 0; i < fEntries; ++i) {
5597  Long64_t entryNumber = this->GetEntryNumber(i);
5598  if (entryNumber < 0) break;
5599  branch->GetEntry(entryNumber);
5600  for (Int_t j = 0; j < leaf->GetLen(); ++j) {
5601  Double_t val = leaf->GetValue(j);
5602  if (val > cmax) {
5603  cmax = val;
5604  }
5605  }
5606  }
5607  return cmax;
5608 }
5609 
5610 ////////////////////////////////////////////////////////////////////////////////
5611 /// Static function which returns the tree file size limit in bytes.
5612 
5615  return fgMaxTreeSize;
5616 }
5617 
5618 ////////////////////////////////////////////////////////////////////////////////
5619 /// Return minimum of column with name columname.
5620 /// if the Tree has an associated TEventList or TEntryList, the minimum
5621 /// is computed for the entries in this list.
5622 
5623 Double_t TTree::GetMinimum(const char* columname)
5625  TLeaf* leaf = this->GetLeaf(columname);
5626  if (!leaf) {
5627  return 0;
5628  }
5629 
5630  // create cache if wanted
5632 
5633  TBranch* branch = leaf->GetBranch();
5634  Double_t cmin = DBL_MAX;
5635  for (Long64_t i = 0; i < fEntries; ++i) {
5636  Long64_t entryNumber = this->GetEntryNumber(i);
5637  if (entryNumber < 0) break;
5638  branch->GetEntry(entryNumber);
5639  for (Int_t j = 0;j < leaf->GetLen(); ++j) {
5640  Double_t val = leaf->GetValue(j);
5641  if (val < cmin) {
5642  cmin = val;
5643  }
5644  }
5645  }
5646  return cmin;
5647 }
5648 
5649 ////////////////////////////////////////////////////////////////////////////////
5650 /// Load the TTreePlayer (if not already done).
5651 
5654  if (fPlayer) {
5655  return fPlayer;
5656  }
5658  return fPlayer;
5659 }
5660 
5661 ////////////////////////////////////////////////////////////////////////////////
5662 /// Find and return the TTreeCache registered with the file and which may
5663 /// contain branches for us. If create is true and there is no cache
5664 /// a new cache is created with default size.
5665 
5666 TTreeCache *TTree::GetReadCache(TFile *file, Bool_t create /* = kFALSE */ )
5668  TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
5669  if (pe && pe->GetTree() != this) pe = 0;
5670  if (create && !pe) {
5672  pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
5673  if (pe && pe->GetTree() != this) pe = 0;
5674  }
5675  return pe;
5676 }
5677 
5678 ////////////////////////////////////////////////////////////////////////////////
5679 /// Return a pointer to the list containing user objects associated to this tree.
5680 ///
5681 /// The list is automatically created if it does not exist.
5682 ///
5683 /// WARNING: By default the TTree destructor will delete all objects added
5684 /// to this list. If you do not want these objects to be deleted,
5685 /// call:
5686 ///
5687 /// mytree->GetUserInfo()->Clear();
5688 ///
5689 /// before deleting the tree.
5690 
5693  if (!fUserInfo) {
5694  fUserInfo = new TList();
5695  fUserInfo->SetName("UserInfo");
5696  }
5697  return fUserInfo;
5698 }
5699 
5700 ////////////////////////////////////////////////////////////////////////////////
5701 /// Appends the cluster range information stored in 'fromtree' to this tree,
5702 /// including the value of fAutoFlush.
5703 ///
5704 /// This is used when doing a fast cloning (by TTreeCloner).
5705 /// See also fAutoFlush and fAutoSave if needed.
5706 
5707 void TTree::ImportClusterRanges(TTree *fromtree)
5709  Long64_t autoflush = fromtree->GetAutoFlush();
5710  if (fNClusterRange || fromtree->fNClusterRange) {
5711  Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
5712  if (newsize > fMaxClusterRange) {
5713  if (fMaxClusterRange) {
5715  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
5717  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
5718  fMaxClusterRange = newsize;
5719  } else {
5720  fMaxClusterRange = newsize;
5723  }
5724  }
5727  ++fNClusterRange;
5728  for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
5730  fClusterSize[fNClusterRange] = fromtree->fClusterSize[i];
5731  ++fNClusterRange;
5732  }
5733  fAutoFlush = autoflush;
5734  } else {
5735  SetAutoFlush( autoflush );
5736  }
5737  Long64_t autosave = GetAutoSave();
5738  if (autoflush > 0 && autosave > 0) {
5739  SetAutoSave( autoflush*(autosave/autoflush) );
5740  }
5741 }
5742 
5743 ////////////////////////////////////////////////////////////////////////////////
5744 /// Keep a maximum of fMaxEntries in memory.
5745 
5746 void TTree::KeepCircular()
5749  Long64_t maxEntries = fMaxEntries - (fMaxEntries / 10);
5750  for (Int_t i = 0; i < nb; ++i) {
5751  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
5752  branch->KeepCircular(maxEntries);
5753  }
5754  if (fNClusterRange) {
5755  Long64_t entriesOffset = fEntries - maxEntries;
5756  Int_t oldsize = fNClusterRange;
5757  for(Int_t i = 0, j = 0; j < oldsize; ++j) {
5758  if (fClusterRangeEnd[j] > entriesOffset) {
5759  fClusterRangeEnd[i] = fClusterRangeEnd[j] - entriesOffset;
5760  ++i;
5761  } else {
5762  --fNClusterRange;
5763  }
5764  }
5765  }
5766  fEntries = maxEntries;
5767  fReadEntry = -1;
5768 }
5769 
5770 ////////////////////////////////////////////////////////////////////////////////
5771 /// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
5772 ///
5773 /// If maxmemory is non null and positive SetMaxVirtualSize is called
5774 /// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
5775 /// The function returns the total number of baskets read into memory
5776 /// if negative an error occurred while loading the branches.
5777 /// This method may be called to force branch baskets in memory
5778 /// when random access to branch entries is required.
5779 /// If random access to only a few branches is required, you should
5780 /// call directly TBranch::LoadBaskets.
5781 
5784  if (maxmemory > 0) SetMaxVirtualSize(maxmemory);
5785 
5787  TLeaf *leaf;
5788  Int_t nimported = 0;
5789  while ((leaf=(TLeaf*)next())) {
5790  nimported += leaf->GetBranch()->LoadBaskets();//break;
5791  }
5792  return nimported;
5793 }
5794 
5795 ////////////////////////////////////////////////////////////////////////////////
5796 /// Set current entry.
5797 ///
5798 /// Returns -2 if entry does not exist (just as TChain::LoadTree()).
5799 ///
5800 /// Note: This function is overloaded in TChain.
5801 ///
5802 
5805  // We already have been visited while recursively looking
5806  // through the friends tree, let return
5807  if (kLoadTree & fFriendLockStatus) {
5808  // We need to return a negative value to avoid a circular list of friend
5809  // to think that there is always an entry somewhere in the list.
5810  return -1;
5811  }
5812 
5813  if (fNotify) {
5814  if (fReadEntry < 0) {
5815  fNotify->Notify();
5816  }
5817  }
5818  fReadEntry = entry;
5819 
5820  Bool_t friendHasEntry = kFALSE;
5821  if (fFriends) {
5822  // Set current entry in friends as well.
5823  //
5824  // An alternative would move this code to each of the
5825  // functions calling LoadTree (and to overload a few more).
5826  Bool_t needUpdate = kFALSE;
5827  {
5828  // This scope is need to insure the lock is released at the right time
5829  TIter nextf(fFriends);
5830  TFriendLock lock(this, kLoadTree);
5831  TFriendElement* fe = 0;
5832  while ((fe = (TFriendElement*) nextf())) {
5834  // This friend element was added by the chain that owns this
5835  // tree, the chain will deal with loading the correct entry.
5836  continue;
5837  }
5838  TTree* friendTree = fe->GetTree();
5839  if (friendTree == 0) {
5840  // Somehow we failed to retrieve the friend TTree.
5841  } else if (friendTree->IsA() == TTree::Class()) {
5842  // Friend is actually a tree.
5843  if (friendTree->LoadTreeFriend(entry, this) >= 0) {
5844  friendHasEntry = kTRUE;
5845  }
5846  } else {
5847  // Friend is actually a chain.
5848  // FIXME: This logic should be in the TChain override.
5849  Int_t oldNumber = friendTree->GetTreeNumber();
5850  if (friendTree->LoadTreeFriend(entry, this) >= 0) {
5851  friendHasEntry = kTRUE;
5852  }
5853  Int_t newNumber = friendTree->GetTreeNumber();
5854  if (oldNumber != newNumber) {
5855  // We can not just compare the tree pointers because they could be reused.
5856  // So we compare the tree number instead.
5857  needUpdate = kTRUE;
5858  }
5859  }
5860  } // for each friend
5861  }
5862  if (needUpdate) {
5863  //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
5864  if (fPlayer) {
5866  }
5867  //Notify user if requested
5868  if (fNotify) {
5869  fNotify->Notify();
5870  }
5871  }
5872  }
5873 
5874  if ((fReadEntry >= fEntries) && !friendHasEntry) {
5875  fReadEntry = -1;
5876  return -2;
5877  }
5878  return fReadEntry;
5879 }
5880 
5881 ////////////////////////////////////////////////////////////////////////////////
5882 /// Load entry on behalf of our master tree, we may use an index.
5883 ///
5884 /// Called by LoadTree() when the masterTree looks for the entry
5885 /// number in a friend tree (us) corresponding to the passed entry
5886 /// number in the masterTree.
5887 ///
5888 /// If we have no index, our entry number and the masterTree entry
5889 /// number are the same.
5890 ///
5891 /// If we *do* have an index, we must find the (major, minor) value pair
5892 /// in masterTree to locate our corresponding entry.
5893 ///
5894 
5897  if (!fTreeIndex) {
5898  return LoadTree(entry);
5899  }
5900  return LoadTree(fTreeIndex->GetEntryNumberFriend(masterTree));
5901 }
5902 
5903 ////////////////////////////////////////////////////////////////////////////////
5904 /// Generate a skeleton analysis class for this tree.
5905 ///
5906 /// The following files are produced: classname.h and classname.C.
5907 /// If classname is 0, classname will be called "nameoftree".
5908 ///
5909 /// The generated code in classname.h includes the following:
5910 ///
5911 /// - Identification of the original tree and the input file name.
5912 /// - Definition of an analysis class (data members and member functions).
5913 /// - The following member functions:
5914 /// - constructor (by default opening the tree file),
5915 /// - GetEntry(Long64_t entry),
5916 /// - Init(TTree* tree) to initialize a new TTree,
5917 /// - Show(Long64_t entry) to read and dump entry.
5918 ///
5919 /// The generated code in classname.C includes only the main
5920 /// analysis function Loop.
5921 ///
5922 /// To use this function:
5923 ///
5924 /// - Open your tree file (eg: TFile f("myfile.root");)
5925 /// - T->MakeClass("MyClass");
5926 ///
5927 /// where T is the name of the TTree in file myfile.root,
5928 /// and MyClass.h, MyClass.C the name of the files created by this function.
5929 /// In a ROOT session, you can do:
5930 /// ~~~ {.cpp}
5931 /// root > .L MyClass.C
5932 /// root > MyClass* t = new MyClass;
5933 /// root > t->GetEntry(12); // Fill data members of t with entry number 12.
5934 /// root > t->Show(); // Show values of entry 12.
5935 /// root > t->Show(16); // Read and show values of entry 16.
5936 /// root > t->Loop(); // Loop on all entries.
5937 /// ~~~
5938 /// NOTE: Do not use the code generated for a single TTree which is part
5939 /// of a TChain to process that entire TChain. The maximum dimensions
5940 /// calculated for arrays on the basis of a single TTree from the TChain
5941 /// might be (will be!) too small when processing all of the TTrees in
5942 /// the TChain. You must use myChain.MakeClass() to generate the code,
5943 /// not myTree.MakeClass(...).
5944 
5945 Int_t TTree::MakeClass(const char* classname, Option_t* option)
5947  GetPlayer();
5948  if (!fPlayer) {
5949  return 0;
5950  }
5951  return fPlayer->MakeClass(classname, option);
5952 }
5953 
5954 ////////////////////////////////////////////////////////////////////////////////
5955 /// Generate a skeleton function for this tree.
5956 ///
5957 /// The function code is written on filename.
5958 /// If filename is 0, filename will be called nameoftree.C
5959 ///
5960 /// The generated code includes the following:
5961 /// - Identification of the original Tree and Input file name,
5962 /// - Opening the Tree file,
5963 /// - Declaration of Tree variables,
5964 /// - Setting of branches addresses,
5965 /// - A skeleton for the entry loop.
5966 ///
5967 /// To use this function:
5968 ///
5969 /// - Open your Tree file (eg: TFile f("myfile.root");)
5970 /// - T->MakeCode("MyAnalysis.C");
5971 ///
5972 /// where T is the name of the TTree in file myfile.root
5973 /// and MyAnalysis.C the name of the file created by this function.
5974 ///
5975 /// NOTE: Since the implementation of this function, a new and better
5976 /// function TTree::MakeClass() has been developed.
5977 
5978 Int_t TTree::MakeCode(const char* filename)
5980  Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
5981 
5982  GetPlayer();
5983  if (!fPlayer) return 0;
5984  return fPlayer->MakeCode(filename);
5985 }
5986 
5987 ////////////////////////////////////////////////////////////////////////////////
5988 /// Generate a skeleton analysis class for this Tree using TBranchProxy.
5989 ///
5990 /// TBranchProxy is the base of a class hierarchy implementing an
5991 /// indirect access to the content of the branches of a TTree.
5992 ///
5993 /// "proxyClassname" is expected to be of the form:
5994 /// ~~~ {.cpp}
5995 /// [path/]fileprefix
5996 /// ~~~
5997 /// The skeleton will then be generated in the file:
5998 /// ~~~ {.cpp}
5999 /// fileprefix.h
6000 /// ~~~
6001 /// located in the current directory or in 'path/' if it is specified.
6002 /// The class generated will be named 'fileprefix'
6003 ///
6004 /// "macrofilename" and optionally "cutfilename" are expected to point
6005 /// to source files which will be included by the generated skeleton.
6006 /// Method of the same name as the file(minus the extension and path)
6007 /// will be called by the generated skeleton's Process method as follow:
6008 /// ~~~ {.cpp}
6009 /// [if (cutfilename())] htemp->Fill(macrofilename());
6010 /// ~~~
6011 /// "option" can be used select some of the optional features during
6012 /// the code generation. The possible options are:
6013 ///
6014 /// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6015 ///
6016 /// 'maxUnrolling' controls how deep in the class hierarchy does the
6017 /// system 'unroll' classes that are not split. Unrolling a class
6018 /// allows direct access to its data members (this emulates the behavior
6019 /// of TTreeFormula).
6020 ///
6021 /// The main features of this skeleton are:
6022 ///
6023 /// * on-demand loading of branches
6024 /// * ability to use the 'branchname' as if it was a data member
6025 /// * protection against array out-of-bounds errors
6026 /// * ability to use the branch data as an object (when the user code is available)
6027 ///
6028 /// For example with Event.root, if
6029 /// ~~~ {.cpp}
6030 /// Double_t somePx = fTracks.fPx[2];
6031 /// ~~~
6032 /// is executed by one of the method of the skeleton,
6033 /// somePx will updated with the current value of fPx of the 3rd track.
6034 ///
6035 /// Both macrofilename and the optional cutfilename are expected to be
6036 /// the name of source files which contain at least a free standing
6037 /// function with the signature:
6038 /// ~~~ {.cpp}
6039 /// x_t macrofilename(); // i.e function with the same name as the file
6040 /// ~~~
6041 /// and
6042 /// ~~~ {.cpp}
6043 /// y_t cutfilename(); // i.e function with the same name as the file
6044 /// ~~~
6045 /// x_t and y_t needs to be types that can convert respectively to a double
6046 /// and a bool (because the skeleton uses:
6047 ///
6048 /// if (cutfilename()) htemp->Fill(macrofilename());
6049 ///
6050 /// These two functions are run in a context such that the branch names are
6051 /// available as local variables of the correct (read-only) type.
6052 ///
6053 /// Note that if you use the same 'variable' twice, it is more efficient
6054 /// to 'cache' the value. For example:
6055 /// ~~~ {.cpp}
6056 /// Int_t n = fEventNumber; // Read fEventNumber
6057 /// if (n<10 || n>10) { ... }
6058 /// ~~~
6059 /// is more efficient than
6060 /// ~~~ {.cpp}
6061 /// if (fEventNumber<10 || fEventNumber>10)
6062 /// ~~~
6063 /// Also, optionally, the generated selector will also call methods named
6064 /// macrofilename_methodname in each of 6 main selector methods if the method
6065 /// macrofilename_methodname exist (Where macrofilename is stripped of its
6066 /// extension).
6067 ///
6068 /// Concretely, with the script named h1analysisProxy.C,
6069 ///
6070 /// - The method calls the method (if it exist)
6071 /// - Begin -> void h1analysisProxy_Begin(TTree*);
6072 /// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6073 /// - Notify -> Bool_t h1analysisProxy_Notify();
6074 /// - Process -> Bool_t h1analysisProxy_Process(Long64_t);
6075 /// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6076 /// - Terminate -> void h1analysisProxy_Terminate();
6077 ///
6078 /// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6079 /// it is included before the declaration of the proxy class. This can
6080 /// be used in particular to insure that the include files needed by
6081 /// the macro file are properly loaded.
6082 ///
6083 /// The default histogram is accessible via the variable named 'htemp'.
6084 ///
6085 /// If the library of the classes describing the data in the branch is
6086 /// loaded, the skeleton will add the needed #include statements and
6087 /// give the ability to access the object stored in the branches.
6088 ///
6089 /// To draw px using the file hsimple.root (generated by the
6090 /// hsimple.C tutorial), we need a file named hsimple.cxx:
6091 /// ~~~ {.cpp}
6092 /// double hsimple() {
6093 /// return px;
6094 /// }
6095 /// ~~~
6096 /// MakeProxy can then be used indirectly via the TTree::Draw interface
6097 /// as follow:
6098 /// ~~~ {.cpp}
6099 /// new TFile("hsimple.root")
6100 /// ntuple->Draw("hsimple.cxx");
6101 /// ~~~
6102 /// A more complete example is available in the tutorials directory:
6103 /// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6104 /// which reimplement the selector found in h1analysis.C
6105 
6106 Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6108  GetPlayer();
6109  if (!fPlayer) return 0;
6110  return fPlayer->MakeProxy(proxyClassname,macrofilename,cutfilename,option,maxUnrolling);
6111 }
6112 
6113 ////////////////////////////////////////////////////////////////////////////////
6114 /// Generate skeleton selector class for this tree.
6115 ///
6116 /// The following files are produced: selector.h and selector.C.
6117 /// If selector is 0, the selector will be called "nameoftree".
6118 /// The option can be used to specify the branches that will have a data member.
6119 /// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6120 /// members and branch pointers instead of TTreeReaders).
6121 /// - If option is empty, readers will be generated for each leaf.
6122 /// - If option is "@", readers will be generated for the topmost branches.
6123 /// - Individual branches can also be picked by their name:
6124 /// - "X" generates readers for leaves of X.
6125 /// - "@X" generates a reader for X as a whole.
6126 /// - "@X;Y" generates a reader for X as a whole and also readers for the
6127 /// leaves of Y.
6128 /// - For further examples see the figure below.
6129 ///
6130 /// \image html ttree_makeselector_option_examples.png
6131 ///
6132 /// The generated code in selector.h includes the following:
6133 /// - Identification of the original Tree and Input file name
6134 /// - Definition of selector class (data and functions)
6135 /// - The following class functions:
6136 /// - constructor and destructor
6137 /// - void Begin(TTree *tree)
6138 /// - void SlaveBegin(TTree *tree)
6139 /// - void Init(TTree *tree)
6140 /// - Bool_t Notify()
6141 /// - Bool_t Process(Long64_t entry)
6142 /// - void Terminate()
6143 /// - void SlaveTerminate()
6144 ///
6145 /// The class selector derives from TSelector.
6146 /// The generated code in selector.C includes empty functions defined above.
6147 ///
6148 /// To use this function:
6149 ///
6150 /// - connect your Tree file (eg: `TFile f("myfile.root");`)
6151 /// - `T->MakeSelector("myselect");`
6152 ///
6153 /// where T is the name of the Tree in file myfile.root
6154 /// and myselect.h, myselect.C the name of the files created by this function.
6155 /// In a ROOT session, you can do:
6156 /// ~~~ {.cpp}
6157 /// root > T->Process("myselect.C")
6158 /// ~~~
6159 
6160 Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6162  TString opt(option);
6163  if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6164  return MakeClass(selector, "selector");
6165  } else {
6166  GetPlayer();
6167  if (!fPlayer) return 0;
6168  return fPlayer->MakeReader(selector, option);
6169  }
6170 }
6171 
6172 ////////////////////////////////////////////////////////////////////////////////
6173 /// Check if adding nbytes to memory we are still below MaxVirtualsize.
6174 
6177  if ((fTotalBuffers + nbytes) < fMaxVirtualSize) {
6178  return kFALSE;
6179  }
6180  return kTRUE;
6181 }
6182 
6183 ////////////////////////////////////////////////////////////////////////////////
6184 /// Static function merging the trees in the TList into a new tree.
6185 ///
6186 /// Trees in the list can be memory or disk-resident trees.
6187 /// The new tree is created in the current directory (memory if gROOT).
6188 
6189 TTree* TTree::MergeTrees(TList* li, Option_t* options)
6191  if (!li) return 0;
6192  TIter next(li);
6193  TTree *newtree = 0;
6194  TObject *obj;
6195 
6196  while ((obj=next())) {
6197  if (!obj->InheritsFrom(TTree::Class())) continue;
6198  TTree *tree = (TTree*)obj;
6199  Long64_t nentries = tree->GetEntries();
6200  if (nentries == 0) continue;
6201  if (!newtree) {
6202  newtree = (TTree*)tree->CloneTree();
6203  if (!newtree) continue;
6204 
6205  // Once the cloning is done, separate the trees,
6206  // to avoid as many side-effects as possible
6207  // The list of clones is guaranteed to exist since we
6208  // just cloned the tree.
6209  tree->GetListOfClones()->Remove(newtree);
6210  tree->ResetBranchAddresses();
6211  newtree->ResetBranchAddresses();
6212  continue;
6213  }
6214 
6215  newtree->CopyAddresses(tree);
6216 
6217  newtree->CopyEntries(tree,-1,options);
6218 
6219  tree->ResetBranchAddresses(); // Disconnect from new tree.
6220  }
6221  if (newtree && newtree->GetTreeIndex()) {
6222  newtree->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
6223  }
6224  return newtree;
6225 }
6226 
6227 ////////////////////////////////////////////////////////////////////////////////
6228 /// Merge the trees in the TList into this tree.
6229 ///
6230 /// Returns the total number of entries in the merged tree.
6231 
6234  if (!li) return 0;
6235  Long64_t storeAutoSave = fAutoSave;
6236  // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6237  // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6238  // Also since this is part of a merging operation, the output file is not as precious as in
6239  // the general case since the input file should still be around.
6240  fAutoSave = 0;
6241  TIter next(li);
6242  TTree *tree;
6243  while ((tree = (TTree*)next())) {
6244  if (tree==this) continue;
6245  if (!tree->InheritsFrom(TTree::Class())) {
6246  Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6247  fAutoSave = storeAutoSave;
6248  return -1;
6249  }
6250 
6251  Long64_t nentries = tree->GetEntries();
6252  if (nentries == 0) continue;
6253 
6254  CopyAddresses(tree);
6255 
6256  CopyEntries(tree,-1,options);
6257 
6258  tree->ResetBranchAddresses();
6259  }
6260  fAutoSave = storeAutoSave;
6261  return GetEntries();
6262 }
6263 
6264 ////////////////////////////////////////////////////////////////////////////////
6265 /// Merge the trees in the TList into this tree.
6266 /// If info->fIsFirst is true, first we clone this TTree info the directory
6267 /// info->fOutputDirectory and then overlay the new TTree information onto
6268 /// this TTree object (so that this TTree object is now the appropriate to
6269 /// use for further merging).
6270 ///
6271 /// Returns the total number of entries in the merged tree.
6272 
6275  const char *options = info ? info->fOptions.Data() : "";
6276  if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
6278  TTree *newtree = CloneTree(-1, options);
6279  if (newtree) {
6280  newtree->Write();
6281  delete newtree;
6282  }
6283  // Make sure things are really written out to disk before attempting any reading.
6284  info->fOutputDirectory->GetFile()->Flush();
6285  info->fOutputDirectory->ReadTObject(this,this->GetName());
6286  }
6287  if (!li) return 0;
6288  Long64_t storeAutoSave = fAutoSave;
6289  // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6290  // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6291  // Also since this is part of a merging operation, the output file is not as precious as in
6292  // the general case since the input file should still be around.
6293  fAutoSave = 0;
6294  TIter next(li);
6295  TTree *tree;
6296  while ((tree = (TTree*)next())) {
6297  if (tree==this) continue;
6298  if (!tree->InheritsFrom(TTree::Class())) {
6299  Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6300  fAutoSave = storeAutoSave;
6301  return -1;
6302  }
6303  // Copy MakeClass status.
6304  tree->SetMakeClass(fMakeClass);
6305 
6306  // Copy branch addresses.
6307  CopyAddresses(tree);
6308 
6309  CopyEntries(tree,-1,options);
6310 
6311  tree->ResetBranchAddresses();
6312  }
6313  fAutoSave = storeAutoSave;
6314  return GetEntries();
6315 }
6316 
6317 ////////////////////////////////////////////////////////////////////////////////
6318 /// Move a cache from a file to the current file in dir.
6319 /// if src is null no operation is done, if dir is null or there is no
6320 /// current file the cache is deleted.
6321 
6322 void TTree::MoveReadCache(TFile *src, TDirectory *dir)
6324  if (!src) return;
6325  TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : 0;
6326  if (src == dst) return;
6327 
6328  TTreeCache *pf = GetReadCache(src);
6329  if (dst) {
6330  src->SetCacheRead(0,this);
6331  dst->SetCacheRead(pf, this);
6332  } else {
6333  if (pf) {
6334  pf->WaitFinishPrefetch();
6335  }
6336  src->SetCacheRead(0,this);
6337  delete pf;
6338  }
6339 }
6340 
6341 ////////////////////////////////////////////////////////////////////////////////
6342 /// Function called when loading a new class library.
6343 
6347  TLeaf* leaf = 0;
6348  while ((leaf = (TLeaf*) next())) {
6349  leaf->Notify();
6350  leaf->GetBranch()->Notify();
6351  }
6352  return kTRUE;
6353 }
6354 
6355 ////////////////////////////////////////////////////////////////////////////////
6356 /// This function may be called after having filled some entries in a Tree
6357 /// Using the information in the existing branch buffers, it will reassign
6358 /// new branch buffer sizes to optimize time and memory.
6359 ///
6360 /// The function computes the best values for branch buffer sizes such that
6361 /// the total buffer sizes is less than maxMemory and nearby entries written
6362 /// at the same time.
6363 /// In case the branch compression factor for the data written so far is less
6364 /// than compMin, the compression is disabled.
6365 ///
6366 /// if option ="d" an analysis report is printed.
6367 
6368 void TTree::OptimizeBaskets(ULong64_t maxMemory, Float_t minComp, Option_t *option)
6370  //Flush existing baskets if the file is writable
6371  if (this->GetDirectory()->IsWritable()) this->FlushBaskets();
6372 
6373  TString opt( option );
6374  opt.ToLower();
6375  Bool_t pDebug = opt.Contains("d");
6376  TObjArray *leaves = this->GetListOfLeaves();
6377  Int_t nleaves = leaves->GetEntries();
6378  Double_t treeSize = (Double_t)this->GetTotBytes();
6379 
6380  if (nleaves == 0 || treeSize == 0) {
6381  // We're being called too early, we really have nothing to do ...
6382  return;
6383  }
6384  Double_t aveSize = treeSize/nleaves;
6385  UInt_t bmin = 512;
6386  UInt_t bmax = 256000;
6387  Double_t memFactor = 1;
6388  Int_t i, oldMemsize,newMemsize,oldBaskets,newBaskets;
6389  i = oldMemsize = newMemsize = oldBaskets = newBaskets = 0;
6390 
6391  //we make two passes
6392  //one pass to compute the relative branch buffer sizes
6393  //a second pass to compute the absolute values
6394  for (Int_t pass =0;pass<2;pass++) {
6395  oldMemsize = 0; //to count size of baskets in memory with old buffer size
6396  newMemsize = 0; //to count size of baskets in memory with new buffer size
6397  oldBaskets = 0; //to count number of baskets with old buffer size
6398  newBaskets = 0; //to count number of baskets with new buffer size
6399  for (i=0;i<nleaves;i++) {
6400  TLeaf *leaf = (TLeaf*)leaves->At(i);
6401  TBranch *branch = leaf->GetBranch();
6402  Double_t totBytes = (Double_t)branch->GetTotBytes();
6403  Double_t idealFactor = totBytes/aveSize;
6404  UInt_t sizeOfOneEntry;
6405  if (branch->GetEntries() == 0) {
6406  // There is no data, so let's make a guess ...
6407  sizeOfOneEntry = aveSize;
6408  } else {
6409  sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
6410  }
6411  Int_t oldBsize = branch->GetBasketSize();
6412  oldMemsize += oldBsize;
6413  oldBaskets += 1+Int_t(totBytes/oldBsize);
6414  Int_t nb = branch->GetListOfBranches()->GetEntries();
6415  if (nb > 0) {
6416  newBaskets += 1+Int_t(totBytes/oldBsize);
6417  continue;
6418  }
6419  Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
6420  if (bsize < 0) bsize = bmax;
6421  if (bsize > bmax) bsize = bmax;
6422  UInt_t newBsize = UInt_t(bsize);
6423  newBsize = newBsize - newBsize%512;
6424  if (newBsize < sizeOfOneEntry) newBsize = sizeOfOneEntry;
6425  if (newBsize < bmin) newBsize = bmin;
6426  if (newBsize > 10000000) newBsize = bmax;
6427  if (pass) {
6428  if (pDebug) printf("Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
6429  branch->SetBasketSize(newBsize);
6430  }
6431  newMemsize += newBsize;
6432  // For this number to be somewhat accurate when newBsize is 'low'
6433  // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
6434  // not let it be lower than 100+TBranch::fEntryOffsetLen.
6435  newBaskets += 1+Int_t(totBytes/newBsize);
6436  if (pass == 0) continue;
6437  //Reset the compression level in case the compression factor is small
6438  Double_t comp = 1;
6439  if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
6440  if (comp > 1 && comp < minComp) {
6441  if (pDebug) printf("Disabling compression for branch : %s\n",branch->GetName());
6442  branch->SetCompressionSettings(0);
6443  }
6444  }
6445  // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
6446  memFactor = Double_t(maxMemory)/Double_t(newMemsize);
6447  if (memFactor > 100) memFactor = 100;
6448  Double_t bmin_new = bmin*memFactor;
6449  Double_t bmax_new = bmax*memFactor;
6450  static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
6451 
6452  // Really, really never go lower than 8 bytes (we use this number
6453  // so that the calculation of the number of basket is consistent
6454  // but in fact SetBasketSize will not let the size go below
6455  // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
6456  // (The 2nd part being a slight over estimate of the key length.
6457  static const UInt_t hardmin = 8;
6458  bmin = (bmin_new > hardmax) ? hardmax : ( bmin_new < hardmin ? hardmin : (UInt_t)bmin_new );
6459  bmax = (bmax_new > hardmax) ? bmin : (UInt_t)bmax_new;
6460  }
6461  if (pDebug) {
6462  printf("oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
6463  printf("oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
6464  }
6465 }
6466 
6467 ////////////////////////////////////////////////////////////////////////////////
6468 /// Interface to the Principal Components Analysis class.
6469 ///
6470 /// Create an instance of TPrincipal
6471 ///
6472 /// Fill it with the selected variables
6473 ///
6474 /// - if option "n" is specified, the TPrincipal object is filled with
6475 /// normalized variables.
6476 /// - If option "p" is specified, compute the principal components
6477 /// - If option "p" and "d" print results of analysis
6478 /// - If option "p" and "h" generate standard histograms
6479 /// - If option "p" and "c" generate code of conversion functions
6480 /// - return a pointer to the TPrincipal object. It is the user responsibility
6481 /// - to delete this object.
6482 /// - The option default value is "np"
6483 ///
6484 /// see TTree::Draw for explanation of the other parameters.
6485 ///
6486 /// The created object is named "principal" and a reference to it
6487 /// is added to the list of specials Root objects.
6488 /// you can retrieve a pointer to the created object via:
6489 /// ~~~ {.cpp}
6490 /// TPrincipal *principal =
6491 /// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
6492 /// ~~~
6493 
6494 TPrincipal* TTree::Principal(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
6496  GetPlayer();
6497  if (fPlayer) {
6498  return fPlayer->Principal(varexp, selection, option, nentries, firstentry);
6499  }
6500  return 0;
6501 }
6502 
6503 ////////////////////////////////////////////////////////////////////////////////
6504 /// Print a summary of the tree contents.
6505 ///
6506 /// - If option contains "all" friend trees are also printed.
6507 /// - If option contains "toponly" only the top level branches are printed.
6508 /// - If option contains "clusters" information about the cluster of baskets is printed.
6509 ///
6510 /// Wildcarding can be used to print only a subset of the branches, e.g.,
6511 /// `T.Print("Elec*")` will print all branches with name starting with "Elec".
6512 
6513 void TTree::Print(Option_t* option) const
6515  // We already have been visited while recursively looking
6516  // through the friends tree, let's return.
6517  if (kPrint & fFriendLockStatus) {
6518  return;
6519  }
6520  Int_t s = 0;
6521  Int_t skey = 0;
6522  if (fDirectory) {
6523  TKey* key = fDirectory->GetKey(GetName());
6524  if (key) {
6525  skey = key->GetKeylen();
6526  s = key->GetNbytes();
6527  }
6528  }
6529  Long64_t total = skey;
6530  if (fZipBytes > 0) {
6531  total += fTotBytes;
6532  }
6533  TBufferFile b(TBuffer::kWrite, 10000);
6534  TTree::Class()->WriteBuffer(b, (TTree*) this);
6535  total += b.Length();
6536  Long64_t file = fZipBytes + s;
6537  Float_t cx = 1;
6538  if (fZipBytes) {
6539  cx = (fTotBytes + 0.00001) / fZipBytes;
6540  }
6541  Printf("******************************************************************************");
6542  Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
6543  Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
6544  Printf("* : : Tree compression factor = %6.2f *", cx);
6545  Printf("******************************************************************************");
6546 
6547  if (strncmp(option,"clusterRange",strlen("clusters"))==0) {
6548  Printf("%-16s %-16s %-16s %5s",
6549  "Cluster Range #", "Entry Start", "Last Entry", "Size");
6550  Int_t index= 0;
6551  Long64_t clusterRangeStart = 0;
6552  if (fNClusterRange) {
6553  for( ; index < fNClusterRange; ++index) {
6554  Printf("%-16d %-16lld %-16lld %5lld",
6555  index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
6556  clusterRangeStart = fClusterRangeEnd[index] + 1;
6557  }
6558  }
6559  Printf("%-16d %-16lld %-16lld %5lld",
6560  index, clusterRangeStart, fEntries - 1, fAutoFlush);
6561  return;
6562  }
6563 
6564  Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
6565  Int_t l;
6566  TBranch* br = 0;
6567  TLeaf* leaf = 0;
6568  if (strstr(option, "toponly")) {
6569  Long64_t *count = new Long64_t[nl];
6570  Int_t keep =0;
6571  for (l=0;l<nl;l++) {
6572  leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
6573  br = leaf->GetBranch();
6574  if (strchr(br->GetName(),'.')) {
6575  count[l] = -1;
6576  count[keep] += br->GetZipBytes();
6577  } else {
6578  keep = l;
6579  count[keep] = br->GetZipBytes();
6580  }
6581  }
6582  for (l=0;l<nl;l++) {
6583  if (count[l] < 0) continue;
6584  leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
6585  br = leaf->GetBranch();
6586  printf("branch: %-20s %9lld\n",br->GetName(),count[l]);
6587  }
6588  delete [] count;
6589  } else {
6590  TString reg = "*";
6591  if (strlen(option) && strchr(option,'*')) reg = option;
6592  TRegexp re(reg,kTRUE);
6593  TIter next(const_cast<TTree*>(this)->GetListOfBranches());
6595  while ((br= (TBranch*)next())) {
6596  TString st = br->GetName();
6597  st.ReplaceAll("/","_");
6598  if (st.Index(re) == kNPOS) continue;
6599  br->Print(option);
6600  }
6601  }
6602 
6603  //print TRefTable (if one)
6604  if (fBranchRef) fBranchRef->Print(option);
6605 
6606  //print friends if option "all"
6607  if (!fFriends || !strstr(option,"all")) return;
6608  TIter nextf(fFriends);
6609  TFriendLock lock(const_cast<TTree*>(this),kPrint);
6610  TFriendElement *fr;
6611  while ((fr = (TFriendElement*)nextf())) {
6612  TTree * t = fr->GetTree();
6613  if (t) t->Print(option);
6614  }
6615 }
6616 
6617 ////////////////////////////////////////////////////////////////////////////////
6618 /// print statistics about the TreeCache for this tree, like
6619 /// ~~~ {.cpp}
6620 /// ******TreeCache statistics for file: cms2.root ******
6621 /// Reading 73921562 bytes in 716 transactions
6622 /// Average transaction = 103.242405 Kbytes
6623 /// Number of blocks in current cache: 202, total size : 6001193
6624 /// ~~~
6625 /// if option = "a" the list of blocks in the cache is printed
6626 
6627 void TTree::PrintCacheStats(Option_t* option) const
6629  TFile *f = GetCurrentFile();
6630  if (!f) return;
6631  TTreeCache *tc = (TTreeCache*)f->GetCacheRead(const_cast<TTree*>(this));
6632  if (tc) tc->Print(option);
6633 }
6634 
6635 ////////////////////////////////////////////////////////////////////////////////
6636 /// Process this tree executing the TSelector code in the specified filename.
6637 /// The return value is -1 in case of error and TSelector::GetStatus() in
6638 /// in case of success.
6639 ///
6640 /// The code in filename is loaded (interpreted or compiled, see below),
6641 /// filename must contain a valid class implementation derived from TSelector,
6642 /// where TSelector has the following member functions:
6643 ///
6644 /// - `Begin()`: called every time a loop on the tree starts,
6645 /// a convenient place to create your histograms.
6646 /// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
6647 /// slave servers.
6648 /// - `Process()`: called for each event, in this function you decide what
6649 /// to read and fill your histograms.
6650 /// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
6651 /// called only on the slave servers.
6652 /// - `Terminate()`: called at the end of the loop on the tree,
6653 /// a convenient place to draw/fit your histograms.
6654 ///
6655 /// If filename is of the form file.C, the file will be interpreted.
6656 ///
6657 /// If filename is of the form file.C++, the file file.C will be compiled
6658 /// and dynamically loaded.
6659 ///
6660 /// If filename is of the form file.C+, the file file.C will be compiled
6661 /// and dynamically loaded. At next call, if file.C is older than file.o
6662 /// and file.so, the file.C is not compiled, only file.so is loaded.
6663 ///
6664 /// ## NOTE1
6665 ///
6666 /// It may be more interesting to invoke directly the other Process function
6667 /// accepting a TSelector* as argument.eg
6668 /// ~~~ {.cpp}
6669 /// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
6670 /// selector->CallSomeFunction(..);
6671 /// mytree.Process(selector,..);
6672 /// ~~~
6673 /// ## NOTE2
6674 //
6675 /// One should not call this function twice with the same selector file
6676 /// in the same script. If this is required, proceed as indicated in NOTE1,
6677 /// by getting a pointer to the corresponding TSelector,eg
6678 ///
6679 /// ### workaround 1
6680 /// ~~~ {.cpp}
6681 /// void stubs1() {
6682 /// TSelector *selector = TSelector::GetSelector("h1test.C");
6683 /// TFile *f1 = new TFile("stubs_nood_le1.root");
6684 /// TTree *h1 = (TTree*)f1->Get("h1");
6685 /// h1->Process(selector);
6686 /// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
6687 /// TTree *h2 = (TTree*)f2->Get("h1");
6688 /// h2->Process(selector);
6689 /// }
6690 /// ~~~
6691 /// or use ACLIC to compile the selector
6692 ///
6693 /// ### workaround 2
6694 /// ~~~ {.cpp}
6695 /// void stubs2() {
6696 /// TFile *f1 = new TFile("stubs_nood_le1.root");
6697 /// TTree *h1 = (TTree*)f1->Get("h1");
6698 /// h1->Process("h1test.C+");
6699 /// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
6700 /// TTree *h2 = (TTree*)f2->Get("h1");
6701 /// h2->Process("h1test.C+");
6702 /// }
6703 /// ~~~
6704 
6705 Long64_t TTree::Process(const char* filename, Option_t* option, Long64_t nentries, Long64_t firstentry)
6707  GetPlayer();
6708  if (fPlayer) {
6709  return fPlayer->Process(filename, option, nentries, firstentry);
6710  }
6711  return -1;
6712 }
6713 
6714 ////////////////////////////////////////////////////////////////////////////////
6715 /// Process this tree executing the code in the specified selector.
6716 /// The return value is -1 in case of error and TSelector::GetStatus() in
6717 /// in case of success.
6718 ///
6719 /// The TSelector class has the following member functions:
6720 ///
6721 /// - `Begin()`: called every time a loop on the tree starts,
6722 /// a convenient place to create your histograms.
6723 /// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
6724 /// slave servers.
6725 /// - `Process()`: called for each event, in this function you decide what
6726 /// to read and fill your histograms.
6727 /// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
6728 /// called only on the slave servers.
6729 /// - `Terminate()`: called at the end of the loop on the tree,
6730 /// a convenient place to draw/fit your histograms.
6731 ///
6732 /// If the Tree (Chain) has an associated EventList, the loop is on the nentries
6733 /// of the EventList, starting at firstentry, otherwise the loop is on the
6734 /// specified Tree entries.
6735 
6736 Long64_t TTree::Process(TSelector* selector, Option_t* option, Long64_t nentries, Long64_t firstentry)
6738  GetPlayer();
6739  if (fPlayer) {
6740  return fPlayer->Process(selector, option, nentries, firstentry);
6741  }
6742  return -1;
6743 }
6744 
6745 ////////////////////////////////////////////////////////////////////////////////
6746 /// Make a projection of a tree using selections.
6747 ///
6748 /// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
6749 /// projection of the tree will be filled in histogram hname.
6750 /// Note that the dimension of hname must match with the dimension of varexp.
6751 ///
6752 
6753 Long64_t TTree::Project(const char* hname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
6755  TString var;
6756  var.Form("%s>>%s", varexp, hname);
6757  TString opt("goff");
6758  if (option) {
6759  opt.Form("%sgoff", option);
6760  }
6761  Long64_t nsel = Draw(var, selection, opt, nentries, firstentry);
6762  return nsel;
6763 }
6764 
6765 ////////////////////////////////////////////////////////////////////////////////
6766 /// Loop over entries and return a TSQLResult object containing entries following selection.
6767 
6768 TSQLResult* TTree::Query(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
6770  GetPlayer();
6771  if (fPlayer) {
6772  return fPlayer->Query(varexp, selection, option, nentries, firstentry);
6773  }
6774  return 0;
6775 }
6776 
6777 ////////////////////////////////////////////////////////////////////////////////
6778 /// Create or simply read branches from filename.
6779 ///
6780 /// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
6781 /// is given in the first line of the file with a syntax like
6782 /// ~~~ {.cpp}
6783 /// A/D:Table[2]/F:Ntracks/I:astring/C
6784 /// ~~~
6785 /// otherwise branchDescriptor must be specified with the above syntax.
6786 ///
6787 /// - If the type of the first variable is not specified, it is assumed to be "/F"
6788 /// - If the type of any other variable is not specified, the type of the previous
6789 /// variable is assumed. eg
6790 /// - `x:y:z` (all variables are assumed of type "F"
6791 /// - `x/D:y:z` (all variables are of type "D"
6792 /// - `x:y/D:z` (x is type "F", y and z of type "D"
6793 ///
6794 /// delimiter allows for the use of another delimiter besides whitespace.
6795 /// This provides support for direct import of common data file formats
6796 /// like csv. If delimiter != ' ' and branchDescriptor == "", then the
6797 /// branch description is taken from the first line in the file, but
6798 /// delimiter is used for the branch names tokenization rather than ':'.
6799 /// Note however that if the values in the first line do not use the
6800 /// /[type] syntax, all variables are assumed to be of type "F".
6801 /// If the filename ends with extensions .csv or .CSV and a delimiter is
6802 /// not specified (besides ' '), the delimiter is automatically set to ','.
6803 ///
6804 /// Lines in the input file starting with "#" are ignored. Leading whitespace
6805 /// for each column data is skipped. Empty lines are skipped.
6806 ///
6807 /// A TBranch object is created for each variable in the expression.
6808 /// The total number of rows read from the file is returned.
6809 ///
6810 /// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
6811 ///
6812 /// To fill a TTree with multiple input text files, proceed as indicated above
6813 /// for the first input file and omit the second argument for subsequent calls
6814 /// ~~~ {.cpp}
6815 /// T.ReadFile("file1.dat","branch descriptor");
6816 /// T.ReadFile("file2.dat");
6817 /// ~~~
6818 
6819 Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
6821  std::ifstream in;
6822  in.open(filename);
6823  if (!in.good()) {
6824  Error("ReadFile","Cannot open file: %s",filename);
6825  return 0;
6826  }
6827  const char* ext = strrchr(filename, '.');
6828  if(ext != NULL && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
6829  delimiter = ',';
6830  }
6831  return ReadStream(in, branchDescriptor, delimiter);
6832 }
6833 
6834 ////////////////////////////////////////////////////////////////////////////////
6835 /// Determine which newline this file is using.
6836 /// Return '\\r' for Windows '\\r\\n' as that already terminates.
6837 
6838 char TTree::GetNewlineValue(std::istream &inputStream)
6840  Long_t inPos = inputStream.tellg();
6841  char newline = '\n';
6842  while(1) {
6843  char c = 0;
6844  inputStream.get(c);
6845  if(!inputStream.good()) {
6846  Error("ReadStream","Error reading stream: no newline found.");
6847  return 0;
6848  }
6849  if(c == newline) break;
6850  if(c == '\r') {
6851  newline = '\r';
6852  break;
6853  }
6854  }
6855  inputStream.clear();
6856  inputStream.seekg(inPos);
6857  return newline;
6858 }
6859 
6860 ////////////////////////////////////////////////////////////////////////////////
6861 /// Create or simply read branches from an input stream.
6862 ///
6863 /// See reference information for TTree::ReadFile
6864 
6865 Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
6867  char newline = GetNewlineValue(inputStream);
6868  std::istream& in = inputStream;
6869  Long64_t nlines = 0;
6870 
6871  TBranch *branch = 0;
6872  Int_t nbranches = fBranches.GetEntries();
6873  if (nbranches == 0) {
6874  char *bdname = new char[4000];
6875  char *bd = new char[100000];
6876  Int_t nch = 0;
6877  if (branchDescriptor) nch = strlen(branchDescriptor);
6878  // branch Descriptor is null, read its definition from the first line in the file
6879  if (!nch) {
6880  do {
6881  in.getline(bd, 100000, newline);
6882  if (!in.good()) {
6883  delete [] bdname;
6884  delete [] bd;
6885  Error("ReadStream","Error reading stream");
6886  return 0;
6887  }
6888  char *cursor = bd;
6889  while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
6890  ++cursor;
6891  }
6892  if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
6893  break;
6894  }
6895  } while (true);
6896  ++nlines;
6897  nch = strlen(bd);
6898  } else {
6899  strlcpy(bd,branchDescriptor,100000);
6900  }
6901 
6902  //parse the branch descriptor and create a branch for each element
6903  //separated by ":"
6904  void *address = &bd[90000];
6905  char *bdcur = bd;
6906  TString desc="", olddesc="F";
6907  char bdelim = ':';
6908  if(delimiter != ' ') {
6909  bdelim = delimiter;
6910  if (strchr(bdcur,bdelim)==0 && strchr(bdcur,':') != 0) {
6911  // revert to the default
6912  bdelim = ':';
6913  }
6914  }
6915  while (bdcur) {
6916  char *colon = strchr(bdcur,bdelim);
6917  if (colon) *colon = 0;
6918  strlcpy(bdname,bdcur,4000);
6919  char *slash = strchr(bdname,'/');
6920  if (slash) {
6921  *slash = 0;
6922  desc = bdcur;
6923  olddesc = slash+1;
6924  } else {
6925  desc.Form("%s/%s",bdname,olddesc.Data());
6926  }
6927  char *bracket = strchr(bdname,'[');
6928  if (bracket) {
6929  *bracket = 0;
6930  }
6931  branch = new TBranch(this,bdname,address,desc.Data(),32000);
6932  if (branch->IsZombie()) {
6933  delete branch;
6934  Warning("ReadStream","Illegal branch definition: %s",bdcur);
6935  } else {
6936  fBranches.Add(branch);
6937  branch->SetAddress(0);
6938  }
6939  if (!colon)break;
6940  bdcur = colon+1;
6941  }
6942  delete [] bdname;
6943  delete [] bd;
6944  }
6945 
6946  nbranches = fBranches.GetEntries();
6947 
6948  if (gDebug > 1) {
6949  Info("ReadStream", "Will use branches:");
6950  for (int i = 0 ; i < nbranches; ++i) {
6951  TBranch* br = (TBranch*) fBranches.At(i);
6952  Info("ReadStream", " %s: %s [%s]", br->GetName(),
6953  br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
6954  }
6955  if (gDebug > 3) {
6956  Info("ReadStream", "Dumping read tokens, format:");
6957  Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
6958  Info("ReadStream", " L: line number");
6959  Info("ReadStream", " B: branch number");
6960  Info("ReadStream", " gfbe: good / fail / bad / eof of token");
6961  Info("ReadStream", " GFBE: good / fail / bad / eof of file");
6962  Info("ReadStream", " T: Token being read");
6963  }
6964  }
6965 
6966  //loop on all lines in the file
6967  Long64_t nGoodLines = 0;
6968  std::string line;
6969  const char sDelimBuf[2] = { delimiter, 0 };
6970  const char* sDelim = sDelimBuf;
6971  if (delimiter == ' ') {
6972  // ' ' really means whitespace
6973  sDelim = "[ \t]";
6974  }
6975  while(in.good()) {
6976  if (newline == '\r' && in.peek() == '\n') {
6977  // Windows, skip '\n':
6978  in.get();
6979  }
6980  std::getline(in, line, newline);
6981  ++nlines;
6982 
6983  TString sLine(line);
6984  sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
6985  if (sLine.IsNull()) {
6986  if (gDebug > 2) {
6987  Info("ReadStream", "Skipping empty line number %lld", nlines);
6988  }
6989  continue; // silently skip empty lines
6990  }
6991  if (sLine[0] == '#') {
6992  if (gDebug > 2) {
6993  Info("ReadStream", "Skipping comment line number %lld: '%s'",
6994  nlines, line.c_str());
6995  }
6996  continue;
6997  }
6998  if (gDebug > 2) {
6999  Info("ReadStream", "Parsing line number %lld: '%s'",
7000  nlines, line.c_str());
7001  }
7002 
7003  // Loop on branches and read the branch values into their buffer
7004  branch = 0;
7005  TString tok; // one column's data
7006  TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7007  std::stringstream sToken; // string stream feeding leafData into leaves
7008  Ssiz_t pos = 0;
7009  Int_t iBranch = 0;
7010  Bool_t goodLine = kTRUE; // whether the row can be filled into the tree
7011  Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7012  while (goodLine && iBranch < nbranches
7013  && sLine.Tokenize(tok, pos, sDelim)) {
7014  tok = tok.Strip(TString::kLeading); // skip leading whitespace
7015  if (tok.IsNull() && delimiter == ' ') {
7016  // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7017  // Thus continue until we have a non-empty token.
7018  continue;
7019  }
7020 
7021  if (!remainingLeafLen) {
7022  // next branch!
7023  branch = (TBranch*)fBranches.At(iBranch);
7024  }
7025  TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7026  if (!remainingLeafLen) {
7027  remainingLeafLen = leaf->GetLen();
7028  if (leaf->GetMaximum() > 0) {
7029  // This is a dynamic leaf length, i.e. most likely a TLeafC's
7030  // string size. This still translates into one token:
7031  remainingLeafLen = 1;
7032  }
7033 
7034  leafData = tok;
7035  } else {
7036  // append token to laf data:
7037  leafData += " ";
7038  leafData += tok;
7039  }
7040  --remainingLeafLen;
7041  if (remainingLeafLen) {
7042  // need more columns for this branch:
7043  continue;
7044  }
7045  ++iBranch;
7046 
7047  // initialize stringstream with token
7048  sToken.clear();
7049  sToken.seekp(0, std::ios_base::beg);
7050  sToken.str(leafData.Data());
7051  sToken.seekg(0, std::ios_base::beg);
7052  leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7053  if (gDebug > 3) {
7054  Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7055  nlines, iBranch,
7056  (int)sToken.good(), (int)sToken.fail(),
7057  (int)sToken.bad(), (int)sToken.eof(),
7058  (int)in.good(), (int)in.fail(),
7059  (int)in.bad(), (int)in.eof(),
7060  sToken.str().c_str());
7061  }
7062 
7063  // Error handling
7064  if (sToken.bad()) {
7065  // How could that happen for a stringstream?
7066  Warning("ReadStream",
7067  "Buffer error while reading data for branch %s on line %lld",
7068  branch->GetName(), nlines);
7069  } else if (!sToken.eof()) {
7070  if (sToken.fail()) {
7071  Warning("ReadStream",
7072  "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7073  tok.Data(), branch->GetName(), nlines);
7074  goodLine = kFALSE;
7075  } else {
7076  std::string remainder;
7077  std::getline(sToken, remainder, newline);
7078  if (!remainder.empty()) {
7079  Warning("ReadStream",
7080  "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7081  remainder.c_str(), branch->GetName(), nlines);
7082  }
7083  }
7084  }
7085  } // tokenizer loop
7086 
7087  if (iBranch < nbranches) {
7088  Warning("ReadStream",
7089  "Read too few columns (%d < %d) in line %lld; ignoring line",
7090  iBranch, nbranches, nlines);
7091  goodLine = kFALSE;
7092  } else if (pos != kNPOS) {
7093  sLine = sLine.Strip(TString::kTrailing);
7094  if (pos < sLine.Length()) {
7095  Warning("ReadStream",
7096  "Ignoring trailing \"%s\" while reading line %lld",
7097  sLine.Data() + pos - 1 /* also print delimiter */,
7098  nlines);
7099  }
7100  }
7101 
7102  //we are now ready to fill the tree
7103  if (goodLine) {
7104  Fill();
7105  ++nGoodLines;
7106  }
7107  }
7108 
7109  return nGoodLines;
7110 }
7111 
7112 ////////////////////////////////////////////////////////////////////////////////
7113 /// Make sure that obj (which is being deleted or will soon be) is no
7114 /// longer referenced by this TTree.
7115 
7118  if (obj == fEventList) {
7119  fEventList = 0;
7120  }
7121  if (obj == fEntryList) {
7122  fEntryList = 0;
7123  }
7124  if (fUserInfo) {
7125  fUserInfo->RecursiveRemove(obj);
7126  }
7127  if (fPlayer == obj) {
7128  fPlayer = 0;
7129  }
7130  if (fTreeIndex == obj) {
7131  fTreeIndex = 0;
7132  }
7133  if (fAliases) {
7134  fAliases->RecursiveRemove(obj);
7135  }
7136  if (fFriends) {
7137  fFriends->RecursiveRemove(obj);
7138  }
7139 }
7140 
7141 ////////////////////////////////////////////////////////////////////////////////
7142 /// Refresh contents of this tree and its branches from the current status on disk.
7143 ///
7144 /// One can call this function in case the tree file is being
7145 /// updated by another process.
7146 
7147 void TTree::Refresh()
7149  if (!fDirectory->GetFile()) {
7150  return;
7151  }
7152  fDirectory->ReadKeys();
7153  fDirectory->Remove(this);
7154  TTree* tree; fDirectory->GetObject(GetName(),tree);
7155  if (!tree) {
7156  return;
7157  }
7158  //copy info from tree header into this Tree
7159  fEntries = 0;
7160  fNClusterRange = 0;
7161  ImportClusterRanges(tree);
7162 
7163  fAutoSave = tree->fAutoSave;
7164  fEntries = tree->fEntries;
7165  fTotBytes = tree->fTotBytes;
7166  fZipBytes = tree->fZipBytes;
7167  fSavedBytes = tree->fSavedBytes;
7168  fTotalBuffers = tree->fTotalBuffers;
7169 
7170  //loop on all branches and update them
7171  Int_t nleaves = fLeaves.GetEntriesFast();
7172  for (Int_t i = 0; i < nleaves; i++) {
7173  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7174  TBranch* branch = (TBranch*) leaf->GetBranch();
7175  branch->Refresh(tree->GetBranch(branch->GetName()));
7176  }
7177  fDirectory->Remove(tree);
7178  fDirectory->Append(this);
7179  delete tree;
7180  tree = 0;
7181 }
7182 
7183 ////////////////////////////////////////////////////////////////////////////////
7184 /// Remove a friend from the list of friends.
7185 
7186 void TTree::RemoveFriend(TTree* oldFriend)
7188  // We already have been visited while recursively looking
7189  // through the friends tree, let return
7191  return;
7192  }
7193  if (!fFriends) {
7194  return;
7195  }
7196  TFriendLock lock(this, kRemoveFriend);
7197  TIter nextf(fFriends);
7198  TFriendElement* fe = 0;
7199  while ((fe = (TFriendElement*) nextf())) {
7200  TTree* friend_t = fe->GetTree();
7201  if (friend_t == oldFriend) {
7202  fFriends->Remove(fe);
7203  delete fe;
7204  fe = 0;
7205  }
7206  }
7207 }
7208 
7209 ////////////////////////////////////////////////////////////////////////////////
7210 /// Reset baskets, buffers and entries count in all branches and leaves.
7211 
7212 void TTree::Reset(Option_t* option)
7214  fNotify = 0;
7215  fEntries = 0;
7216  fNClusterRange = 0;
7217  fTotBytes = 0;
7218  fZipBytes = 0;
7219  fFlushedBytes = 0;
7220  fSavedBytes = 0;
7221  fTotalBuffers = 0;
7222  fChainOffset = 0;
7223  fReadEntry = -1;
7224 
7225  delete fTreeIndex;
7226  fTreeIndex = 0;
7227 
7229  for (Int_t i = 0; i < nb; ++i) {
7230  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7231  branch->Reset(option);
7232  }
7233 
7234  if (fBranchRef) {
7235  fBranchRef->Reset();
7236  }
7237 }
7238 
7239 ////////////////////////////////////////////////////////////////////////////////
7240 /// Resets the state of this TTree after a merge (keep the customization but
7241 /// forget the data).
7242 
7245  fEntries = 0;
7246  fNClusterRange = 0;
7247  fTotBytes = 0;
7248  fZipBytes = 0;
7249  fSavedBytes = 0;
7250  fFlushedBytes = 0;
7251  fTotalBuffers = 0;
7252  fChainOffset = 0;
7253  fReadEntry = -1;
7254 
7255  delete fTreeIndex;
7256  fTreeIndex = 0;
7257 
7259  for (Int_t i = 0; i < nb; ++i) {
7260  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7261  branch->ResetAfterMerge(info);
7262  }
7263 
7264  if (fBranchRef) {
7265  fBranchRef->ResetAfterMerge(info);
7266  }
7267 }
7268 
7269 ////////////////////////////////////////////////////////////////////////////////
7270 /// Tell all of our branches to set their addresses to zero.
7271 ///
7272 /// Note: If any of our branches own any objects, they are deleted.
7273 
7276  if (br && br->GetTree()) {
7277  br->ResetAddress();
7278  }
7279 }
7280 
7281 ////////////////////////////////////////////////////////////////////////////////
7282 /// Tell all of our branches to drop their current objects and allocate new ones.
7283 
7286  TObjArray* branches = GetListOfBranches();
7287  Int_t nbranches = branches->GetEntriesFast();
7288  for (Int_t i = 0; i < nbranches; ++i) {
7289  TBranch* branch = (TBranch*) branches->UncheckedAt(i);
7290  branch->ResetAddress();
7291  }
7292 }
7293 
7294 ////////////////////////////////////////////////////////////////////////////////
7295 /// Loop over tree entries and print entries passing selection.
7296 ///
7297 /// - If varexp is 0 (or "") then print only first 8 columns.
7298 /// - If varexp = "*" print all columns.
7299 ///
7300 /// Otherwise a columns selection can be made using "var1:var2:var3".
7301 /// See TTreePlayer::Scan for more information
7302 
7303 Long64_t TTree::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7305  GetPlayer();
7306  if (fPlayer) {
7307  return fPlayer->Scan(varexp, selection, option, nentries, firstentry);
7308  }
7309  return -1;
7310 }
7311 
7312 ////////////////////////////////////////////////////////////////////////////////
7313 /// Set a tree variable alias.
7314 ///
7315 /// Set an alias for an expression/formula based on the tree 'variables'.
7316 ///
7317 /// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
7318 /// TTree::Scan, TTreeViewer) and will be evaluated as the content of
7319 /// 'aliasFormula'.
7320 ///
7321 /// If the content of 'aliasFormula' only contains symbol names, periods and
7322 /// array index specification (for example event.fTracks[3]), then
7323 /// the content of 'aliasName' can be used as the start of symbol.
7324 ///
7325 /// If the alias 'aliasName' already existed, it is replaced by the new
7326 /// value.
7327 ///
7328 /// When being used, the alias can be preceded by an eventual 'Friend Alias'
7329 /// (see TTree::GetFriendAlias)
7330 ///
7331 /// Return true if it was added properly.
7332 ///
7333 /// For example:
7334 /// ~~~ {.cpp}
7335 /// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
7336 /// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
7337 /// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
7338 /// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
7339 /// tree->Draw("y2-y1:x2-x1");
7340 ///
7341 /// tree->SetAlias("theGoodTrack","event.fTracks[3]");
7342 /// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
7343 /// ~~~
7344 
7345 Bool_t TTree::SetAlias(const char* aliasName, const char* aliasFormula)
7347  if (!aliasName || !aliasFormula) {
7348  return kFALSE;
7349  }
7350  if (!aliasName[0] || !aliasFormula[0]) {
7351  return kFALSE;
7352  }
7353  if (!fAliases) {
7354  fAliases = new TList;
7355  } else {
7356  TNamed* oldHolder = (TNamed*) fAliases->FindObject(aliasName);
7357  if (oldHolder) {
7358  oldHolder->SetTitle(aliasFormula);
7359  return kTRUE;
7360  }
7361  }
7362  TNamed* holder = new TNamed(aliasName, aliasFormula);
7363  fAliases->Add(holder);
7364  return kTRUE;
7365 }
7366 
7367 ////////////////////////////////////////////////////////////////////////////////
7368 /// This function may be called at the start of a program to change
7369 /// the default value for fAutoFlush.
7370 ///
7371 /// ### CASE 1 : autof > 0
7372 ///
7373 /// autof is the number of consecutive entries after which TTree::Fill will
7374 /// flush all branch buffers to disk.
7375 ///
7376 /// ### CASE 2 : autof < 0
7377 ///
7378 /// When filling the Tree the branch buffers will be flushed to disk when
7379 /// more than autof bytes have been written to the file. At the first FlushBaskets
7380 /// TTree::Fill will replace fAutoFlush by the current value of fEntries.
7381 ///
7382 /// Calling this function with autof<0 is interesting when it is hard to estimate
7383 /// the size of one entry. This value is also independent of the Tree.
7384 ///
7385 /// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
7386 /// the first AutoFlush will be done when 30 MBytes of data are written to the file.
7387 ///
7388 /// ### CASE 3 : autof = 0
7389 ///
7390 /// The AutoFlush mechanism is disabled.
7391 ///
7392 /// Flushing the buffers at regular intervals optimize the location of
7393 /// consecutive entries on the disk by creating clusters of baskets.
7394 ///
7395 /// A cluster of baskets is a set of baskets that contains all
7396 /// the data for a (consecutive) set of entries and that is stored
7397 /// consecutively on the disk. When reading all the branches, this
7398 /// is the minimum set of baskets that the TTreeCache will read.
7399 
7400 void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
7402  // Implementation note:
7403  //
7404  // A positive value of autoflush determines the size (in number of entries) of
7405  // a cluster of baskets.
7406  //
7407  // If the value of autoflush is changed over time (this happens in
7408  // particular when the TTree results from fast merging many trees),
7409  // we record the values of fAutoFlush in the data members:
7410  // fClusterRangeEnd and fClusterSize.
7411  // In the code we refer to a range of entries where the size of the
7412  // cluster of baskets is the same (i.e the value of AutoFlush was
7413  // constant) is called a ClusterRange.
7414  //
7415  // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
7416  // active (used) values and have fMaxClusterRange allocated entries.
7417  //
7418  // fClusterRangeEnd contains the last entries number of a cluster range.
7419  // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
7420  // fClusterSize contains the size in number of entries of all the cluster
7421  // within the given range.
7422  // The last range (and the only one if fNClusterRange is zero) start at
7423  // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
7424  // size of the cluster in this range is given by the value of fAutoFlush.
7425  //
7426  // For example printing the beginning and end of each the ranges can be done by:
7427  //
7428  // Printf("%-16s %-16s %-16s %5s",
7429  // "Cluster Range #", "Entry Start", "Last Entry", "Size");
7430  // Int_t index= 0;
7431  // Long64_t clusterRangeStart = 0;
7432  // if (fNClusterRange) {
7433  // for( ; index < fNClusterRange; ++index) {
7434  // Printf("%-16d %-16lld %-16lld %5lld",
7435  // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7436  // clusterRangeStart = fClusterRangeEnd[index] + 1;
7437  // }
7438  // }
7439  // Printf("%-16d %-16lld %-16lld %5lld",
7440  // index, prevEntry, fEntries - 1, fAutoFlush);
7441  //
7442 
7443  // Note: We store the entry number corresponding to the end of the cluster
7444  // rather than its start in order to avoid using the array if the cluster
7445  // size never varies (If there is only one value of AutoFlush for the whole TTree).
7446 
7447  if (fAutoFlush > 0 || autof > 0) {
7448  // The mechanism was already enabled, let's record the previous
7449  // cluster if needed.
7450  if (fFlushedBytes) {
7451  if ( (fNClusterRange+1) > fMaxClusterRange ) {
7452  if (fMaxClusterRange) {
7453  Int_t newsize = TMath::Max(10,Int_t(2*fMaxClusterRange));
7455  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7457  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7458  fMaxClusterRange = newsize;
7459  } else {
7460  fMaxClusterRange = 2;
7463  }
7464  }
7467  ++fNClusterRange;
7468  }
7469  }
7470  fAutoFlush = autof;
7471 }
7472 
7473 ////////////////////////////////////////////////////////////////////////////////
7474 /// This function may be called at the start of a program to change
7475 /// the default value for fAutoSave (and for SetAutoSave) is -300000000, ie 300 MBytes
7476 /// When filling the Tree the branch buffers as well as the Tree header
7477 /// will be flushed to disk when the watermark is reached.
7478 /// If fAutoSave is positive the watermark is reached when a multiple of fAutoSave
7479 /// entries have been written.
7480 /// If fAutoSave is negative the watermark is reached when -fAutoSave bytes
7481 /// have been written to the file.
7482 /// In case of a program crash, it will be possible to recover the data in the Tree
7483 /// up to the last AutoSave point.
7484 
7485 void TTree::SetAutoSave(Long64_t autos)
7487  fAutoSave = autos;
7488 }
7489 
7490 ////////////////////////////////////////////////////////////////////////////////
7491 /// Set a branch's basket size.
7492 ///
7493 /// bname is the name of a branch.
7494 ///
7495 /// - if bname="*", apply to all branches.
7496 /// - if bname="xxx*", apply to all branches with name starting with xxx
7497 ///
7498 /// see TRegexp for wildcarding options
7499 /// buffsize = branc basket size
7500 
7501 void TTree::SetBasketSize(const char* bname, Int_t buffsize)
7503  Int_t nleaves = fLeaves.GetEntriesFast();
7504  TRegexp re(bname, kTRUE);
7505  Int_t nb = 0;
7506  for (Int_t i = 0; i < nleaves; i++) {
7507  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7508  TBranch* branch = (TBranch*) leaf->GetBranch();
7509  TString s = branch->GetName();
7510  if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
7511  continue;
7512  }
7513  nb++;
7514  branch->SetBasketSize(buffsize);
7515  }
7516  if (!nb) {
7517  Error("SetBasketSize", "unknown branch -> '%s'", bname);
7518  }
7519 }
7520 
7521 ////////////////////////////////////////////////////////////////////////////////
7522 /// Change branch address, dealing with clone trees properly.
7523 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7524 ///
7525 /// Note: See the comments in TBranchElement::SetAddress() for the
7526 /// meaning of the addr parameter and the object ownership policy.
7527 
7528 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
7530  TBranch* branch = GetBranch(bname);
7531  if (!branch) {
7532  if (ptr) *ptr = 0;
7533  Error("SetBranchAddress", "unknown branch -> %s", bname);
7534  return kMissingBranch;
7535  }
7536  return SetBranchAddressImp(branch,addr,ptr);
7537 }
7538 
7539 ////////////////////////////////////////////////////////////////////////////////
7540 /// Verify the validity of the type of addr before calling SetBranchAddress.
7541 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7542 ///
7543 /// Note: See the comments in TBranchElement::SetAddress() for the
7544 /// meaning of the addr parameter and the object ownership policy.
7545 
7546 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
7548  return SetBranchAddress(bname, addr, 0, ptrClass, datatype, isptr);
7549 }
7550 
7551 ////////////////////////////////////////////////////////////////////////////////
7552 /// Verify the validity of the type of addr before calling SetBranchAddress.
7553 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7554 ///
7555 /// Note: See the comments in TBranchElement::SetAddress() for the
7556 /// meaning of the addr parameter and the object ownership policy.
7557 
7558 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
7560  TBranch* branch = GetBranch(bname);
7561  if (!branch) {
7562  if (ptr) *ptr = 0;
7563  Error("SetBranchAddress", "unknown branch -> %s", bname);
7564  return kMissingBranch;
7565  }
7566 
7567  Int_t res = CheckBranchAddressType(branch, ptrClass, datatype, isptr);
7568  // This will set the value of *ptr to branch.
7569  if (res >= 0) {
7570  // The check succeeded.
7571  SetBranchAddressImp(branch,addr,ptr);
7572  } else {
7573  if (ptr) *ptr = 0;
7574  }
7575  return res;
7576 }
7577 
7578 ////////////////////////////////////////////////////////////////////////////////
7579 /// Change branch address, dealing with clone trees properly.
7580 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7581 ///
7582 /// Note: See the comments in TBranchElement::SetAddress() for the
7583 /// meaning of the addr parameter and the object ownership policy.
7584 
7585 Int_t TTree::SetBranchAddressImp(TBranch *branch, void* addr, TBranch** ptr)
7587  if (ptr) {
7588  *ptr = branch;
7589  }
7590  if (fClones) {
7591  void* oldAddr = branch->GetAddress();
7592  TIter next(fClones);
7593  TTree* clone = 0;
7594  const char *bname = branch->GetName();
7595  while ((clone = (TTree*) next())) {
7596  TBranch* cloneBr = clone->GetBranch(bname);
7597  if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
7598  cloneBr->SetAddress(addr);
7599  }
7600  }
7601  }
7602  branch->SetAddress(addr);
7603  return kVoidPtr;
7604 }
7605 
7606 ////////////////////////////////////////////////////////////////////////////////
7607 /// Set branch status to Process or DoNotProcess.
7608 ///
7609 /// When reading a Tree, by default, all branches are read.
7610 /// One can speed up considerably the analysis phase by activating
7611 /// only the branches that hold variables involved in a query.
7612 ///
7613 /// bname is the name of a branch.
7614 ///
7615 /// - if bname="*", apply to all branches.
7616 /// - if bname="xxx*", apply to all branches with name starting with xxx
7617 ///
7618 /// see TRegexp for wildcarding options
7619 ///
7620 /// - status = 1 branch will be processed
7621 /// - = 0 branch will not be processed
7622 ///
7623 /// Example:
7624 ///
7625 /// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
7626 /// when doing T.GetEntry(i) all branches are read for entry i.
7627 /// to read only the branches c and e, one can do
7628 /// ~~~ {.cpp}
7629 /// T.SetBranchStatus("*",0); //disable all branches
7630 /// T.SetBranchStatus("c",1);
7631 /// T.setBranchStatus("e",1);
7632 /// T.GetEntry(i);
7633 /// ~~~
7634 /// bname is interpreted as a wildcarded TRegexp (see TRegexp::MakeWildcard).
7635 /// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
7636 /// "b", but not any other branch with an "a" followed at some point by a
7637 /// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
7638 /// support '|', and so you cannot select, e.g. track and shower branches
7639 /// with "track|shower".
7640 ///
7641 /// __WARNING! WARNING! WARNING!__
7642 ///
7643 /// SetBranchStatus is matching the branch based on match of the branch
7644 /// 'name' and not on the branch hierarchy! In order to be able to
7645 /// selectively enable a top level object that is 'split' you need to make
7646 /// sure the name of the top level branch is prefixed to the sub-branches'
7647 /// name (by adding a dot ('.') at the end of the Branch creation and use the
7648 /// corresponding bname.
7649 ///
7650 /// I.e If your Tree has been created in split mode with a parent branch "parent."
7651 /// (note the trailing dot).
7652 /// ~~~ {.cpp}
7653 /// T.SetBranchStatus("parent",1);
7654 /// ~~~
7655 /// will not activate the sub-branches of "parent". You should do:
7656 /// ~~~ {.cpp}
7657 /// T.SetBranchStatus("parent*",1);
7658 /// ~~~
7659 /// Without the trailing dot in the branch creation you have no choice but to
7660 /// call SetBranchStatus explicitly for each of the sub branches.
7661 ///
7662 /// An alternative to this function is to read directly and only
7663 /// the interesting branches. Example:
7664 /// ~~~ {.cpp}
7665 /// TBranch *brc = T.GetBranch("c");
7666 /// TBranch *bre = T.GetBranch("e");
7667 /// brc->GetEntry(i);
7668 /// bre->GetEntry(i);
7669 /// ~~~
7670 /// If found is not 0, the number of branch(es) found matching the regular
7671 /// expression is returned in *found AND the error message 'unknown branch'
7672 /// is suppressed.
7673 
7674 void TTree::SetBranchStatus(const char* bname, Bool_t status, UInt_t* found)
7676  // We already have been visited while recursively looking
7677  // through the friends tree, let return
7679  return;
7680  }
7681 
7682  TBranch *branch, *bcount, *bson;
7683  TLeaf *leaf, *leafcount;
7684 
7685  Int_t i,j;
7686  Int_t nleaves = fLeaves.GetEntriesFast();
7687  TRegexp re(bname,kTRUE);
7688  Int_t nb = 0;
7689 
7690  // first pass, loop on all branches
7691  // for leafcount branches activate/deactivate in function of status
7692  for (i=0;i<nleaves;i++) {
7693  leaf = (TLeaf*)fLeaves.UncheckedAt(i);
7694  branch = (TBranch*)leaf->GetBranch();
7695  TString s = branch->GetName();
7696  if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
7697  TString longname;
7698  longname.Form("%s.%s",GetName(),branch->GetName());
7699  if (strcmp(bname,branch->GetName())
7700  && longname != bname
7701  && s.Index(re) == kNPOS) continue;
7702  }
7703  nb++;
7704  if (status) branch->ResetBit(kDoNotProcess);
7705  else branch->SetBit(kDoNotProcess);
7706  leafcount = leaf->GetLeafCount();
7707  if (leafcount) {
7708  bcount = leafcount->GetBranch();
7709  if (status) bcount->ResetBit(kDoNotProcess);
7710  else bcount->SetBit(kDoNotProcess);
7711  }
7712  }
7713  if (nb==0 && strchr(bname,'*')==0) {
7714  branch = GetBranch(bname);
7715  if (branch) {
7716  if (status) branch->ResetBit(kDoNotProcess);
7717  else branch->SetBit(kDoNotProcess);
7718  ++nb;
7719  }
7720  }
7721 
7722  //search in list of friends
7723  UInt_t foundInFriend = 0;
7724  if (fFriends) {
7725  TFriendLock lock(this,kSetBranchStatus);
7726  TIter nextf(fFriends);
7727  TFriendElement *fe;
7728  TString name;
7729  while ((fe = (TFriendElement*)nextf())) {
7730  TTree *t = fe->GetTree();
7731  if (t==0) continue;
7732 
7733  // If the alias is present replace it with the real name.
7734  char *subbranch = (char*)strstr(bname,fe->GetName());
7735  if (subbranch!=bname) subbranch = 0;
7736  if (subbranch) {
7737  subbranch += strlen(fe->GetName());
7738  if ( *subbranch != '.' ) subbranch = 0;
7739  else subbranch ++;
7740  }
7741  if (subbranch) {
7742  name.Form("%s.%s",t->GetName(),subbranch);
7743  } else {
7744  name = bname;
7745  }
7746  t->SetBranchStatus(name,status, &foundInFriend);
7747  }
7748  }
7749  if (!nb && !foundInFriend) {
7750  if (found==0) {
7751  if (status) {
7752  if (strchr(bname,'*') != 0)
7753  Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
7754  else
7755  Error("SetBranchStatus", "unknown branch -> %s", bname);
7756  } else {
7757  if (strchr(bname,'*') != 0)
7758  Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
7759  else
7760  Warning("SetBranchStatus", "unknown branch -> %s", bname);
7761  }
7762  }
7763  return;
7764  }
7765  if (found) *found = nb + foundInFriend;
7766 
7767  // second pass, loop again on all branches
7768  // activate leafcount branches for active branches only
7769  for (i = 0; i < nleaves; i++) {
7770  leaf = (TLeaf*)fLeaves.UncheckedAt(i);
7771  branch = (TBranch*)leaf->GetBranch();
7772  if (!branch->TestBit(kDoNotProcess)) {
7773  leafcount = leaf->GetLeafCount();
7774  if (leafcount) {
7775  bcount = leafcount->GetBranch();
7776  bcount->ResetBit(kDoNotProcess);
7777  }
7778  } else {
7779  //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
7780  Int_t nbranches = branch->GetListOfBranches()->GetEntries();
7781  for (j=0;j<nbranches;j++) {
7782  bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
7783  if (!bson) continue;
7784  if (!bson->TestBit(kDoNotProcess)) {
7785  if (bson->GetNleaves() <= 0) continue;
7786  branch->ResetBit(kDoNotProcess);
7787  break;
7788  }
7789  }
7790  }
7791  }
7792 }
7793 
7794 ////////////////////////////////////////////////////////////////////////////////
7795 /// Set the current branch style. (static function)
7796 ///
7797 /// - style = 0 old Branch
7798 /// - style = 1 new Bronch
7799 
7802  fgBranchStyle = style;
7803 }
7804 
7805 ////////////////////////////////////////////////////////////////////////////////
7806 /// Set maximum size of the file cache .
7807 //
7808 /// - if cachesize = 0 the existing cache (if any) is deleted.
7809 /// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
7810 /// the Tree (default is 30 MBytes).
7811 ///
7812 /// Returns:
7813 /// - 0 size set, cache was created if possible
7814 /// - -1 on error
7815 
7818  // remember that the user has requested an explicit cache setup
7819  fCacheUserSet = kTRUE;
7820 
7821  return SetCacheSizeAux(kFALSE, cacheSize);
7822 }
7823 
7824 ////////////////////////////////////////////////////////////////////////////////
7825 /// Set the size of the file cache and create it if possible.
7826 ///
7827 /// If autocache is true:
7828 /// this may be an autocreated cache, possibly enlarging an existing
7829 /// autocreated cache. The size is calculated. The value passed in cacheSize:
7830 /// - cacheSize = 0 make cache if default cache creation is enabled
7831 /// - cacheSize = -1 make a default sized cache in any case
7832 ///
7833 /// If autocache is false:
7834 /// this is a user requested cache. cacheSize is used to size the cache.
7835 /// This cache should never be automatically adjusted.
7836 ///
7837 /// Returns:
7838 /// - 0 size set, or existing autosized cache almost large enough.
7839 /// (cache was created if possible)
7840 /// - -1 on error
7841 
7842 Int_t TTree::SetCacheSizeAux(Bool_t autocache /* = kTRUE */, Long64_t cacheSize /* = 0 */ )
7844  if (autocache) {
7845  // used as a once only control for automatic cache setup
7847  }
7848 
7849  if (!autocache) {
7850  // negative size means the user requests the default
7851  if (cacheSize < 0) {
7852  cacheSize = GetCacheAutoSize(kTRUE);
7853  }
7854  } else {
7855  if (cacheSize == 0) {
7856  cacheSize = GetCacheAutoSize();
7857  } else if (cacheSize < 0) {
7858  cacheSize = GetCacheAutoSize(kTRUE);
7859  }
7860  }
7861 
7862  TFile* file = GetCurrentFile();
7863  if (!file || GetTree() != this) {
7864  // if there's no file or we are not a plain tree (e.g. if we're a TChain)
7865  // do not create a cache, only record the size if one was given
7866  if (!autocache) {
7867  fCacheSize = cacheSize;
7868  }
7869  if (GetTree() != this) {
7870  return 0;
7871  }
7872  if (!autocache && cacheSize>0) {
7873  Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
7874  }
7875  return 0;
7876  }
7877 
7878  // Check for an existing cache
7879  TTreeCache* pf = GetReadCache(file);
7880  if (pf) {
7881  if (autocache) {
7882  // reset our cache status tracking in case existing cache was added
7883  // by the user without using one of the TTree methods
7884  fCacheSize = pf->GetBufferSize();
7885  fCacheUserSet = !pf->IsAutoCreated();
7886 
7887  if (fCacheUserSet) {
7888  // existing cache was created by the user, don't change it
7889  return 0;
7890  }
7891  } else {
7892  // update the cache to ensure it records the user has explicitly
7893  // requested it
7894  pf->SetAutoCreated(kFALSE);
7895  }
7896 
7897  // if we're using an automatically calculated size and the existing
7898  // cache is already almost large enough don't resize
7899  if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
7900  // already large enough
7901  return 0;
7902  }
7903 
7904  if (cacheSize == fCacheSize) {
7905  return 0;
7906  }
7907 
7908  if (cacheSize == 0) {
7909  // delete existing cache
7910  pf->WaitFinishPrefetch();
7911  file->SetCacheRead(0,this);
7912  delete pf;
7913  pf = 0;
7914  } else {
7915  // resize
7916  Int_t res = pf->SetBufferSize(cacheSize);
7917  if (res < 0) {
7918  return -1;
7919  }
7920  }
7921  } else {
7922  // no existing cache
7923  if (autocache) {
7924  if (fCacheUserSet) {
7925  // value was already set manually.
7926  if (fCacheSize == 0) return 0;
7927  // Expected a cache should exist; perhaps the user moved it
7928  // Do nothing more here.
7929  if (cacheSize) {
7930  Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
7931  }
7932  return -1;
7933  }
7934  }
7935  }
7936 
7937  fCacheSize = cacheSize;
7938  if (cacheSize == 0 || pf) {
7939  return 0;
7940  }
7941 
7943  pf = new TTreeCacheUnzip(this, cacheSize);
7944  else
7945  pf = new TTreeCache(this, cacheSize);
7946 
7947  pf->SetAutoCreated(autocache);
7948 
7949  return 0;
7950 }
7951 
7952 ////////////////////////////////////////////////////////////////////////////////
7953 ///interface to TTreeCache to set the cache entry range
7954 ///
7955 /// Returns:
7956 /// - 0 entry range set
7957 /// - -1 on error
7958 
7961  if (!GetTree()) {
7962  if (LoadTree(0)<0) {
7963  Error("SetCacheEntryRange","Could not load a tree");
7964  return -1;
7965  }
7966  }
7967  if (GetTree()) {
7968  if (GetTree() != this) {
7969  return GetTree()->SetCacheEntryRange(first, last);
7970  }
7971  } else {
7972  Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
7973  return -1;
7974  }
7975 
7976  TFile *f = GetCurrentFile();
7977  if (!f) {
7978  Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
7979  return -1;
7980  }
7981  TTreeCache *tc = GetReadCache(f,kTRUE);
7982  if (!tc) {
7983  Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
7984  return -1;
7985  }
7986  tc->SetEntryRange(first,last);
7987  return 0;
7988 }
7989 
7990 ////////////////////////////////////////////////////////////////////////////////
7991 /// Interface to TTreeCache to set the number of entries for the learning phase
7992 
7996 }
7997 
7998 ////////////////////////////////////////////////////////////////////////////////
7999 /// Enable/Disable circularity for this tree.
8000 ///
8001 /// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8002 /// per branch in memory.
8003 /// Note that when this function is called (maxEntries>0) the Tree
8004 /// must be empty or having only one basket per branch.
8005 /// if maxEntries <= 0 the tree circularity is disabled.
8006 ///
8007 /// #### NOTE 1:
8008 /// Circular Trees are interesting in online real time environments
8009 /// to store the results of the last maxEntries events.
8010 /// #### NOTE 2:
8011 /// Calling SetCircular with maxEntries <= 0 is necessary before
8012 /// merging circular Trees that have been saved on files.
8013 /// #### NOTE 3:
8014 /// SetCircular with maxEntries <= 0 is automatically called
8015 /// by TChain::Merge
8016 /// #### NOTE 4:
8017 /// A circular Tree can still be saved in a file. When read back,
8018 /// it is still a circular Tree and can be filled again.
8019 
8020 void TTree::SetCircular(Long64_t maxEntries)
8022  if (maxEntries <= 0) {
8023  // Disable circularity.
8024  fMaxEntries = 1000000000;
8025  fMaxEntries *= 1000;
8027  //in case the Tree was originally created in gROOT, the branch
8028  //compression level was set to -1. If the Tree is now associated to
8029  //a file, reset the compression level to the file compression level
8030  if (fDirectory) {
8031  TFile* bfile = fDirectory->GetFile();
8032  Int_t compress = 1;
8033  if (bfile) {
8034  compress = bfile->GetCompressionSettings();
8035  }
8037  for (Int_t i = 0; i < nb; i++) {
8038  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8039  branch->SetCompressionSettings(compress);
8040  }
8041  }
8042  } else {
8043  // Enable circularity.
8044  fMaxEntries = maxEntries;
8045  SetBit(kCircular);
8046  }
8047 }
8048 
8049 ////////////////////////////////////////////////////////////////////////////////
8050 /// Set the debug level and the debug range.
8051 ///
8052 /// For entries in the debug range, the functions TBranchElement::Fill
8053 /// and TBranchElement::GetEntry will print the number of bytes filled
8054 /// or read for each branch.
8055 
8058  fDebug = level;
8059  fDebugMin = min;
8060  fDebugMax = max;
8061 }
8062 
8063 ////////////////////////////////////////////////////////////////////////////////
8064 /// Update the default value for the branch's fEntryOffsetLen.
8065 /// If updateExisting is true, also update all the existing branches.
8066 /// If newdefault is less than 10, the new default value will be 10.
8067 
8068 void TTree::SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
8070  if (newdefault < 10) {
8071  newdefault = 10;
8072  }
8073  fDefaultEntryOffsetLen = newdefault;
8074  if (updateExisting) {
8076  TBranch *b;
8077  while ( ( b = (TBranch*)next() ) ) {
8078  b->SetEntryOffsetLen( newdefault, kTRUE );
8079  }
8080  if (fBranchRef) {
8081  fBranchRef->SetEntryOffsetLen( newdefault, kTRUE );
8082  }
8083  }
8084 }
8085 
8086 ////////////////////////////////////////////////////////////////////////////////
8087 /// Change the tree's directory.
8088 ///
8089 /// Remove reference to this tree from current directory and
8090 /// add reference to new directory dir. The dir parameter can
8091 /// be 0 in which case the tree does not belong to any directory.
8092 ///
8093 
8096  if (fDirectory == dir) {
8097  return;
8098  }
8099  if (fDirectory) {
8100  fDirectory->Remove(this);
8101 
8102  // Delete or move the file cache if it points to this Tree
8103  TFile *file = fDirectory->GetFile();
8104  MoveReadCache(file,dir);
8105  }
8106  fDirectory = dir;
8107  if (fDirectory) {
8108  fDirectory->Append(this);
8109  }
8110  TFile* file = 0;
8111  if (fDirectory) {
8112  file = fDirectory->GetFile();
8113  }
8114  if (fBranchRef) {
8115  fBranchRef->SetFile(file);
8116  }
8117  TBranch* b = 0;
8119  while((b = (TBranch*) next())) {
8120  b->SetFile(file);
8121  }
8122 }
8123 
8124 ////////////////////////////////////////////////////////////////////////////////
8125 /// Change number of entries in the tree.
8126 ///
8127 /// If n >= 0, set number of entries in the tree = n.
8128 ///
8129 /// If n < 0, set number of entries in the tree to match the
8130 /// number of entries in each branch. (default for n is -1)
8131 ///
8132 /// This function should be called only when one fills each branch
8133 /// independently via TBranch::Fill without calling TTree::Fill.
8134 /// Calling TTree::SetEntries() make sense only if the number of entries
8135 /// in each branch is identical, a warning is issued otherwise.
8136 /// The function returns the number of entries.
8137 ///
8138 
8141  // case 1 : force number of entries to n
8142  if (n >= 0) {
8143  fEntries = n;
8144  return n;
8145  }
8146 
8147  // case 2; compute the number of entries from the number of entries in the branches
8148  TBranch* b = 0;
8149  Long64_t nMin = 99999999;
8150  Long64_t nMax = 0;
8152  while((b = (TBranch*) next())){
8153  Long64_t n2 = b->GetEntries();
8154  if (n2 < nMin) {
8155  nMin = n2;
8156  }
8157  if (n2 > nMax) {
8158  nMax = n2;
8159  }
8160  }
8161  if (nMin != nMax) {
8162  Warning("SetEntries", "Tree branches have different numbers of entries, with %lld maximum.", nMax);
8163  }
8164  fEntries = nMax;
8165  return fEntries;
8166 }
8167 
8168 ////////////////////////////////////////////////////////////////////////////////
8169 /// Set an EntryList
8170 
8171 void TTree::SetEntryList(TEntryList *enlist, Option_t * /*opt*/)
8173  if (fEntryList) {
8174  //check if the previous entry list is owned by the tree
8175  if (fEntryList->TestBit(kCanDelete)){
8176  delete fEntryList;
8177  }
8178  }
8179  fEventList = 0;
8180  if (!enlist) {
8181  fEntryList = 0;
8182  return;
8183  }
8184  fEntryList = enlist;
8185  fEntryList->SetTree(this);
8186 
8187 }
8188 
8189 ////////////////////////////////////////////////////////////////////////////////
8190 /// This function transfroms the given TEventList into a TEntryList
8191 /// The new TEntryList is owned by the TTree and gets deleted when the tree
8192 /// is deleted. This TEntryList can be returned by GetEntryList() function.
8193 
8194 void TTree::SetEventList(TEventList *evlist)
8196  fEventList = evlist;
8197  if (fEntryList){
8198  if (fEntryList->TestBit(kCanDelete)) {
8199  TEntryList *tmp = fEntryList;
8200  fEntryList = 0; // Avoid problem with RecursiveRemove.
8201  delete tmp;
8202  } else {
8203  fEntryList = 0;
8204  }
8205  }
8206 
8207  if (!evlist) {
8208  fEntryList = 0;
8209  fEventList = 0;
8210  return;
8211  }
8212 
8213  fEventList = evlist;
8214  char enlistname[100];
8215  snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
8216  fEntryList = new TEntryList(enlistname, evlist->GetTitle());
8217  fEntryList->SetDirectory(0); // We own this.
8218  Int_t nsel = evlist->GetN();
8219  fEntryList->SetTree(this);
8220  Long64_t entry;
8221  for (Int_t i=0; i<nsel; i++){
8222  entry = evlist->GetEntry(i);
8223  fEntryList->Enter(entry);
8224  }
8225  fEntryList->SetReapplyCut(evlist->GetReapplyCut());
8226  fEntryList->SetBit(kCanDelete, kTRUE);
8227 }
8228 
8229 ////////////////////////////////////////////////////////////////////////////////
8230 /// Set number of entries to estimate variable limits.
8231 /// If n is -1, the estimate is set to be the current maximum
8232 /// for the tree (i.e. GetEntries() + 1)
8233 /// If n is less than -1, the behavior is undefined.
8234 
8235 void TTree::SetEstimate(Long64_t n /* = 1000000 */)
8237  if (n == 0) {
8238  n = 10000;
8239  } else if (n < 0) {
8240  n = fEntries - n;
8241  }
8242  fEstimate = n;
8243  GetPlayer();
8244  if (fPlayer) {
8245  fPlayer->SetEstimate(n);
8246  }
8247 }
8248 
8249 ////////////////////////////////////////////////////////////////////////////////
8250 /// Set fFileNumber to number.
8251 /// fFileNumber is used by TTree::Fill to set the file name
8252 /// for a new file to be created when the current file exceeds fgTreeMaxSize.
8253 /// (see TTree::ChangeFile)
8254 /// if fFileNumber=10, the new file name will have a suffix "_11",
8255 /// ie, fFileNumber is incremented before setting the file name
8256 
8257 void TTree::SetFileNumber(Int_t number)
8259  if (fFileNumber < 0) {
8260  Warning("SetFileNumber", "file number must be positive. Set to 0");
8261  fFileNumber = 0;
8262  return;
8263  }
8264  fFileNumber = number;
8265 }
8266 
8267 ////////////////////////////////////////////////////////////////////////////////
8268 /// Set all the branches in this TTree to be in decomposed object mode
8269 /// (also known as MakeClass mode).
8270 
8273  fMakeClass = make;
8274 
8276  for (Int_t i = 0; i < nb; ++i) {
8277  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8278  branch->SetMakeClass(make);
8279  }
8280 }
8281 
8282 ////////////////////////////////////////////////////////////////////////////////
8283 /// Set the maximum size in bytes of a Tree file (static function).
8284 /// The default size is 100000000000LL, ie 100 Gigabytes.
8285 ///
8286 /// In TTree::Fill, when the file has a size > fgMaxTreeSize,
8287 /// the function closes the current file and starts writing into
8288 /// a new file with a name of the style "file_1.root" if the original
8289 /// requested file name was "file.root".
8290 
8294 }
8295 
8296 ////////////////////////////////////////////////////////////////////////////////
8297 /// Change the name of this tree.
8298 
8299 void TTree::SetName(const char* name)
8301  if (gPad) {
8302  gPad->Modified();
8303  }
8304  // Trees are named objects in a THashList.
8305  // We must update hashlists if we change the name.
8306  TFile *file = 0;
8307  TTreeCache *pf = 0;
8308  if (fDirectory) {
8309  fDirectory->Remove(this);
8310  if ((file = GetCurrentFile())) {
8311  pf = GetReadCache(file);
8312  file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8313  }
8314  }
8315  // This changes our hash value.
8316  fName = name;
8317  if (fDirectory) {
8318  fDirectory->Append(this);
8319  if (pf) {
8320  file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8321  }
8322  }
8323 }
8324 
8325 ////////////////////////////////////////////////////////////////////////////////
8326 /// Change the name and title of this tree.
8327 
8328 void TTree::SetObject(const char* name, const char* title)
8330  if (gPad) {
8331  gPad->Modified();
8332  }
8333 
8334  // Trees are named objects in a THashList.
8335  // We must update hashlists if we change the name
8336  TFile *file = 0;
8337  TTreeCache *pf = 0;
8338  if (fDirectory) {
8339  fDirectory->Remove(this);
8340  if ((file = GetCurrentFile())) {
8341  pf = GetReadCache(file);
8342  file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8343  }
8344  }
8345  // This changes our hash value.
8346  fName = name;
8347  fTitle = title;
8348  if (fDirectory) {
8349  fDirectory->Append(this);
8350  if (pf) {
8351  file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8352  }
8353  }
8354 }
8355 
8356 ////////////////////////////////////////////////////////////////////////////////
8357 /// Enable or disable parallel unzipping of Tree buffers.
8358 
8359 void TTree::SetParallelUnzip(Bool_t opt, Float_t RelSize)
8363 
8364  if (RelSize > 0) {
8366  }
8367 
8368 }
8369 
8370 ////////////////////////////////////////////////////////////////////////////////
8371 /// Set perf stats
8372 
8375  fPerfStats = perf;
8376 }
8377 
8378 ////////////////////////////////////////////////////////////////////////////////
8379 /// The current TreeIndex is replaced by the new index.
8380 /// Note that this function does not delete the previous index.
8381 /// This gives the possibility to play with more than one index, e.g.,
8382 /// ~~~ {.cpp}
8383 /// TVirtualIndex* oldIndex = tree.GetTreeIndex();
8384 /// tree.SetTreeIndex(newIndex);
8385 /// tree.Draw();
8386 /// tree.SetTreeIndex(oldIndex);
8387 /// tree.Draw(); etc
8388 /// ~~~
8389 
8392  if (fTreeIndex) {
8393  fTreeIndex->SetTree(0);
8394  }
8395  fTreeIndex = index;
8396 }
8397 
8398 ////////////////////////////////////////////////////////////////////////////////
8399 /// Set tree weight.
8400 ///
8401 /// The weight is used by TTree::Draw to automatically weight each
8402 /// selected entry in the resulting histogram.
8403 ///
8404 /// For example the equivalent of:
8405 /// ~~~ {.cpp}
8406 /// T.Draw("x", "w")
8407 /// ~~~
8408 /// is:
8409 /// ~~~ {.cpp}
8410 /// T.SetWeight(w);
8411 /// T.Draw("x");
8412 /// ~~~
8413 /// This function is redefined by TChain::SetWeight. In case of a
8414 /// TChain, an option "global" may be specified to set the same weight
8415 /// for all trees in the TChain instead of the default behaviour
8416 /// using the weights of each tree in the chain (see TChain::SetWeight).
8417 
8420  fWeight = w;
8421 }
8422 
8423 ////////////////////////////////////////////////////////////////////////////////
8424 /// Print values of all active leaves for entry.
8425 ///
8426 /// - if entry==-1, print current entry (default)
8427 /// - if a leaf is an array, a maximum of lenmax elements is printed.
8428 
8429 void TTree::Show(Long64_t entry, Int_t lenmax)
8431  if (entry != -1) {
8432  Int_t ret = LoadTree(entry);
8433  if (ret == -2) {
8434  Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
8435  return;
8436  } else if (ret == -1) {
8437  Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8438  return;
8439  }
8440  ret = GetEntry(entry);
8441  if (ret == -1) {
8442  Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8443  return;
8444  } else if (ret == 0) {
8445  Error("Show()", "Cannot read entry %lld (no data read)", entry);
8446  return;
8447  }
8448  }
8449  printf("======> EVENT:%lld\n", fReadEntry);
8450  TObjArray* leaves = GetListOfLeaves();
8451  Int_t nleaves = leaves->GetEntriesFast();
8452  Int_t ltype;
8453  for (Int_t i = 0; i < nleaves; i++) {
8454  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
8455  TBranch* branch = leaf->GetBranch();
8456  if (branch->TestBit(kDoNotProcess)) {
8457  continue;
8458  }
8459  Int_t len = leaf->GetLen();
8460  if (len <= 0) {
8461  continue;
8462  }
8463  len = TMath::Min(len, lenmax);
8464  if (leaf->IsA() == TLeafElement::Class()) {
8465  leaf->PrintValue(lenmax);
8466  continue;
8467  }
8468  if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
8469  continue;
8470  }
8471  ltype = 10;
8472  if (leaf->IsA() == TLeafF::Class()) {
8473  ltype = 5;
8474  }
8475  if (leaf->IsA() == TLeafD::Class()) {
8476  ltype = 5;
8477  }
8478  if (leaf->IsA() == TLeafC::Class()) {
8479  len = 1;
8480  ltype = 5;
8481  };
8482  printf(" %-15s = ", leaf->GetName());
8483  for (Int_t l = 0; l < len; l++) {
8484  leaf->PrintValue(l);
8485  if (l == (len - 1)) {
8486  printf("\n");
8487  continue;
8488  }
8489  printf(", ");
8490  if ((l % ltype) == 0) {
8491  printf("\n ");
8492  }
8493  }
8494  }
8495 }
8496 
8497 ////////////////////////////////////////////////////////////////////////////////
8498 /// Start the TTreeViewer on this tree.
8499 ///
8500 /// - ww is the width of the canvas in pixels
8501 /// - wh is the height of the canvas in pixels
8502 
8503 void TTree::StartViewer()
8505  GetPlayer();
8506  if (fPlayer) {
8507  fPlayer->StartViewer(600, 400);
8508  }
8509 }
8510 
8511 ////////////////////////////////////////////////////////////////////////////////
8512 /// Stop the cache learning phase
8513 ///
8514 /// Returns:
8515 /// - 0 learning phase stopped or not active
8516 /// - -1 on error
8517 
8520  if (!GetTree()) {
8521  if (LoadTree(0)<0) {
8522  Error("StopCacheLearningPhase","Could not load a tree");
8523  return -1;
8524  }
8525  }
8526  if (GetTree()) {
8527  if (GetTree() != this) {
8528  return GetTree()->StopCacheLearningPhase();
8529  }
8530  } else {
8531  Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
8532  return -1;
8533  }
8534 
8535  TFile *f = GetCurrentFile();
8536  if (!f) {
8537  Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
8538  return -1;
8539  }
8540  TTreeCache *tc = GetReadCache(f,kTRUE);
8541  if (!tc) {
8542  Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
8543  return -1;
8544  }
8545  tc->StopLearningPhase();
8546  return 0;
8547 }
8548 
8549 ////////////////////////////////////////////////////////////////////////////////
8550 /// Set the fTree member for all branches and sub branches.
8551 
8552 static void TBranch__SetTree(TTree *tree, TObjArray &branches)
8554  Int_t nb = branches.GetEntriesFast();
8555  for (Int_t i = 0; i < nb; ++i) {
8556  TBranch* br = (TBranch*) branches.UncheckedAt(i);
8557  br->SetTree(tree);
8558 
8559  Int_t nBaskets = br->GetListOfBaskets()->GetEntries();
8560  Int_t writeBasket = br->GetWriteBasket();
8561  for (Int_t j=writeBasket,n=0;j>=0 && n<nBaskets;--j) {
8562  TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
8563  if (bk) {
8564  tree->IncrementTotalBuffers(bk->GetBufferSize());
8565  ++n;
8566  }
8567  }
8568 
8569  TBranch__SetTree(tree,*br->GetListOfBranches());
8570  }
8571 }
8572 
8573 ////////////////////////////////////////////////////////////////////////////////
8574 /// Set the fTree member for all friend elements.
8575 
8576 void TFriendElement__SetTree(TTree *tree, TList *frlist)
8578  if (frlist) {
8579  TObjLink *lnk = frlist->FirstLink();
8580  while (lnk) {
8581  TFriendElement *elem = (TFriendElement*)lnk->GetObject();
8582  elem->fParentTree = tree;
8583  lnk = lnk->Next();
8584  }
8585  }
8586 }
8587 
8588 ////////////////////////////////////////////////////////////////////////////////
8589 /// Stream a class object.
8590 
8591 void TTree::Streamer(TBuffer& b)
8592 {
8593  if (b.IsReading()) {
8594  UInt_t R__s, R__c;
8595  if (fDirectory) {
8596  fDirectory->Remove(this);
8597  //delete the file cache if it points to this Tree
8598  TFile *file = fDirectory->GetFile();
8599  MoveReadCache(file,0);
8600  }
8601  fDirectory = 0;
8604  Version_t R__v = b.ReadVersion(&R__s, &R__c);
8605  if (R__v > 4) {
8606  b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
8607 
8608  fBranches.SetOwner(kTRUE); // True needed only for R__v < 19 and most R__v == 19
8609 
8610  if (fBranchRef) fBranchRef->SetTree(this);
8613 
8614  if (fTreeIndex) {
8615  fTreeIndex->SetTree(this);
8616  }
8617  if (fIndex.fN) {
8618  Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
8619  fIndex.Set(0);
8620  fIndexValues.Set(0);
8621  }
8622  if (fEstimate <= 10000) {
8623  fEstimate = 1000000;
8624  }
8625  if (GetCacheAutoSize() != 0) {
8626  // a cache will be automatically created.
8627  // No need for TTreePlayer::Process to enable the cache
8628  fCacheSize = 0;
8629  } else if (fAutoFlush < 0) {
8630  // If there is no autoflush set, let's keep the cache completely
8631  // disable by default for now.
8633  } else if (fAutoFlush != 0) {
8634  // Estimate the cluster size.
8635  // This will allow TTree::Process to enable the cache.
8636  if (fZipBytes != 0) {
8638  } else if (fTotBytes != 0) {
8640  } else {
8641  fCacheSize = 30000000;
8642  }
8643  if (fCacheSize >= (INT_MAX / 4)) {
8644  fCacheSize = INT_MAX / 4;
8645  } else if (fCacheSize == 0) {
8646  fCacheSize = 30000000;
8647  }
8648  } else {
8649  fCacheSize = 0;
8650  }
8652  return;
8653  }
8654  //====process old versions before automatic schema evolution
8655  Stat_t djunk;
8656  Int_t ijunk;
8657  TNamed::Streamer(b);
8658  TAttLine::Streamer(b);
8659  TAttFill::Streamer(b);
8660  TAttMarker::Streamer(b);
8661  b >> fScanField;
8662  b >> ijunk; fMaxEntryLoop = (Long64_t)ijunk;
8663  b >> ijunk; fMaxVirtualSize = (Long64_t)ijunk;
8664  b >> djunk; fEntries = (Long64_t)djunk;
8665  b >> djunk; fTotBytes = (Long64_t)djunk;
8666  b >> djunk; fZipBytes = (Long64_t)djunk;
8667  b >> ijunk; fAutoSave = (Long64_t)ijunk;
8668  b >> ijunk; fEstimate = (Long64_t)ijunk;
8669  if (fEstimate <= 10000) fEstimate = 1000000;
8670  fBranches.Streamer(b);
8671  if (fBranchRef) fBranchRef->SetTree(this);
8673  fLeaves.Streamer(b);
8675  if (R__v > 1) fIndexValues.Streamer(b);
8676  if (R__v > 2) fIndex.Streamer(b);
8677  if (R__v > 3) {
8678  TList OldInfoList;
8679  OldInfoList.Streamer(b);
8680  OldInfoList.Delete();
8681  }
8682  fNClusterRange = 0;
8683  fDefaultEntryOffsetLen = 1000;
8685  b.CheckByteCount(R__s, R__c, TTree::IsA());
8686  //====end of old versions
8687  } else {
8688  if (fBranchRef) {
8689  fBranchRef->Clear();
8690  }
8691  TRefTable *table = TRefTable::GetRefTable();
8692  if (table) TRefTable::SetRefTable(0);
8693 
8694  b.WriteClassBuffer(TTree::Class(), this);
8695 
8696  if (table) TRefTable::SetRefTable(table);
8697  }
8698 }
8699 
8700 ////////////////////////////////////////////////////////////////////////////////
8701 /// Unbinned fit of one or more variable(s) from a tree.
8702 ///
8703 /// funcname is a TF1 function.
8704 ///
8705 /// See TTree::Draw for explanations of the other parameters.
8706 ///
8707 /// Fit the variable varexp using the function funcname using the
8708 /// selection cuts given by selection.
8709 ///
8710 /// The list of fit options is given in parameter option.
8711 ///
8712 /// - option = "Q" Quiet mode (minimum printing)
8713 /// - option = "V" Verbose mode (default is between Q and V)
8714 /// - option = "E" Perform better Errors estimation using Minos technique
8715 /// - option = "M" More. Improve fit results
8716 ///
8717 /// You can specify boundary limits for some or all parameters via
8718 /// ~~~ {.cpp}
8719 /// func->SetParLimits(p_number, parmin, parmax);
8720 /// ~~~
8721 /// if parmin>=parmax, the parameter is fixed
8722 ///
8723 /// Note that you are not forced to fix the limits for all parameters.
8724 /// For example, if you fit a function with 6 parameters, you can do:
8725 /// ~~~ {.cpp}
8726 /// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
8727 /// func->SetParLimits(4,-10,-4);
8728 /// func->SetParLimits(5, 1,1);
8729 /// ~~~
8730 /// With this setup:
8731 ///
8732 /// - Parameters 0->3 can vary freely
8733 /// - Parameter 4 has boundaries [-10,-4] with initial value -8
8734 /// - Parameter 5 is fixed to 100.
8735 ///
8736 /// For the fit to be meaningful, the function must be self-normalized.
8737 ///
8738 /// i.e. It must have the same integral regardless of the parameter
8739 /// settings. Otherwise the fit will effectively just maximize the
8740 /// area.
8741 ///
8742 /// It is mandatory to have a normalization variable
8743 /// which is fixed for the fit. e.g.
8744 /// ~~~ {.cpp}
8745 /// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
8746 /// f1->SetParameters(1, 3.1, 0.01);
8747 /// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
8748 /// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
8749 /// ~~~
8750 /// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
8751 ///
8752 /// Return status:
8753 ///
8754 /// - The function return the status of the fit in the following form
8755 /// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
8756 /// - The fitResult is 0 is the fit is OK.
8757 /// - The fitResult is negative in case of an error not connected with the fit.
8758 /// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
8759 /// - If the number of selected entries is null the function returns -1
8760 
8761 Int_t TTree::UnbinnedFit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
8763  GetPlayer();
8764  if (fPlayer) {
8765  return fPlayer->UnbinnedFit(funcname, varexp, selection, option, nentries, firstentry);
8766  }
8767  return -1;
8768 }
8769 
8770 ////////////////////////////////////////////////////////////////////////////////
8771 /// Replace current attributes by current style.
8772 
8775  if (gStyle->IsReading()) {
8784  } else {
8793  }
8794 }
8795 
8796 ////////////////////////////////////////////////////////////////////////////////
8797 /// Write this object to the current directory. For more see TObject::Write
8798 /// Write calls TTree::FlushBaskets before writing the tree.
8799 
8800 Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
8802  FlushBaskets();
8803  return TObject::Write(name, option, bufsize);
8804 }
8805 
8806 ////////////////////////////////////////////////////////////////////////////////
8807 /// Write this object to the current directory. For more see TObject::Write
8808 /// If option & kFlushBasket, call FlushBasket before writing the tree.
8809 
8810 Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize)
8812  return ((const TTree*)this)->Write(name, option, bufsize);
8813 }
8814 
8815 ////////////////////////////////////////////////////////////////////////////////
8816 /// \class TTreeFriendLeafIter
8817 ///
8818 /// Iterator on all the leaves in a TTree and its friend
8819 
8822 ////////////////////////////////////////////////////////////////////////////////
8823 /// Create a new iterator. By default the iteration direction
8824 /// is kIterForward. To go backward use kIterBackward.
8825 
8827 : fTree(const_cast<TTree*>(tree))
8828 , fLeafIter(0)
8829 , fTreeIter(0)
8830 , fDirection(dir)
8831 {
8832 }
8833 
8834 ////////////////////////////////////////////////////////////////////////////////
8835 /// Copy constructor. Does NOT copy the 'cursor' location!
8836 
8838 : TIterator(iter)
8839 , fTree(iter.fTree)
8840 , fLeafIter(0)
8841 , fTreeIter(0)
8842 , fDirection(iter.fDirection)
8843 {
8844 }
8845 
8846 ////////////////////////////////////////////////////////////////////////////////
8847 /// Overridden assignment operator. Does NOT copy the 'cursor' location!
8848 
8851  if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
8852  const TTreeFriendLeafIter &rhs1 = (const TTreeFriendLeafIter &)rhs;
8853  fDirection = rhs1.fDirection;
8854  }
8855  return *this;
8856 }
8857 
8858 ////////////////////////////////////////////////////////////////////////////////
8859 /// Overridden assignment operator. Does NOT copy the 'cursor' location!
8860 
8863  if (this != &rhs) {
8864  fDirection = rhs.fDirection;
8865  }
8866  return *this;
8867 }
8868 
8869 ////////////////////////////////////////////////////////////////////////////////
8870 /// Go the next friend element
8871 
8874  if (!fTree) return 0;
8875 
8876  TObject * next;
8877  TTree * nextTree;
8878 
8879  if (!fLeafIter) {
8880  TObjArray *list = fTree->GetListOfLeaves();
8881  if (!list) return 0; // Can happen with an empty chain.
8882  fLeafIter = list->MakeIterator(fDirection);
8883  if (!fLeafIter) return 0;
8884  }
8885 
8886  next = fLeafIter->Next();
8887  if (!next) {
8888  if (!fTreeIter) {
8889  TCollection * list = fTree->GetListOfFriends();
8890  if (!list) return next;
8891  fTreeIter = list->MakeIterator(fDirection);
8892  if (!fTreeIter) return 0;
8893  }
8894  TFriendElement * nextFriend = (TFriendElement*) fTreeIter->Next();
8895  ///nextTree = (TTree*)fTreeIter->Next();
8896  if (nextFriend) {
8897  nextTree = const_cast<TTree*>(nextFriend->GetTree());
8898  if (!nextTree) return Next();
8899  SafeDelete(fLeafIter);
8900  fLeafIter = nextTree->GetListOfLeaves()->MakeIterator(fDirection);
8901  if (!fLeafIter) return 0;
8902  next = fLeafIter->Next();
8903  }
8904  }
8905  return next;
8906 }
8907 
8908 ////////////////////////////////////////////////////////////////////////////////
8909 /// Returns the object option stored in the list.
8910 
8913  if (fLeafIter) return fLeafIter->GetOption();
8914  return "";
8915 }
A zero length substring is legal.
Definition: TString.h:83
TString fTitle
Definition: TNamed.h:37
TTree * fParentTree
void Add(TObject *obj, const char *name=0, Int_t check=-1)
Add object with name to browser.
Definition: TBrowser.cxx:259
virtual Int_t GetLen() const
Return the number of effective elements of this leaf.
Definition: TLeaf.cxx:276
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:47
virtual void UpdateAddress()
Definition: TBranch.h:217
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 'branchname', which can include the name of the tree or...
Definition: TTree.cxx:4511
virtual Int_t GetEntries() const
Definition: TCollection.h:92
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:823
virtual Bool_t GetReapplyCut() const
Definition: TEventList.h:59
Double_t fWeight
Definition: TTree.h:102
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
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:1265
virtual Int_t MakeProxy(const char *classname, const char *macrofilename=0, const char *cutfilename=0, const char *option=0, Int_t maxUnrolling=3)=0
virtual Style_t GetLineStyle() const
Definition: TAttLine.h:48
virtual Style_t GetFillStyle() const
Definition: TAttFill.h:44
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:37
virtual void SetLineWidth(Width_t lwidth)
Definition: TAttLine.h:57
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:864
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:5667
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:195
virtual TList * GetListOfClones()
Definition: TTree.h:404
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3448
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:2524
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
Debug level.
Definition: TTree.h:124
Principal Components Analysis (PCA)
Definition: TPrincipal.h:28
virtual Long64_t GetAutoSave() const
Definition: TTree.h:368
Bool_t IsAutoCreated() const
Definition: TTreeCache.h:89
virtual void Append(const TVirtualIndex *, Bool_t delaySort=kFALSE)=0
virtual void PrintValue(Int_t i=0) const
Definition: TLeaf.h:123
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
Bool_t fPrevious
Definition: TTree.h:181
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:404
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition: TBranch.cxx:2643
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2228
static Vc_ALWAYS_INLINE int_v min(const int_v &x, const int_v &y)
Definition: vector.h:433
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:2048
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:6369
virtual const char * GetFriendAlias(TTree *) const
If the 'tree' is a friend, this method returns its alias name.
Definition: TTree.cxx:5390
Bool_t MemoryFull(Int_t nbytes)
Check if adding nbytes to memory we are still below MaxVirtualsize.
Definition: TTree.cxx:6176
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:1444
Long64_t fTotalBuffers
Number of the entry being processed.
Definition: TTree.h:120
virtual Int_t MakeCode(const char *filename=0)
Generate a skeleton function for this tree.
Definition: TTree.cxx:5979
long long Long64_t
Definition: RtypesCore.h:69
Abstract interface for Tree Index.
Definition: TVirtualIndex.h:31
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition: TBranch.cxx:1459
virtual Int_t MakeReader(const char *classname, Option_t *option)=0
virtual const char * GetName() const
Return name of this collection.
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition: TTree.cxx:8519
Bool_t IsReading() const
Definition: TBuffer.h:81
virtual void SetBranchStatus(const char *bname, Bool_t status=1, UInt_t *found=0)
Set branch status to Process or DoNotProcess.
Definition: TTree.cxx:7675
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:487
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:155
virtual void IncrementTotalBuffers(Int_t nbytes)
Definition: TTree.h:460
short Version_t
Definition: RtypesCore.h:61
virtual void Delete(Option_t *option="")
Delete this tree from memory or/and disk.
Definition: TTree.cxx:3520
Int_t GetType() const
Definition: TDataType.h:70
A Branch for the case of an object.
Definition: TBranchObject.h:28
ClassImp(TSeqCollection) Int_t TSeqCollection TIter next(this)
Return index of object in collection.
Ssiz_t Length() const
Definition: TString.h:390
TObjArray * GetListOfBaskets()
Definition: TBranch.h:176
TLine * line
static Int_t fgBranchStyle
true if the cache setting was explicitly given by user
Definition: TTree.h:149
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:5783
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:297
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:1362
static Long64_t GetMaxTreeSize()
Static function which returns the tree file size limit in bytes.
Definition: TTree.cxx:5614
virtual void SetParallelUnzip(Bool_t opt=kTRUE, Float_t RelSize=-1)
Enable or disable parallel unzipping of Tree buffers.
Definition: TTree.cxx:8360
virtual Int_t MakeCode(const char *filename)=0
Provides the interface for the PROOF internal performance measurement and event tracing.
Style_t GetHistLineStyle() const
Definition: TStyle.h:244
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:6345
TTree()
Default constructor and I/O constructor.
Definition: TTree.cxx:626
void GetObject(const char *namecycle, T *&ptr)
Definition: TDirectory.h:144
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:328
virtual Long64_t GetReadEntry() const
Definition: TTree.h:424
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:33
TBuffer * fTransientBuffer
Record which method is locking the friend recursion.
Definition: TTree.h:145
virtual void Flush()
Synchronize a file's in-memory and on-disk states.
Definition: TFile.cxx:1080
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=0, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition: TFile.cxx:2177
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:4739
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
R__EXTERN TStyle * gStyle
Definition: TStyle.h:423
TList * fFriends
Definition: TTree.h:138
void SetHistLineWidth(Width_t width=1)
Definition: TStyle.h:378
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:6495
const char Int_t perf
Definition: TXSlave.cxx:46
#define gDirectory
Definition: TDirectory.h:218
virtual Int_t Fill()
Fill all branches.
Definition: TTree.cxx:4328
virtual TEntryList * GetEntryList()
Returns the entry list, set to this tree.
Definition: TTree.cxx:5213
virtual void SetName(const char *name)
Change (i.e.
Definition: TNamed.cxx:128
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual TList * GetList() const
Definition: TDirectory.h:154
virtual void DropBaskets(Option_t *option="")
Loop on all branch baskets.
Definition: TBranch.cxx:626
Long64_t GetCacheAutoSize(Bool_t withDefault=kFALSE) const
Used for automatic sizing of the cache.
Definition: TTree.cxx:4945
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5552
static void SetBranchStyle(Int_t style=1)
Set the current branch style.
Definition: TTree.cxx:7801
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:5539
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:5039
TTree * fTree
Definition: TTree.h:179
static Int_t SetParallelUnzip(TTreeCacheUnzip::EParUnzipMode option=TTreeCacheUnzip::kEnable)
Static function that (de)activates multithreading unzipping.
Double_t Atof() const
Return floating-point value contained in string.
Definition: TString.cxx:2030
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:892
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:45
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:5449
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:1617
virtual void Print(Option_t *option="") const
Print TBranch parameters.
Definition: TBranch.cxx:1726
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
Regular expression class.
Definition: TRegexp.h:35
TDirectory * fDirectory
Object to be notified when loading a Tree.
Definition: TTree.h:129
static const char * filename()
Bool_t IsPersistent() const
Definition: TDataMember.h:89
Int_t fMakeClass
Last entry number to debug.
Definition: TTree.h:126
#define R__ASSERT(e)
Definition: TError.h:98
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition: TTree.cxx:3504
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
#define gROOT
Definition: TROOT.h:340
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3539
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
TObject * ob
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:7486
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:5163
virtual Int_t ReadKeys(Bool_t=kTRUE)
Definition: TDirectory.h:179
Bool_t IsZombie() const
Definition: TObject.h:141
Basic string class.
Definition: TString.h:137
virtual TTree * GetFriend(const char *) const
Return a pointer to the TTree friend whose name or alias is 'friendname.
Definition: TTree.cxx:5333
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:6107
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:1088
static TBranch * R__FindBranchHelper(TObjArray *list, const char *branchname)
Search in the array for a branch matching the branch name, with the branch possibly expressed as a 'f...
Definition: TTree.cxx:4463
TAlienJobStatus * status
Definition: TAlienJob.cxx:51
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TDataType * GetDataType() const
Definition: TDataMember.h:74
virtual void PrintCacheStats(Option_t *option="") const
print statistics about the TreeCache for this tree, like ******TreeCache statistics for file: cms2...
Definition: TTree.cxx:6628
Bool_t IsaPointer() const
Return true if data member is a pointer.
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual void Browse(TBrowser *)
Browse content of the TTree.
Definition: TTree.cxx:2484
constexpr std::array< decltype(std::declval< F >)(std::declval< int >))), N > make(F f)
virtual void SetFillStyle(Style_t fstyle)
Definition: TAttFill.h:52
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:496
TBranch * GetBranch() const
Definition: TLeaf.h:70
virtual Long64_t GetBasketSeek(Int_t basket) const
Return address of basket in the file.
Definition: TBranch.cxx:1143
virtual void StopLearningPhase()
This is the counterpart of StartLearningPhase() and can be used to stop the learning phase...
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition: TTree.cxx:5224
Int_t fScanField
Definition: TTree.h:104
virtual Long64_t GetEND() const
Definition: TFile.h:191
virtual Int_t FlushBaskets() const
Write to disk all the basket that have not yet been individually written.
Definition: TTree.cxx:4753
Int_t GetEntriesFast() const
Definition: TObjArray.h:66
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition: TTree.cxx:2961
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:3492
Definition: drr.cxx:518
virtual TVirtualIndex * GetTreeIndex() const
Definition: TTree.h:433
virtual void KeepCircular()
Keep a maximum of fMaxEntries in memory.
Definition: TTree.cxx:5747
TArrayD fIndexValues
Pointer to event selection list (if one)
Definition: TTree.h:135
Style_t GetHistFillStyle() const
Definition: TStyle.h:243
TTree * GetTree() const
Definition: TTreeCache.h:88
void SetAutoCreated(Bool_t val)
Definition: TTreeCache.h:101
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition: TTree.cxx:5006
virtual EDataType GetType() const =0
virtual Long64_t GetEntries(const char *)=0
Long64_t fMaxEntryLoop
Definition: TTree.h:110
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition: TTree.cxx:5653
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition: TTree.h:541
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:6769
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 'human readeable' format.
Definition: StringConv.h: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:330
virtual Int_t DeleteGlobal(void *obj)=0
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:310
virtual void SetupAddresses()
If the branch address is not set, we set all addresses starting with the top level parent branch...
Definition: TBranch.cxx:2633
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...
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns an array iterator.
Definition: TObjArray.cxx:590
Iterator abstract base class.
Definition: TIterator.h:32
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
virtual void Print(Option_t *option="") const
Print cache statistics.
Definition: TTreeCache.cxx:994
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:732
virtual void Reset(Option_t *option="")
Definition: TBranchRef.cxx:184
const char * GetArrayIndex() const
If the data member is pointer and has a valid array size in its comments GetArrayIndex returns a stri...
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 void Refresh()
Refresh contents of this tree and its branches from the current status on disk.
Definition: TTree.cxx:7148
virtual void SetFileNumber(Int_t number=0)
Set fFileNumber to number.
Definition: TTree.cxx:8258
virtual Double_t GetMinimum(const char *columname)
Return minimum of column with name columname.
Definition: TTree.cxx:5624
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:3592
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:3851
virtual void SetTree(TTree *tree)
Definition: TBranch.h:215
virtual void SetDirectory(TDirectory *dir)
Add reference to directory dir. dir can be 0.
TList * GetListOfRealData() const
Definition: TClass.h:405
static void SetRefTable(TRefTable *table)
Static function setting the current TRefTable.
Definition: TRefTable.cxx:381
virtual Int_t GetN() const
Definition: TEventList.h:58
virtual void StartViewer()
Start the TTreeViewer on this tree.
Definition: TTree.cxx:8504
virtual Long64_t Merge(TCollection *list, Option_t *option="")
Merge the trees in the TList into this tree.
Definition: TTree.cxx:6233
Marker Attributes class.
Definition: TAttMarker.h:32
const char * Data() const
Definition: TString.h:349
virtual void Print(Option_t *option="") const
Print a summary of the tree contents.
Definition: TTree.cxx:6514
virtual void SetBranchFolder()
virtual TKey * GetKey(const char *, Short_t=9999) const
Definition: TDirectory.h:153
TFileCacheRead * GetCacheRead(TObject *tree=0) const
Return a pointer to the current read cache.
Definition: TFile.cxx:1196
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:946
virtual Int_t GetEntryWithIndex(Int_t major, Int_t minor=0)
Read entry corresponding to major and minor number.
Definition: TTree.cxx:5286
TList * fAliases
Definition: TTree.h:132
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.h:86
virtual Long64_t DrawSelect(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
#define SafeDelete(p)
Definition: RConfig.h:436
virtual TObjArray * GetListOfBranches()
Definition: TTree.h:405
Helper class to iterate over cluster of baskets.
Definition: TTree.h:245
TVirtualTreePlayer * fPlayer
Definition: TTree.h:141
Double_t dot(const TVector2 &v1, const TVector2 &v2)
Definition: CsgOps.cxx:333
Fill Area Attributes class.
Definition: TAttFill.h:32
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in 'fromtree' to this tree, including the value of fAuto...
Definition: TTree.cxx:5708
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:7401
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:2334
Int_t GetCompressionLevel() const
Definition: TFile.h:357
virtual const char * GetTreeName() const
void Class()
Definition: Class.C:29
virtual Long64_t CopyEntries(TTree *tree, Long64_t nentries=-1, Option_t *option="")
Copy nentries from given tree to this tree.
Definition: TTree.cxx:3323
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:7529
void SetHistFillColor(Color_t color=1)
Definition: TStyle.h:374
Int_t fNfill
Number of entries in one packet for parallel root.
Definition: TTree.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:8329
virtual void ReadValue(std::istream &, Char_t= ' ')
Definition: TLeaf.h:95
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:33
Int_t GetNbytes() const
Definition: TKey.h:88
virtual Bool_t Notify()
This method must be overridden to handle object notification.
Definition: TObject.cxx:550
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition: TTree.cxx:5804
Bool_t fCacheUserSet
true if cache auto creation or resize check is needed
Definition: TTree.h:147
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition: TTree.cxx:8391
Int_t fMaxClusterRange
Definition: TTree.h:108
static Int_t GetBranchStyle()
Static function returning the current branch style.
Definition: TTree.cxx:4933
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4683
virtual Int_t BuildIndex(const char *majorname, const char *minorname="0")
Build a Tree Index (default is TTreeIndex).
Definition: TTree.cxx:2509
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:8762
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:2293
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:1857
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition: TClass.cxx:2524
virtual void Show(Long64_t entry=-1, Int_t lenmax=20)
Print values of all active leaves for entry.
Definition: TTree.cxx:8430
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
virtual Int_t GetBufferSize() const
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition: TBranch.cxx:893
TBranchRef * fBranchRef
List of cloned trees which share our addresses.
Definition: TTree.h:143
virtual Int_t MakeClass(const char *classname=0, Option_t *option="")
Generate a skeleton analysis class for this tree.
Definition: TTree.cxx:5946
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1627
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition: TTree.cxx:4995
virtual void SetMarkerColor(Color_t mcolor=1)
Definition: TAttMarker.h:51
const Int_t kDoNotProcess
Definition: TBranch.h:52
UInt_t fFriendLockStatus
Definition: TTree.h:144
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
const int maxsize
virtual Int_t MakeClass(const char *classname, const char *option)=0
Int_t fTimerInterval
Definition: TTree.h:103
Long64_t GetEntries() const
Definition: TBranch.h:182
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition: TTree.cxx:1157
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:1635
Bool_t IsWritable() const
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:7304
Long64_t fFlushedBytes
Definition: TTree.h:101
TObjArray * GetListOfBranches()
Definition: TBranch.h:177
Specialization of TTreeCache for parallel Unzipping.
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:63
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 Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
Bool_t IsObject() const
Definition: TRealData.h:60
virtual void Delete(Option_t *option="")
Delete an object from the file.
Definition: TKey.cxx:531
virtual Double_t GetMaximum(const char *columname)
Return maximum of column with name columname.
Definition: TTree.cxx:5585
void Set(Int_t n)
Set size of this array to n ints.
Definition: TArrayI.cxx:104
virtual void RemoveFriend(TTree *)
Remove a friend from the list of friends.
Definition: TTree.cxx:7187
virtual void SetAddress(void *add=0)
Definition: TLeaf.h:124
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition: TTree.cxx:5692
virtual void SetCacheLearnEntries(Int_t n=10)
Interface to TTreeCache to set the number of entries for the learning phase.
Definition: TTree.cxx:7994
A branch containing and managing a TRefTable for TRef autoloading.
Definition: TBranchRef.h:33
Long64_t fZipBytes
Definition: TTree.h:99
Long64_t fDebugMax
First entry number to debug.
Definition: TTree.h:125
virtual Double_t GetValue(Int_t i=0) const
Definition: TLeaf.h:122
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:1363
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:8195
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition: TBuffer.cxx:199
ClassImp(TTree) static char DataTypeToChar(EDataType datatype)
Definition: TTree.cxx:397
void UseCurrentStyle()
Replace current attributes by current style.
Definition: TTree.cxx:8774
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:1964
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:4822
Bool_t fCacheDoAutoInit
Pointer to the current transient buffer.
Definition: TTree.h:146
virtual TFile * GetFile() const
Definition: TDirectory.h:152
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:1233
virtual Int_t GetMaximum() const
Definition: TLeaf.h:76
virtual Int_t Fill()
Loop on all leaves of this branch to fill Basket buffer.
Definition: TBranch.cxx:723
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:91
TObjArray fLeaves
Definition: TTree.h:131
Long64_t * fClusterRangeEnd
Definition: TTree.h:115
static TVirtualTreePlayer * TreePlayer(TTree *obj)
virtual Long64_t GetTotBytes() const
Definition: TTree.h:431
virtual void SetLineColor(Color_t lcolor)
Definition: TAttLine.h:54
Bool_t IsReading() const
Definition: TStyle.h:296
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1937
Int_t GetBufferSize() const
Definition: TBasket.h:75
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:41
Int_t fNClusterRange
Definition: TTree.h:107
Int_t fN
Definition: TArray.h:40
virtual Long64_t GetEntry(Int_t index) const
Return value of entry at index in the list.
Definition: TEventList.cxx:220
Bool_t HasRuleWithSourceClass(const TString &source) const
Return True if we have any rule whose source class is 'source'.
virtual char * GetAddress() const
Definition: TBranch.h:146
TEntryList * fEntryList
Pointer to event selection list (if one)
Definition: TTree.h:134
void SetParentClass(TClass *clparent)
virtual Size_t GetMarkerSize() const
Definition: TAttMarker.h:46
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...
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
Option_t * GetOption() const
Returns the object option stored in the list.
Definition: TTree.cxx:8912
Color_t GetHistFillColor() const
Definition: TStyle.h:241
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:8811
TVirtualStreamerInfo * FindConversionStreamerInfo(const char *onfile_classname, UInt_t checksum) const
Return a Conversion StreamerInfo from the class 'classname' for the layout represented by 'checksum' ...
Definition: TClass.cxx:6711
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition: TTree.cxx:8236
Width_t GetHistLineWidth() const
Definition: TStyle.h:245
virtual void SetOffset(Int_t offset=0)
Definition: TBranch.h:213
virtual Long64_t Process(const char *filename, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual void UpdateFormulaLeaves()=0
virtual Int_t DropBranch(TBranch *b, Bool_t subbranches=kFALSE)
Remove a branch to the list of branches to be stored in the cache this function is called by TBranch:...
Definition: TTreeCache.cxx:482
void SetHistFillStyle(Style_t styl=0)
Definition: TStyle.h:376
TObjArray * GetElements() const
void SetCompressionSettings(Int_t settings=1)
Set compression settings.
Definition: TBranch.cxx:2171
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
Long64_t fChainOffset
Maximum size of file buffers.
Definition: TTree.h:118
~TFriendLock()
Restore the state of tree the same as before we set the lock.
Definition: TTree.cxx:484
Long64_t * fClusterSize
Definition: TTree.h:116
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:4337
Bool_t EqualTo(const char *cs, ECaseCompare cmp=kExact) const
Definition: TString.h:576
virtual void WriteStreamerInfo()
Write the list of TStreamerInfo as a single object in this file The class Streamer description for al...
Definition: TFile.cxx:3561
virtual void SetFillColor(Color_t fcolor)
Definition: TAttFill.h:50
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:8577
TVirtualPerfStats * fPerfStats
Definition: TTree.h:139
virtual Int_t GetTreeNumber() const
Definition: TTree.h:434
virtual TIterator * MakeIterator(Bool_t dir=kIterForward) const =0
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TObjArray.cxx:629
TDirectory * GetDirectory() const
Definition: TTree.h:381
TVirtualStreamerInfo * GetConversionStreamerInfo(const char *onfile_classname, Int_t version) const
Return a Conversion StreamerInfo from the class 'classname' for version number 'version' to this clas...
Definition: TClass.cxx:6614
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx:494
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:187
virtual Int_t ReadTObject(TObject *, const char *)
Definition: TDirectory.h:180
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:674
Long64_t fReadEntry
Offset of 1st entry of this Tree in a TChain.
Definition: TTree.h:119
virtual Bool_t HasPointers() const =0
virtual ~TTree()
Destructor.
Definition: TTree.cxx:801
virtual Color_t GetFillColor() const
Definition: TAttFill.h:43
Collection abstract base class.
Definition: TCollection.h:48
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition: TTree.cxx:4781
TClass * IsA() const
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5040
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1532
TList * fUserInfo
pointer to the current perf stats object
Definition: TTree.h:140
TObjArray fBranches
Pointer to directory holding this tree.
Definition: TTree.h:130
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2321
unsigned int UInt_t
Definition: RtypesCore.h:42
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:173
TMarker * m
Definition: textangle.C:8
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:8292
virtual Long64_t GetEntry(Int_t index)
Return the number of the entry #index of this TEntryList in the TTree or TChain See also Next()...
Definition: TEntryList.cxx:653
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition: TFile.cxx:1388
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:151
Manages buffers for branches of a Tree.
Definition: TBasket.h:38
virtual TBranchRef * GetBranchRef() const
Definition: TTree.h:370
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:4583
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:1198
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5269
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:358
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
TArrayI fIndex
Definition: TTree.h:136
TSubString Strip(EStripType s=kTrailing, char c= ' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1069
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
virtual void SetMarkerStyle(Style_t mstyle=1)
Definition: TAttMarker.h:53
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...
Version_t GetClassVersion() const
Definition: TClass.h:382
Bool_t IsNull() const
Definition: TString.h:387
virtual TObjLink * FirstLink() const
Definition: TList.h:101
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:7275
Bool_t fDirection
Definition: TTree.h:578
virtual Color_t GetLineColor() const
Definition: TAttLine.h:47
Long64_t entry
TEventList * fEventList
Definition: TTree.h:133
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:2187
virtual void SetMarkerSize(Size_t msize=1)
Definition: TAttMarker.h:54
Long64_t fMaxEntries
Memory allocated for the cluster range.
Definition: TTree.h:109
TTree * GetTree() const
Definition: TBranch.h:183
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:1072
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2240
virtual void KeepCircular(Long64_t maxEntries)
keep a maximum of fMaxEntries in memory
Definition: TBranch.cxx:1672
virtual TLeaf * GetLeafCount() const
Definition: TLeaf.h:71
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:6839
A Branch for the case of an object.
#define Printf
Definition: TGeoToOCC.h:18
virtual Int_t DropBranchFromCache(const char *bname, Bool_t subbranches=kFALSE)
Remove the branch with name 'bname' from the Tree cache.
Definition: TTree.cxx:995
Int_t GetCompressionSettings() const
Definition: TFile.h:363
Long64_t fAutoSave
Definition: TTree.h:112
virtual void SaveSelf(Bool_t=kFALSE)
Definition: TDirectory.h:186
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:2095
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:2712
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:8057
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:6706
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
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition: TClass.cxx:5526
virtual Int_t GetBasketSize() const
Definition: TBranch.h:151
int Ssiz_t
Definition: RtypesCore.h:63
virtual Long64_t ReadStream(std::istream &inputStream, const char *branchDescriptor="", char delimiter= ' ')
Create or simply read branches from an input stream.
Definition: TTree.cxx:6866
virtual void DropBuffers(Int_t nbytes)
Drop branch buffers to accommodate nbytes below MaxVirtualsize.
Definition: TTree.cxx:4260
virtual Int_t Fill()
Fill the branch basket with the referenced objects parent numbers.
Definition: TBranchRef.cxx:100
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:8272
virtual void SetWeight(Double_t w=1, Option_t *option="")
Set tree weight.
Definition: TTree.cxx:8419
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition: TTree.cxx:575
virtual Int_t GetSize() const
Definition: TCollection.h:95
virtual void SetDirectory(TDirectory *dir)
Change the tree's directory.
Definition: TTree.cxx:8095
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:5896
virtual void SetEstimate(Long64_t n)=0
virtual Long64_t GetAutoFlush() const
Definition: TTree.h:367
Long64_t fMaxVirtualSize
Definition: TTree.h:111
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
double f(double x)
TCollection * GetListOfFolders() const
Definition: TFolder.h:57
virtual void StartViewer(Int_t ww, Int_t wh)=0
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition: TTree.cxx:8172
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator. Does NOT copy the 'cursor' location!
Definition: TTree.cxx:8850
virtual void ResetAddress()
Reset the address of the branch.
Definition: TBranch.cxx:2017
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:415
double Double_t
Definition: RtypesCore.h:55
virtual void Clear(Option_t *option="")
Clear entries in the TRefTable.
Definition: TBranchRef.cxx:92
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
Definition: TRefTable.cxx:285
void SetHistLineStyle(Style_t styl=0)
Definition: TStyle.h:377
Long64_t fTotBytes
Definition: TTree.h:98
virtual void WaitFinishPrefetch()
TClass * GetClass() const
Definition: TClonesArray.h:57
Describe directory structure in memory.
Definition: TDirectory.h:41
virtual void SetPerfStats(TVirtualPerfStats *perf)
Set perf stats.
Definition: TTree.cxx:8374
static void TBranch__SetTree(TTree *tree, TObjArray &branches)
Set the fTree member for all branches and sub branches.
Definition: TTree.cxx:8553
virtual Long64_t GetEntriesFast() const
Definition: TTree.h:384
R__EXTERN TEnv * gEnv
Definition: TEnv.h:174
unsigned long long ULong64_t
Definition: RtypesCore.h:70
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
TNamed()
Definition: TNamed.h:40
Long64_t fAutoFlush
Definition: TTree.h:113
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition: TTree.cxx:7285
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:356
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
Int_t GetKeylen() const
Definition: TKey.h:86
EDataType
Definition: TDataType.h:30
Int_t fDefaultEntryOffsetLen
Definition: TTree.h:106
const std::type_info * GetTypeInfo() const
Definition: TClass.h:451
virtual TTree * GetTree() const
Definition: TTree.h:432
void Browse(TBrowser *b)
Browse this collection (called by TBrowser).
Int_t GetNleaves() const
Definition: TBranch.h:180
Color_t GetHistLineColor() const
Definition: TStyle.h:242
TObjArray * GetListOfLeaves()
Definition: TBranch.h:178
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:493
Long64_t fEstimate
Definition: TTree.h:114
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any. ...
static void SetUnzipRelBufferSize(Float_t relbufferSize)
static function: Sets the unzip relatibe buffer size
UInt_t fMethodBit
Definition: TTree.h:180
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition: TTree.h:176
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:2881
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:7817
Int_t fDebug
Local for EntryLoop.
Definition: TTree.h:123
EOnIndexError
Definition: TTree.cxx:3220
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:7843
double Stat_t
Definition: RtypesCore.h:73
virtual void SetLineStyle(Style_t lstyle)
Definition: TAttLine.h:56
static Vc_ALWAYS_INLINE int_v max(const int_v &x, const int_v &y)
Definition: vector.h:440
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2810
#define name(a, b)
Definition: linkTestLib0.cpp:5
virtual void SetBasketSize(const char *bname, Int_t buffsize=16000)
Set a branch's basket size.
Definition: TTree.cxx:7502
virtual TFile * GetFile()
Return pointer to TFile containing this friend TTree.
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition: TTree.cxx:2111
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data)...
Definition: TTree.cxx:7244
virtual Bool_t SetAlias(const char *aliasName, const char *aliasFormula)
Set a tree variable alias.
Definition: TTree.cxx:7346
Int_t fFileNumber
not zero when processing code generated by MakeClass
Definition: TTree.h:127
Mother of all ROOT objects.
Definition: TObject.h:58
virtual Long64_t ReadFile(const char *filename, const char *branchDescriptor="", char delimiter= ' ')
Create or simply read branches from filename.
Definition: TTree.cxx:6820
Int_t fUpdate
Definition: TTree.h:105
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:177
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:1624
TDirectory * fOutputDirectory
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:556
virtual void SetEntryOffsetLen(Int_t len, Bool_t updateSubBranches=kFALSE)
Update the default value for the branch's fEntryOffsetLen if and only if it was already non zero (and...
Definition: TBranch.cxx:2187
virtual Long64_t Scan(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual void SetFile(TFile *file=0)
Set file where this branch writes/reads its buffers.
Definition: TBranch.cxx:2229
Long64_t fEntries
Definition: TTree.h:97
Int_t BufferSize() const
Definition: TBuffer.h:92
TList * fClones
Pointer to current Tree player.
Definition: TTree.h:142
Int_t GetMaxBaskets() const
Definition: TBranch.h:179
virtual void Refresh(TBranch *b)
Refresh this branch using new information in b This function is called by TTree::Refresh.
Definition: TBranch.cxx:1874
virtual Int_t MakeSelector(const char *selector=0, Option_t *option="")
Generate skeleton selector class for this tree.
Definition: TTree.cxx:6161
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:890
virtual Color_t GetMarkerColor() const
Definition: TAttMarker.h:44
virtual TDirectory * GetDirectory() const
Definition: TEntryList.h:76
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:433
virtual Int_t DropBuffers()
Drop buffers of this basket if it is not the current basket.
Definition: TBasket.cxx:191
ROOT::ESTLType IsSTLContainer()
Return which type (if any) of STL container the data member is.
Definition: TBaseClass.cxx:100
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 * GetValuePointer() const
Definition: TLeaf.h:80
virtual void Add(TObject *obj)
Definition: TList.h:81
const Ssiz_t kNPOS
Definition: Rtypes.h:115
TClusterIterator(TTree *tree, Long64_t firstEntry)
Regular constructor.
Definition: TTree.cxx:501
Int_t Length() const
Definition: TBuffer.h:94
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition: TList.cxx:634
Int_t GetClassVersion()
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:1923
A TFriendElement TF describes a TTree object TF in a file.
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
virtual Bool_t IsWritable() const
Definition: TDirectory.h:168
virtual const char * GetMinorName() const =0
Iterator on all the leaves in a TTree and its friend.
Definition: TTree.h:572
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:2195
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:7117
virtual Int_t LoadBaskets()
Baskets associated to this branch are forced to be in memory.
Definition: TBranch.cxx:1697
#define NULL
Definition: Rtypes.h:82
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1838
#define gPad
Definition: TVirtualPad.h:288
virtual void SetCircular(Long64_t maxEntries)
Enable/Disable circularity for this tree.
Definition: TTree.cxx:8021
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition: TTree.cxx:7213
virtual const char * GetMajorName() const =0
ROOT::ESTLType GetCollectionType() const
Return the 'type' of the STL the TClass is representing.
Definition: TClass.cxx:2799
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
TObject * fNotify
current file number (if file extensions)
Definition: TTree.h:128
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition: TTree.cxx:7960
void Add(TObject *obj)
Definition: TObjArray.h:75
virtual Long64_t GetEntries() const
Definition: TTree.h:382
A TTree object has a header with a name and a title.
Definition: TTree.h:94
TVirtualIndex * fTreeIndex
Definition: TTree.h:137
TFriendLock & operator=(const TFriendLock &)
Assignment operator.
Definition: TTree.cxx:471
Int_t SetBranchAddressImp(TBranch *branch, void *addr, TBranch **ptr)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:7586
TDataMember * GetDataMember() const
Definition: TRealData.h:57
virtual TVirtualIndex * BuildIndex(const TTree *T, const char *majorname, const char *minorname)=0
void ResetBit(UInt_t f)
Definition: TObject.h:172
virtual void SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting=kFALSE)
Update the default value for the branch's fEntryOffsetLen.
Definition: TTree.cxx:8069
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4579
Int_t GetMakeClass() const
Definition: TTree.h:412
virtual TObject ** GetObjectRef(const TObject *obj) const =0
TObject * Next()
Go the next friend element.
Definition: TTree.cxx:8873
virtual void DropBaskets()
Remove some baskets from memory.
Definition: TTree.cxx:4247
Int_t FlushBaskets()
Flush to disk all the baskets of this branch and any of subbranches.
Definition: TBranch.cxx:994
Bool_t HasDataMemberInfo() const
Definition: TClass.h:371
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:5433
static Long64_t fgMaxTreeSize
Definition: TTree.h:150
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
virtual void WriteHeader()
Write File Header.
Definition: TFile.cxx:2396
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:1381
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition: TTree.cxx:8140
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:504
virtual void Compress()
Remove empty slots from array.
Definition: TObjArray.cxx:308
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
virtual TFile * ChangeFile(TFile *file)
Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
Definition: TTree.cxx:2599
virtual Int_t Occurence(const TObject *obj) const
Return occurence number of object in the list of objects of this folder.
Definition: TFolder.cxx:434
static TTree * MergeTrees(TList *list, Option_t *option="")
Static function merging the trees in the TList into a new tree.
Definition: TTree.cxx:6190
A TTree is a list of TBranches.
Definition: TBranch.h:58
virtual Bool_t GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition: TTree.cxx:4918
virtual Style_t GetMarkerStyle() const
Definition: TAttMarker.h:45
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 Width_t GetLineWidth() const
Definition: TAttLine.h:49
virtual const char * GetName() const
Returns name of object.
Definition: TRealData.h:56
Long_t GetThisOffset() const
Definition: TRealData.h:59
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:459
virtual void SetTitle(const char *title="")
Change (i.e. set) the title of the TNamed.
Definition: TNamed.cxx:152
void SetHistLineColor(Color_t color=1)
Definition: TStyle.h:375
TObject * obj
A List of entry numbers in a TTree or TChain.
Definition: TEntryList.h:27
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5249
virtual Int_t AddBranchToCache(const char *bname, Bool_t subbranches=kFALSE)
Add branch with name bname to the Tree cache.
Definition: TTree.cxx:912
Int_t fPacketSize
Total number of bytes in branch buffers.
Definition: TTree.h:121
void Set(Int_t n)
Set size of this array to n doubles.
Definition: TArrayD.cxx:104
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:6754
Line Attributes class.
Definition: TAttLine.h:32
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor) const =0
Int_t GetWriteBasket() const
Definition: TBranch.h:170
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Definition: TMath.h:944
TFriendLock(const TFriendLock &)
Copy constructor.
Definition: TTree.cxx:461
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:466
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
Definition: TBranch.cxx:2302
Int_t GetReadBasket() const
Definition: TBranch.h:168
virtual void SetName(const char *name)
Change the name of this tree.
Definition: TTree.cxx:8300
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:544
void MoveReadCache(TFile *src, TDirectory *dir)
Move a cache from a file to the current file in dir.
Definition: TTree.cxx:6323
virtual void CopyAddresses(TTree *, Bool_t undo=kFALSE)
Set branch addresses of passed tree equal to ours.
Definition: TTree.cxx:3116
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:406
static void ResetCount()
Static function resetting fgCount.
Definition: TBranch.cxx:2040
Long64_t fSavedBytes
Definition: TTree.h:100
Long64_t fCacheSize
Definition: TTree.h:117
virtual void Print(Option_t *option="") const
Print the TRefTable branch.
Definition: TBranchRef.cxx:156
virtual Long64_t AutoSave(Option_t *option="")
AutoSave tree header every fAutoSave bytes.
Definition: TTree.cxx:1309
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904