Logo ROOT   6.07/09
Reference Guide
TTree.cxx
Go to the documentation of this file.
1 // @(#)root/tree:$Id$
2 // Author: Rene Brun 12/01/96
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 /**
12  \defgroup tree Tree Library
13 
14  To store large quantities of same-class objects, ROOT provides the TTree and
15  TNtuple classes. The TTree class is optimized to
16  reduce disk space and enhance access speed. A TNtuple is a TTree that is limited
17  to only hold floating-point numbers; a TTree on the other hand can hold all kind
18  of data, such as objects or arrays in addition to all the simple types.
19 
20 */
21 
22 /** \class TTree
23 \ingroup tree
24 
25 A TTree object has a header with a name and a title.
26 
27 It consists of a list of independent branches (TBranch). Each branch has its own
28 definition and list of buffers. Branch buffers may be automatically written to
29 disk or kept in memory until the Tree attribute `fMaxVirtualSize` is reached.
30 Variables of one branch are written to the same buffer. A branch buffer is
31 automatically compressed if the file compression attribute is set (default).
32 
33 Branches may be written to different files (see TBranch::SetFile).
34 
35 The ROOT user can decide to make one single branch and serialize one object into
36 one single I/O buffer or to make several branches. Making one single branch and
37 one single buffer can be the right choice when one wants to process only a subset
38 of all entries in the tree. (you know for example the list of entry numbers you
39 want to process). Making several branches is particularly interesting in the
40 data analysis phase, when one wants to histogram some attributes of an object
41 (entry) without reading all the attributes.
42 ~~~ {.cpp}
43  TTree *tree = new TTree(name, title)
44 ~~~
45 Creates a Tree with name and title.
46 
47 Various kinds of branches can be added to a tree:
48 
49 - simple structures or list of variables. (may be for C or Fortran structures)
50 - any object (inheriting from TObject). (we expect this option be the most frequent)
51 - a ClonesArray. (a specialized object for collections of same class objects)
52 
53 
54 ## Case A
55 
56 ~~~ {.cpp}
57  TBranch *branch = tree->Branch(branchname, address, leaflist, bufsize)
58 ~~~
59 - address is the address of the first item of a structure
60 - leaflist is the concatenation of all the variable names and types
61  separated by a colon character :
62  The variable name and the variable type are separated by a
63  slash (/). The variable type must be 1 character. (Characters
64  after the first are legal and will be appended to the visible
65  name of the leaf, but have no effect.) If no type is given, the
66  type of the variable is assumed to be the same as the previous
67  variable. If the first variable does not have a type, it is
68  assumed of type F by default. The list of currently supported
69  types is given below:
70  - `C` : a character string terminated by the 0 character
71  - `B` : an 8 bit signed integer (`Char_t`)
72  - `b` : an 8 bit unsigned integer (`UChar_t`)
73  - `S` : a 16 bit signed integer (`Short_t`)
74  - `s` : a 16 bit unsigned integer (`UShort_t`)
75  - `I` : a 32 bit signed integer (`Int_t`)
76  - `i` : a 32 bit unsigned integer (`UInt_t`)
77  - `F` : a 32 bit floating point (`Float_t`)
78  - `D` : a 64 bit floating point (`Double_t`)
79  - `L` : a 64 bit signed integer (`Long64_t`)
80  - `l` : a 64 bit unsigned integer (`ULong64_t`)
81  - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
82 - If the address points to a single numerical variable, the leaflist is optional:
83  int value;
84  `tree->Branch(branchname, &value);`
85 - If the address points to more than one numerical variable, we strongly recommend
86  that the variable be sorted in decreasing order of size. Any other order will
87  result in a non-portable (even between CINT and compiled code on the platform)
88  TTree (i.e. you will not be able to read it back on a platform with a different
89  padding strategy).
90 
91 
92 ## Case B
93 
94 ~~~ {.cpp}
95  TBranch *branch = tree->Branch(branchname, &p_object, bufsize, splitlevel)
96  TBranch *branch = tree->Branch(branchname, className, &p_object, bufsize, splitlevel)
97 ~~~
98 - p_object is a pointer to an object.
99 - If className is not specified, Branch uses the type of p_object to determine the
100  type of the object.
101 - If className is used to specify explicitly the object type, the className must
102  be of a type related to the one pointed to by the pointer. It should be either
103  a parent or derived class.
104 - if splitlevel=0, the object is serialized in the branch buffer.
105 - if splitlevel=1, this branch will automatically be split
106  into subbranches, with one subbranch for each data member or object
107  of the object itself. In case the object member is a TClonesArray,
108  the mechanism described in case C is applied to this array.
109 - if splitlevel=2 ,this branch will automatically be split
110  into subbranches, with one subbranch for each data member or object
111  of the object itself. In case the object member is a TClonesArray,
112  it is processed as a TObject*, only one branch.
113 
114 Note: The pointer whose address is passed to TTree::Branch must not
115  be destroyed (i.e. go out of scope) until the TTree is deleted or
116  TTree::ResetBranchAddress is called.
117 
118 Note: The pointer p_object must be initialized before calling TTree::Branch
119 - Do either:
120 ~~~ {.cpp}
121  MyDataClass* p_object = 0;
122  tree->Branch(branchname, &p_object);
123 ~~~
124 - Or:
125 ~~~ {.cpp}
126  MyDataClass* p_object = new MyDataClass;
127  tree->Branch(branchname, &p_object);
128 ~~~
129 Whether the pointer is set to zero or not, the ownership of the object
130 is not taken over by the TTree. I.e. even though an object will be allocated
131 by TTree::Branch if the pointer p_object is zero, the object will <b>not</b>
132 be deleted when the TTree is deleted.
133 
134 
135 ## Case C
136 
137 ~~~ {.cpp}
138  MyClass object;
139  TBranch *branch = tree->Branch(branchname, &object, bufsize, splitlevel)
140 ~~~
141 Note: The 2nd parameter must be the address of a valid object.
142  The object must not be destroyed (i.e. be deleted) until the TTree
143  is deleted or TTree::ResetBranchAddress is called.
144 
145 - if splitlevel=0, the object is serialized in the branch buffer.
146 - if splitlevel=1 (default), this branch will automatically be split
147  into subbranches, with one subbranch for each data member or object
148  of the object itself. In case the object member is a TClonesArray,
149  the mechanism described in case C is applied to this array.
150 - if splitlevel=2 ,this branch will automatically be split
151  into subbranches, with one subbranch for each data member or object
152  of the object itself. In case the object member is a TClonesArray,
153  it is processed as a TObject*, only one branch.
154 
155 
156 ## Case D
157 
158 ~~~ {.cpp}
159  TBranch *branch = tree->Branch(branchname,clonesarray, bufsize, splitlevel)
160  clonesarray is the address of a pointer to a TClonesArray.
161 ~~~
162 The TClonesArray is a direct access list of objects of the same class.
163 For example, if the TClonesArray is an array of TTrack objects,
164 this function will create one subbranch for each data member of
165 the object TTrack.
166 
167 
168 ## Case E
169 
170 ~~~ {.cpp}
171  TBranch *branch = tree->Branch( branchname, STLcollection, buffsize, splitlevel);
172 ~~~
173 STLcollection is the address of a pointer to std::vector, std::list,
174 std::deque, std::set or std::multiset containing pointers to objects.
175 If the splitlevel is a value bigger than 100 (TTree::kSplitCollectionOfPointers)
176 then the collection will be written in split mode, e.g. if it contains objects of
177 any types deriving from TTrack this function will sort the objects
178 based on their type and store them in separate branches in split
179 mode.
180 ~~~ {.cpp}
181  branch->SetAddress(Void *address)
182 ~~~
183 In case of dynamic structures changing with each entry for example, one must
184 redefine the branch address before filling the branch again.
185 This is done via the TBranch::SetAddress member function.
186 ~~~ {.cpp}
187  tree->Fill()
188 ~~~
189 loops on all defined branches and for each branch invokes the Fill function.
190 
191 See also the class TNtuple (a simple Tree with branches of floats)
192 and the class TNtupleD (a simple Tree with branches of doubles)
193 
194 ## Adding a Branch to an Existing Tree
195 
196 You may want to add a branch to an existing tree. For example,
197 if one variable in the tree was computed with a certain algorithm,
198 you may want to try another algorithm and compare the results.
199 One solution is to add a new branch, fill it, and save the tree.
200 The code below adds a simple branch to an existing tree.
201 Note the kOverwrite option in the Write method, it overwrites the
202 existing tree. If it is not specified, two copies of the tree headers
203 are saved.
204 ~~~ {.cpp}
205  void tree3AddBranch() {
206  TFile f("tree3.root", "update");
207 
208  Float_t new_v;
209  TTree *t3 = (TTree*)f->Get("t3");
210  TBranch *newBranch = t3->Branch("new_v", &new_v, "new_v/F");
211 
212  Long64_t nentries = t3->GetEntries(); // read the number of entries in the t3
213 
214  for (Long64_t i = 0; i < nentries; i++) {
215  new_v= gRandom->Gaus(0, 1);
216  newBranch->Fill();
217  }
218 
219  t3->Write("", TObject::kOverwrite); // save only the new version of the tree
220  }
221 ~~~
222 Adding a branch is often not possible because the tree is in a read-only
223 file and you do not have permission to save the modified tree with the
224 new branch. Even if you do have the permission, you risk losing the
225 original tree with an unsuccessful attempt to save the modification.
226 Since trees are usually large, adding a branch could extend it over the
227 2GB limit. In this case, the attempt to write the tree fails, and the
228 original data is erased.
229 In addition, adding a branch to a tree enlarges the tree and increases
230 the amount of memory needed to read an entry, and therefore decreases
231 the performance.
232 
233 For these reasons, ROOT offers the concept of friends for trees (and chains).
234 We encourage you to use TTree::AddFriend rather than adding a branch manually.
235 
236 Begin_Macro
237 ../../../tutorials/tree/tree.C
238 End_Macro
239 
240 ~~~ {.cpp}
241  // A simple example with histograms and a tree
242  //
243  // This program creates :
244  // - a one dimensional histogram
245  // - a two dimensional histogram
246  // - a profile histogram
247  // - a tree
248  //
249  // These objects are filled with some random numbers and saved on a file.
250 
251  #include "TFile.h"
252  #include "TH1.h"
253  #include "TH2.h"
254  #include "TProfile.h"
255  #include "TRandom.h"
256  #include "TTree.h"
257 
258  //__________________________________________________________________________
259  main(int argc, char **argv)
260  {
261  // Create a new ROOT binary machine independent file.
262  // Note that this file may contain any kind of ROOT objects, histograms,trees
263  // pictures, graphics objects, detector geometries, tracks, events, etc..
264  // This file is now becoming the current directory.
265  TFile hfile("htree.root","RECREATE","Demo ROOT file with histograms & trees");
266 
267  // Create some histograms and a profile histogram
268  TH1F *hpx = new TH1F("hpx","This is the px distribution",100,-4,4);
269  TH2F *hpxpy = new TH2F("hpxpy","py ps px",40,-4,4,40,-4,4);
270  TProfile *hprof = new TProfile("hprof","Profile of pz versus px",100,-4,4,0,20);
271 
272  // Define some simple structures
273  typedef struct {Float_t x,y,z;} POINT;
274  typedef struct {
275  Int_t ntrack,nseg,nvertex;
276  UInt_t flag;
277  Float_t temperature;
278  } EVENTN;
279  static POINT point;
280  static EVENTN eventn;
281 
282  // Create a ROOT Tree
283  TTree *tree = new TTree("T","An example of ROOT tree with a few branches");
284  tree->Branch("point",&point,"x:y:z");
285  tree->Branch("eventn",&eventn,"ntrack/I:nseg:nvertex:flag/i:temperature/F");
286  tree->Branch("hpx","TH1F",&hpx,128000,0);
287 
288  Float_t px,py,pz;
289  static Float_t p[3];
290 
291  // Here we start a loop on 1000 events
292  for ( Int_t i=0; i<1000; i++) {
293  gRandom->Rannor(px,py);
294  pz = px*px + py*py;
295  Float_t random = gRandom->::Rndm(1);
296 
297  // Fill histograms
298  hpx->Fill(px);
299  hpxpy->Fill(px,py,1);
300  hprof->Fill(px,pz,1);
301 
302  // Fill structures
303  p[0] = px;
304  p[1] = py;
305  p[2] = pz;
306  point.x = 10*(random-1);;
307  point.y = 5*random;
308  point.z = 20*random;
309  eventn.ntrack = Int_t(100*random);
310  eventn.nseg = Int_t(2*eventn.ntrack);
311  eventn.nvertex = 1;
312  eventn.flag = Int_t(random+0.5);
313  eventn.temperature = 20+random;
314 
315  // Fill the tree. For each event, save the 2 structures and 3 objects
316  // In this simple example, the objects hpx, hprof and hpxpy are slightly
317  // different from event to event. We expect a big compression factor!
318  tree->Fill();
319  }
320  // End of the loop
321 
322  tree->Print();
323 
324  // Save all objects in this file
325  hfile.Write();
326 
327  // Close the file. Note that this is automatically done when you leave
328  // the application.
329  hfile.Close();
330 
331  return 0;
332 }
333 ~~~
334 */
335 
336 #include "RConfig.h"
337 #include "TTree.h"
338 
339 #include "TArrayC.h"
340 #include "TBufferFile.h"
341 #include "TBaseClass.h"
342 #include "TBasket.h"
343 #include "TBranchClones.h"
344 #include "TBranchElement.h"
345 #include "TBranchObject.h"
346 #include "TBranchRef.h"
347 #include "TBrowser.h"
348 #include "TClass.h"
349 #include "TClassEdit.h"
350 #include "TClonesArray.h"
351 #include "TCut.h"
352 #include "TDataMember.h"
353 #include "TDataType.h"
354 #include "TDirectory.h"
355 #include "TError.h"
356 #include "TEntryList.h"
357 #include "TEnv.h"
358 #include "TEventList.h"
359 #include "TFile.h"
360 #include "TFolder.h"
361 #include "TFriendElement.h"
362 #include "TInterpreter.h"
363 #include "TLeaf.h"
364 #include "TLeafB.h"
365 #include "TLeafC.h"
366 #include "TLeafD.h"
367 #include "TLeafElement.h"
368 #include "TLeafF.h"
369 #include "TLeafI.h"
370 #include "TLeafL.h"
371 #include "TLeafObject.h"
372 #include "TLeafS.h"
373 #include "TList.h"
374 #include "TMath.h"
375 #include "TROOT.h"
376 #include "TRealData.h"
377 #include "TRegexp.h"
378 #include "TStreamerElement.h"
379 #include "TStreamerInfo.h"
380 #include "TStyle.h"
381 #include "TSystem.h"
382 #include "TTreeCloner.h"
383 #include "TTreeCache.h"
384 #include "TTreeCacheUnzip.h"
385 #include "TVirtualCollectionProxy.h"
387 #include "TVirtualFitter.h"
388 #include "TVirtualIndex.h"
389 #include "TVirtualPerfStats.h"
390 #include "TVirtualPad.h"
391 #include "TBranchSTL.h"
392 #include "TSchemaRuleSet.h"
393 #include "TFileMergeInfo.h"
394 #include "ROOT/StringConv.hxx"
395 
396 #include <chrono>
397 #include <cstddef>
398 #include <iostream>
399 #include <fstream>
400 #include <sstream>
401 #include <string>
402 #include <stdio.h>
403 #include <limits.h>
404 
405 #ifdef R__USE_IMT
406 #include "tbb/task.h"
407 #include "tbb/task_group.h"
408 #include <thread>
409 #include <string>
410 #include <sstream>
411 #endif
412 
413 constexpr Int_t kNEntriesResort = 100;
416 Int_t TTree::fgBranchStyle = 1; // Use new TBranch style with TBranchElement.
417 Long64_t TTree::fgMaxTreeSize = 100000000000LL;
418 
420 
421 ////////////////////////////////////////////////////////////////////////////////
422 ////////////////////////////////////////////////////////////////////////////////
423 ////////////////////////////////////////////////////////////////////////////////
424 
425 static char DataTypeToChar(EDataType datatype)
426 {
427  // Return the leaflist 'char' for a given datatype.
428 
429  switch(datatype) {
430  case kChar_t: return 'B';
431  case kUChar_t: return 'b';
432  case kBool_t: return 'O';
433  case kShort_t: return 'S';
434  case kUShort_t: return 's';
435  case kCounter:
436  case kInt_t: return 'I';
437  case kUInt_t: return 'i';
438  case kDouble_t:
439  case kDouble32_t: return 'D';
440  case kFloat_t:
441  case kFloat16_t: return 'F';
442  case kLong_t: return 0; // unsupported
443  case kULong_t: return 0; // unsupported?
444  case kchar: return 0; // unsupported
445  case kLong64_t: return 'L';
446  case kULong64_t: return 'l';
447 
448  case kCharStar: return 'C';
449  case kBits: return 0; //unsupported
450 
451  case kOther_t:
452  case kNoType_t:
453  default:
454  return 0;
455  }
456  return 0;
457 }
458 
459 ////////////////////////////////////////////////////////////////////////////////
460 /// \class TTree::TFriendLock
461 /// Helper class to prevent infinite recursion in the usage of TTree Friends.
462 
463 ////////////////////////////////////////////////////////////////////////////////
464 /// Record in tree that it has been used while recursively looks through the friends.
465 
467 : fTree(tree)
468 {
469  // We could also add some code to acquire an actual
470  // lock to prevent multi-thread issues
471  fMethodBit = methodbit;
472  if (fTree) {
473  fPrevious = fTree->fFriendLockStatus & fMethodBit;
474  fTree->fFriendLockStatus |= fMethodBit;
475  } else {
476  fPrevious = 0;
477  }
478 }
479 
480 ////////////////////////////////////////////////////////////////////////////////
481 /// Copy constructor.
482 
484  fTree(tfl.fTree),
485  fMethodBit(tfl.fMethodBit),
486  fPrevious(tfl.fPrevious)
487 {
488 }
489 
490 ////////////////////////////////////////////////////////////////////////////////
491 /// Assignment operator.
492 
494 {
495  if(this!=&tfl) {
496  fTree=tfl.fTree;
498  fPrevious=tfl.fPrevious;
499  }
500  return *this;
501 }
502 
503 ////////////////////////////////////////////////////////////////////////////////
504 /// Restore the state of tree the same as before we set the lock.
505 
507 {
508  if (fTree) {
509  if (!fPrevious) {
511  }
512  }
513 }
514 
515 ////////////////////////////////////////////////////////////////////////////////
516 /// \class TTree::TClusterIterator
517 /// Helper class to iterate over cluster of baskets.
518 
519 ////////////////////////////////////////////////////////////////////////////////
520 /// Regular constructor.
521 /// TTree is not set as const, since we might modify if it is a TChain.
522 
523 TTree::TClusterIterator::TClusterIterator(TTree *tree, Long64_t firstEntry) : fTree(tree), fClusterRange(0), fStartEntry(0), fNextEntry(0)
524 {
525  if ( fTree->GetAutoFlush() <= 0 ) {
526  // Case of old files before November 9 2009
527  fStartEntry = firstEntry;
528  } else if (fTree->fNClusterRange) {
529  // Find the correct cluster range.
530  //
531  // Since fClusterRangeEnd contains the inclusive upper end of the range, we need to search for the
532  // range that was containing the previous entry and add 1 (because BinarySearch consider the values
533  // to be the inclusive start of the bucket).
534  fClusterRange = TMath::BinarySearch(fTree->fNClusterRange, fTree->fClusterRangeEnd, firstEntry - 1) + 1;
535 
536  Long64_t entryInRange;
537  Long64_t pedestal;
538  if (fClusterRange == 0) {
539  pedestal = 0;
540  entryInRange = firstEntry;
541  } else {
542  pedestal = fTree->fClusterRangeEnd[fClusterRange-1] + 1;
543  entryInRange = firstEntry - pedestal;
544  }
545  Long64_t autoflush;
546  if (fClusterRange == fTree->fNClusterRange) {
547  autoflush = fTree->fAutoFlush;
548  } else {
549  autoflush = fTree->fClusterSize[fClusterRange];
550  }
551  if (autoflush == 0) {
552  autoflush = GetEstimatedClusterSize();
553  }
554  fStartEntry = pedestal + entryInRange - entryInRange%autoflush;
555  } else {
556  fStartEntry = firstEntry - firstEntry%fTree->GetAutoFlush();
557  }
558  fNextEntry = fStartEntry; // Position correctly for the first call to Next()
559 }
560 
561 ////////////////////////////////////////////////////////////////////////////////
562 /// In the case where the cluster size was not fixed (old files and
563 /// case where autoflush was explicitly set to zero, we need estimate
564 /// a cluster size in relation to the size of the cache.
565 
567 {
568  Long64_t zipBytes = fTree->GetZipBytes();
569  if (zipBytes == 0) {
570  return fTree->GetEntries() - 1;
571  } else {
572  Long64_t clusterEstimate = 1;
573  Long64_t cacheSize = fTree->GetCacheSize();
574  if (cacheSize == 0) {
575  // Humm ... let's double check on the file.
577  if (file) {
578  TFileCacheRead *cache = file->GetCacheRead(fTree);
579  if (cache) {
580  cacheSize = cache->GetBufferSize();
581  }
582  }
583  }
584  if (cacheSize > 0) {
585  clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
586  if (clusterEstimate == 0)
587  clusterEstimate = 1;
588  }
589  return clusterEstimate;
590  }
591 }
592 
593 ////////////////////////////////////////////////////////////////////////////////
594 /// Move on to the next cluster and return the starting entry
595 /// of this next cluster
596 
598 {
599  fStartEntry = fNextEntry;
600  if ( fTree->GetAutoFlush() <= 0 ) {
601  // Case of old files before November 9 2009
602  Long64_t clusterEstimate = GetEstimatedClusterSize();
603  fNextEntry = fStartEntry + clusterEstimate;
604  } else {
605  if (fClusterRange == fTree->fNClusterRange) {
606  // We are looking at the last range ; its size
607  // is defined by AutoFlush itself and goes to the GetEntries.
608  fNextEntry += fTree->GetAutoFlush();
609  } else {
610  if (fStartEntry > fTree->fClusterRangeEnd[fClusterRange]) {
611  ++fClusterRange;
612  }
613  if (fClusterRange == fTree->fNClusterRange) {
614  // We are looking at the last range which size
615  // is defined by AutoFlush itself and goes to the GetEntries.
616  fNextEntry += fTree->GetAutoFlush();
617  } else {
618  Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
619  if (clusterSize == 0) {
620  clusterSize = GetEstimatedClusterSize();
621  }
622  fNextEntry += clusterSize;
623  if (fNextEntry > fTree->fClusterRangeEnd[fClusterRange]) {
624  // The last cluster of the range was a partial cluster,
625  // so the next cluster starts at the beginning of the
626  // next range.
627  fNextEntry = fTree->fClusterRangeEnd[fClusterRange] + 1;
628  }
629  }
630  }
631  }
632  if (fNextEntry > fTree->GetEntries()) {
633  fNextEntry = fTree->GetEntries();
634  }
635  return fStartEntry;
636 }
637 
638 ////////////////////////////////////////////////////////////////////////////////
639 ////////////////////////////////////////////////////////////////////////////////
640 ////////////////////////////////////////////////////////////////////////////////
641 
642 ////////////////////////////////////////////////////////////////////////////////
643 /// Default constructor and I/O constructor.
644 ///
645 /// Note: We do *not* insert ourself into the current directory.
646 ///
647 
648 TTree::TTree()
650 , TAttLine()
651 , TAttFill()
652 , TAttMarker()
653 , fEntries(0)
654 , fTotBytes(0)
655 , fZipBytes(0)
656 , fSavedBytes(0)
657 , fFlushedBytes(0)
658 , fWeight(1)
659 , fTimerInterval(0)
660 , fScanField(25)
661 , fUpdate(0)
663 , fNClusterRange(0)
664 , fMaxClusterRange(0)
665 , fMaxEntries(0)
666 , fMaxEntryLoop(0)
667 , fMaxVirtualSize(0)
668 , fAutoSave( -300000000)
669 , fAutoFlush(-30000000)
670 , fEstimate(1000000)
671 , fClusterRangeEnd(0)
672 , fClusterSize(0)
673 , fCacheSize(0)
674 , fChainOffset(0)
675 , fReadEntry(-1)
676 , fTotalBuffers(0)
677 , fPacketSize(100)
678 , fNfill(0)
679 , fDebug(0)
680 , fDebugMin(0)
681 , fDebugMax(9999999)
682 , fMakeClass(0)
683 , fFileNumber(0)
684 , fNotify(0)
685 , fDirectory(0)
686 , fBranches()
687 , fLeaves()
688 , fAliases(0)
689 , fEventList(0)
690 , fEntryList(0)
691 , fIndexValues()
692 , fIndex()
693 , fTreeIndex(0)
694 , fFriends(0)
695 , fPerfStats(0)
696 , fUserInfo(0)
697 , fPlayer(0)
698 , fClones(0)
699 , fBranchRef(0)
701 , fTransientBuffer(0)
706 {
707  fMaxEntries = 1000000000;
708  fMaxEntries *= 1000;
709 
710  fMaxEntryLoop = 1000000000;
711  fMaxEntryLoop *= 1000;
712 
714 }
715 
716 ////////////////////////////////////////////////////////////////////////////////
717 /// Normal tree constructor.
718 ///
719 /// The tree is created in the current directory.
720 /// Use the various functions Branch below to add branches to this tree.
721 ///
722 /// If the first character of title is a "/", the function assumes a folder name.
723 /// In this case, it creates automatically branches following the folder hierarchy.
724 /// splitlevel may be used in this case to control the split level.
725 
726 TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */)
727 : TNamed(name, title)
728 , TAttLine()
729 , TAttFill()
730 , TAttMarker()
731 , fEntries(0)
732 , fTotBytes(0)
733 , fZipBytes(0)
734 , fSavedBytes(0)
735 , fFlushedBytes(0)
736 , fWeight(1)
737 , fTimerInterval(0)
738 , fScanField(25)
739 , fUpdate(0)
741 , fNClusterRange(0)
742 , fMaxClusterRange(0)
743 , fMaxEntries(0)
744 , fMaxEntryLoop(0)
745 , fMaxVirtualSize(0)
746 , fAutoSave( -300000000)
747 , fAutoFlush(-30000000)
748 , fEstimate(1000000)
749 , fClusterRangeEnd(0)
750 , fClusterSize(0)
751 , fCacheSize(0)
752 , fChainOffset(0)
753 , fReadEntry(-1)
754 , fTotalBuffers(0)
755 , fPacketSize(100)
756 , fNfill(0)
757 , fDebug(0)
758 , fDebugMin(0)
759 , fDebugMax(9999999)
760 , fMakeClass(0)
761 , fFileNumber(0)
762 , fNotify(0)
763 , fDirectory(0)
764 , fBranches()
765 , fLeaves()
766 , fAliases(0)
767 , fEventList(0)
768 , fEntryList(0)
769 , fIndexValues()
770 , fIndex()
771 , fTreeIndex(0)
772 , fFriends(0)
773 , fPerfStats(0)
774 , fUserInfo(0)
775 , fPlayer(0)
776 , fClones(0)
777 , fBranchRef(0)
779 , fTransientBuffer(0)
784 {
785  // TAttLine state.
789 
790  // TAttFill state.
793 
794  // TAttMarkerState.
798 
799  fMaxEntries = 1000000000;
800  fMaxEntries *= 1000;
801 
802  fMaxEntryLoop = 1000000000;
803  fMaxEntryLoop *= 1000;
804 
805  // Insert ourself into the current directory.
806  // FIXME: This is very annoying behaviour, we should
807  // be able to choose to not do this like we
808  // can with a histogram.
810  if (fDirectory) fDirectory->Append(this);
811 
813 
814  // If title starts with "/" and is a valid folder name, a superbranch
815  // is created.
816  // FIXME: Why?
817  if (strlen(title) > 2) {
818  if (title[0] == '/') {
819  Branch(title+1,32000,splitlevel);
820  }
821  }
822 }
823 
824 ////////////////////////////////////////////////////////////////////////////////
825 /// Destructor.
826 
828 {
829  if (fDirectory) {
830  // We are in a directory, which may possibly be a file.
831  if (fDirectory->GetList()) {
832  // Remove us from the directory listing.
833  fDirectory->Remove(this);
834  }
835  //delete the file cache if it points to this Tree
837  MoveReadCache(file,0);
838  }
839  // We don't own the leaves in fLeaves, the branches do.
840  fLeaves.Clear();
841  // I'm ready to destroy any objects allocated by
842  // SetAddress() by my branches. If I have clones,
843  // tell them to zero their pointers to this shared
844  // memory.
845  if (fClones && fClones->GetEntries()) {
846  // I have clones.
847  // I am about to delete the objects created by
848  // SetAddress() which we are sharing, so tell
849  // the clones to release their pointers to them.
850  for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
851  TTree* clone = (TTree*) lnk->GetObject();
852  // clone->ResetBranchAddresses();
853 
854  // Reset only the branch we have set the address of.
855  CopyAddresses(clone,kTRUE);
856  }
857  }
858  // Get rid of our branches, note that this will also release
859  // any memory allocated by TBranchElement::SetAddress().
860  fBranches.Delete();
861  // FIXME: We must consider what to do with the reset of these if we are a clone.
862  delete fPlayer;
863  fPlayer = 0;
864  if (fFriends) {
865  fFriends->Delete();
866  delete fFriends;
867  fFriends = 0;
868  }
869  if (fAliases) {
870  fAliases->Delete();
871  delete fAliases;
872  fAliases = 0;
873  }
874  if (fUserInfo) {
875  fUserInfo->Delete();
876  delete fUserInfo;
877  fUserInfo = 0;
878  }
879  if (fClones) {
880  // Clone trees should no longer be removed from fClones when they are deleted.
881  gROOT->GetListOfCleanups()->Remove(fClones);
882  // Note: fClones does not own its content.
883  delete fClones;
884  fClones = 0;
885  }
886  if (fEntryList) {
888  // Delete the entry list if it is marked to be deleted and it is not also
889  // owned by a directory. (Otherwise we would need to make sure that a
890  // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
891  delete fEntryList;
892  fEntryList=0;
893  }
894  }
895  delete fTreeIndex;
896  fTreeIndex = 0;
897  delete fBranchRef;
898  fBranchRef = 0;
899  delete [] fClusterRangeEnd;
900  fClusterRangeEnd = 0;
901  delete [] fClusterSize;
902  fClusterSize = 0;
903  // Must be done after the destruction of friends.
904  // Note: We do *not* own our directory.
905  fDirectory = 0;
906 
907  if (fTransientBuffer) {
908  delete fTransientBuffer;
909  fTransientBuffer = 0;
910  }
911 }
912 
913 ////////////////////////////////////////////////////////////////////////////////
914 /// Returns the transient buffer currently used by this TTree for reading/writing baskets.
915 
917 {
918  if (fTransientBuffer) {
919  if (fTransientBuffer->BufferSize() < size) {
920  fTransientBuffer->Expand(size);
921  }
922  return fTransientBuffer;
923  }
925  return fTransientBuffer;
926 }
927 
928 ////////////////////////////////////////////////////////////////////////////////
929 /// Add branch with name bname to the Tree cache.
930 /// If bname="*" all branches are added to the cache.
931 /// if subbranches is true all the branches of the subbranches are
932 /// also put to the cache.
933 ///
934 /// Returns:
935 /// - 0 branch added or already included
936 /// - -1 on error
937 
938 Int_t TTree::AddBranchToCache(const char*bname, Bool_t subbranches)
939 {
940  if (!GetTree()) {
941  if (LoadTree(0)<0) {
942  Error("AddBranchToCache","Could not load a tree");
943  return -1;
944  }
945  }
946  if (GetTree()) {
947  if (GetTree() != this) {
948  return GetTree()->AddBranchToCache(bname, subbranches);
949  }
950  } else {
951  Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
952  return -1;
953  }
954 
955  TFile *f = GetCurrentFile();
956  if (!f) {
957  Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
958  return -1;
959  }
960  TTreeCache *tc = GetReadCache(f,kTRUE);
961  if (!tc) {
962  Error("AddBranchToCache", "No cache is available, branch not added");
963  return -1;
964  }
965  return tc->AddBranch(bname,subbranches);
966 }
967 
968 ////////////////////////////////////////////////////////////////////////////////
969 /// Add branch b to the Tree cache.
970 /// if subbranches is true all the branches of the subbranches are
971 /// also put to the cache.
972 ///
973 /// Returns:
974 /// - 0 branch added or already included
975 /// - -1 on error
976 
978 {
979  if (!GetTree()) {
980  if (LoadTree(0)<0) {
981  Error("AddBranchToCache","Could not load a tree");
982  return -1;
983  }
984  }
985  if (GetTree()) {
986  if (GetTree() != this) {
987  Int_t res = GetTree()->AddBranchToCache(b, subbranches);
988  if (res<0) {
989  Error("AddBranchToCache", "Error adding branch");
990  }
991  return res;
992  }
993  } else {
994  Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
995  return -1;
996  }
997 
998  TFile *f = GetCurrentFile();
999  if (!f) {
1000  Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1001  return -1;
1002  }
1003  TTreeCache *tc = GetReadCache(f,kTRUE);
1004  if (!tc) {
1005  Error("AddBranchToCache", "No cache is available, branch not added");
1006  return -1;
1007  }
1008  return tc->AddBranch(b,subbranches);
1009 }
1010 
1011 ////////////////////////////////////////////////////////////////////////////////
1012 /// Remove the branch with name 'bname' from the Tree cache.
1013 /// If bname="*" all branches are removed from the cache.
1014 /// if subbranches is true all the branches of the subbranches are
1015 /// also removed from the cache.
1016 ///
1017 /// Returns:
1018 /// - 0 branch dropped or not in cache
1019 /// - -1 on error
1020 
1021 Int_t TTree::DropBranchFromCache(const char*bname, Bool_t subbranches)
1023  if (!GetTree()) {
1024  if (LoadTree(0)<0) {
1025  Error("DropBranchFromCache","Could not load a tree");
1026  return -1;
1027  }
1028  }
1029  if (GetTree()) {
1030  if (GetTree() != this) {
1031  return GetTree()->DropBranchFromCache(bname, subbranches);
1032  }
1033  } else {
1034  Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1035  return -1;
1036  }
1037 
1038  TFile *f = GetCurrentFile();
1039  if (!f) {
1040  Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1041  return -1;
1042  }
1043  TTreeCache *tc = GetReadCache(f,kTRUE);
1044  if (!tc) {
1045  Error("DropBranchFromCache", "No cache is available, branch not dropped");
1046  return -1;
1047  }
1048  return tc->DropBranch(bname,subbranches);
1049 }
1050 
1051 ////////////////////////////////////////////////////////////////////////////////
1052 /// Remove the branch b from the Tree cache.
1053 /// if subbranches is true all the branches of the subbranches are
1054 /// also removed from the cache.
1055 ///
1056 /// Returns:
1057 /// - 0 branch dropped or not in cache
1058 /// - -1 on error
1059 
1062  if (!GetTree()) {
1063  if (LoadTree(0)<0) {
1064  Error("DropBranchFromCache","Could not load a tree");
1065  return -1;
1066  }
1067  }
1068  if (GetTree()) {
1069  if (GetTree() != this) {
1070  Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1071  if (res<0) {
1072  Error("DropBranchFromCache", "Error dropping branch");
1073  }
1074  return res;
1075  }
1076  } else {
1077  Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1078  return -1;
1079  }
1080 
1081  TFile *f = GetCurrentFile();
1082  if (!f) {
1083  Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1084  return -1;
1085  }
1086  TTreeCache *tc = GetReadCache(f,kTRUE);
1087  if (!tc) {
1088  Error("DropBranchFromCache", "No cache is available, branch not dropped");
1089  return -1;
1090  }
1091  return tc->DropBranch(b,subbranches);
1092 }
1093 
1094 ////////////////////////////////////////////////////////////////////////////////
1095 /// Add a cloned tree to our list of trees to be notified whenever we change
1096 /// our branch addresses or when we are deleted.
1097 
1098 void TTree::AddClone(TTree* clone)
1100  if (!fClones) {
1101  fClones = new TList();
1102  fClones->SetOwner(false);
1103  // So that the clones are automatically removed from the list when
1104  // they are deleted.
1105  gROOT->GetListOfCleanups()->Add(fClones);
1106  }
1107  if (!fClones->FindObject(clone)) {
1108  fClones->Add(clone);
1109  }
1110 }
1111 
1112 ////////////////////////////////////////////////////////////////////////////////
1113 /// Add a TFriendElement to the list of friends.
1114 ///
1115 /// This function:
1116 /// - opens a file if filename is specified
1117 /// - reads a Tree with name treename from the file (current directory)
1118 /// - adds the Tree to the list of friends
1119 /// see other AddFriend functions
1120 ///
1121 /// A TFriendElement TF describes a TTree object TF in a file.
1122 /// When a TFriendElement TF is added to the the list of friends of an
1123 /// existing TTree T, any variable from TF can be referenced in a query
1124 /// to T.
1125 ///
1126 /// A tree keeps a list of friends. In the context of a tree (or a chain),
1127 /// friendship means unrestricted access to the friends data. In this way
1128 /// it is much like adding another branch to the tree without taking the risk
1129 /// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1130 /// method. The tree in the diagram below has two friends (friend_tree1 and
1131 /// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1132 ///
1133 /// \image html ttree_friend1.png
1134 ///
1135 /// The AddFriend method has two parameters, the first is the tree name and the
1136 /// second is the name of the ROOT file where the friend tree is saved.
1137 /// AddFriend automatically opens the friend file. If no file name is given,
1138 /// the tree called ft1 is assumed to be in the same file as the original tree.
1139 ///
1140 /// tree.AddFriend("ft1","friendfile1.root");
1141 /// If the friend tree has the same name as the original tree, you can give it
1142 /// an alias in the context of the friendship:
1143 ///
1144 /// tree.AddFriend("tree1 = tree","friendfile1.root");
1145 /// Once the tree has friends, we can use TTree::Draw as if the friend's
1146 /// variables were in the original tree. To specify which tree to use in
1147 /// the Draw method, use the syntax:
1148 /// ~~~ {.cpp}
1149 /// <treeName>.<branchname>.<varname>
1150 /// ~~~
1151 /// If the variablename is enough to uniquely identify the variable, you can
1152 /// leave out the tree and/or branch name.
1153 /// For example, these commands generate a 3-d scatter plot of variable "var"
1154 /// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1155 /// TTree ft2.
1156 /// ~~~ {.cpp}
1157 /// tree.AddFriend("ft1","friendfile1.root");
1158 /// tree.AddFriend("ft2","friendfile2.root");
1159 /// tree.Draw("var:ft1.v1:ft2.v2");
1160 /// ~~~
1161 /// \image html ttree_friend2.png
1162 ///
1163 /// The picture illustrates the access of the tree and its friends with a
1164 /// Draw command.
1165 /// When AddFriend is called, the ROOT file is automatically opened and the
1166 /// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1167 /// the list of friends of tree.
1168 /// The number of entries in the friend must be equal or greater to the number
1169 /// of entries of the original tree. If the friend tree has fewer entries a
1170 /// warning is given and the missing entries are not included in the histogram.
1171 /// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1172 /// When the tree is written to file (TTree::Write), the friends list is saved
1173 /// with it. And when the tree is retrieved, the trees on the friends list are
1174 /// also retrieved and the friendship restored.
1175 /// When a tree is deleted, the elements of the friend list are also deleted.
1176 /// It is possible to declare a friend tree that has the same internal
1177 /// structure (same branches and leaves) as the original tree, and compare the
1178 /// same values by specifying the tree.
1179 /// ~~~ {.cpp}
1180 /// tree.Draw("var:ft1.var:ft2.var")
1181 /// ~~~
1182 
1183 TFriendElement* TTree::AddFriend(const char* treename, const char* filename)
1185  if (!fFriends) {
1186  fFriends = new TList();
1187  }
1188  TFriendElement* fe = new TFriendElement(this, treename, filename);
1189 
1190  fFriends->Add(fe);
1191  TTree* t = fe->GetTree();
1192  if (t) {
1193  if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1194  Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename, filename, t->GetEntries(), fEntries);
1195  }
1196  } else {
1197  Warning("AddFriend", "Cannot add FriendElement %s in file %s", treename, filename);
1198  }
1199  return fe;
1200 }
1201 
1202 ////////////////////////////////////////////////////////////////////////////////
1203 /// Add a TFriendElement to the list of friends.
1204 ///
1205 /// The TFile is managed by the user (e.g. the user must delete the file).
1206 /// For complete description see AddFriend(const char *, const char *).
1207 /// This function:
1208 /// - reads a Tree with name treename from the file
1209 /// - adds the Tree to the list of friends
1210 
1211 TFriendElement* TTree::AddFriend(const char* treename, TFile* file)
1213  if (!fFriends) {
1214  fFriends = new TList();
1215  }
1216  TFriendElement *fe = new TFriendElement(this, treename, file);
1217  R__ASSERT(fe);
1218  fFriends->Add(fe);
1219  TTree *t = fe->GetTree();
1220  if (t) {
1221  if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1222  Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent tree: %lld", treename, file->GetName(), t->GetEntries(), fEntries);
1223  }
1224  } else {
1225  Warning("AddFriend", "unknown tree '%s' in file '%s'", treename, file->GetName());
1226  }
1227  return fe;
1228 }
1229 
1230 ////////////////////////////////////////////////////////////////////////////////
1231 /// Add a TFriendElement to the list of friends.
1232 ///
1233 /// The TTree is managed by the user (e.g., the user must delete the file).
1234 /// For a complete description see AddFriend(const char *, const char *).
1235 
1236 TFriendElement* TTree::AddFriend(TTree* tree, const char* alias, Bool_t warn)
1238  if (!tree) {
1239  return 0;
1240  }
1241  if (!fFriends) {
1242  fFriends = new TList();
1243  }
1244  TFriendElement* fe = new TFriendElement(this, tree, alias);
1245  R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1246  fFriends->Add(fe);
1247  TTree* t = fe->GetTree();
1248  if (warn && (t->GetEntries() < fEntries)) {
1249  Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1250  tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(), fEntries);
1251  }
1252  return fe;
1253 }
1254 
1255 ////////////////////////////////////////////////////////////////////////////////
1256 /// AutoSave tree header every fAutoSave bytes.
1257 ///
1258 /// When large Trees are produced, it is safe to activate the AutoSave
1259 /// procedure. Some branches may have buffers holding many entries.
1260 /// If fAutoSave is negative, AutoSave is automatically called by
1261 /// TTree::Fill when the number of bytes generated since the previous
1262 /// AutoSave is greater than -fAutoSave bytes.
1263 /// If fAutoSave is positive, AutoSave is automatically called by
1264 /// TTree::Fill every N entries.
1265 /// This function may also be invoked by the user.
1266 /// Each AutoSave generates a new key on the file.
1267 /// Once the key with the tree header has been written, the previous cycle
1268 /// (if any) is deleted.
1269 ///
1270 /// Note that calling TTree::AutoSave too frequently (or similarly calling
1271 /// TTree::SetAutoSave with a small value) is an expensive operation.
1272 /// You should make tests for your own application to find a compromise
1273 /// between speed and the quantity of information you may loose in case of
1274 /// a job crash.
1275 ///
1276 /// In case your program crashes before closing the file holding this tree,
1277 /// the file will be automatically recovered when you will connect the file
1278 /// in UPDATE mode.
1279 /// The Tree will be recovered at the status corresponding to the last AutoSave.
1280 ///
1281 /// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1282 /// This allows another process to analyze the Tree while the Tree is being filled.
1283 ///
1284 /// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1285 /// the current basket are closed-out and written to disk individually.
1286 ///
1287 /// By default the previous header is deleted after having written the new header.
1288 /// if option contains "Overwrite", the previous Tree header is deleted
1289 /// before written the new header. This option is slightly faster, but
1290 /// the default option is safer in case of a problem (disk quota exceeded)
1291 /// when writing the new header.
1292 ///
1293 /// The function returns the number of bytes written to the file.
1294 /// if the number of bytes is null, an error has occurred while writing
1295 /// the header to the file.
1296 ///
1297 /// ## How to write a Tree in one process and view it from another process
1298 ///
1299 /// The following two scripts illustrate how to do this.
1300 /// The script treew.C is executed by process1, treer.C by process2
1301 ///
1302 /// script treew.C:
1303 /// ~~~ {.cpp}
1304 /// void treew() {
1305 /// TFile f("test.root","recreate");
1306 /// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1307 /// Float_t px, py, pz;
1308 /// for ( Int_t i=0; i<10000000; i++) {
1309 /// gRandom->Rannor(px,py);
1310 /// pz = px*px + py*py;
1311 /// Float_t random = gRandom->Rndm(1);
1312 /// ntuple->Fill(px,py,pz,random,i);
1313 /// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1314 /// }
1315 /// }
1316 /// ~~~
1317 /// script treer.C:
1318 /// ~~~ {.cpp}
1319 /// void treer() {
1320 /// TFile f("test.root");
1321 /// TTree *ntuple = (TTree*)f.Get("ntuple");
1322 /// TCanvas c1;
1323 /// Int_t first = 0;
1324 /// while(1) {
1325 /// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1326 /// else ntuple->Draw("px>>+hpx","","",10000000,first);
1327 /// first = (Int_t)ntuple->GetEntries();
1328 /// c1.Update();
1329 /// gSystem->Sleep(1000); //sleep 1 second
1330 /// ntuple->Refresh();
1331 /// }
1332 /// }
1333 /// ~~~
1334 
1337  if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1338  if (gDebug > 0) {
1339  printf("AutoSave Tree:%s after %lld bytes written\n",GetName(),fTotBytes);
1340  }
1341  TString opt = option;
1342  opt.ToLower();
1343 
1344  if (opt.Contains("flushbaskets")) {
1345  if (gDebug > 0) printf("AutoSave: calling FlushBaskets \n");
1346  FlushBaskets();
1347  }
1348 
1350 
1352  Long64_t nbytes;
1353  if (opt.Contains("overwrite")) {
1354  nbytes = fDirectory->WriteTObject(this,"","overwrite");
1355  } else {
1356  nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1357  if (nbytes && key) {
1358  key->Delete();
1359  delete key;
1360  }
1361  }
1362  // save StreamerInfo
1363  TFile *file = fDirectory->GetFile();
1364  if (file) file->WriteStreamerInfo();
1365 
1366  if (opt.Contains("saveself")) {
1367  fDirectory->SaveSelf();
1368  //the following line is required in case GetUserInfo contains a user class
1369  //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1370  if (file) file->WriteHeader();
1371  }
1372 
1373  return nbytes;
1374 }
1375 
1376 namespace {
1377  // This error message is repeated several times in the code. We write it once.
1378  const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1379  " is an instance of an stl collection and does not have a compiled CollectionProxy."
1380  " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1381 }
1382 
1383 ////////////////////////////////////////////////////////////////////////////////
1384 /// Same as TTree::Branch() with added check that addobj matches className.
1385 ///
1386 /// See TTree::Branch() for other details.
1387 ///
1388 
1389 TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1391  TClass* claim = TClass::GetClass(classname);
1392  if (!ptrClass) {
1393  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1394  Error("Branch", writeStlWithoutProxyMsg,
1395  claim->GetName(), branchname, claim->GetName());
1396  return 0;
1397  }
1398  return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1399  }
1400  TClass* actualClass = 0;
1401  void** addr = (void**) addobj;
1402  if (addr) {
1403  actualClass = ptrClass->GetActualClass(*addr);
1404  }
1405  if (ptrClass && claim) {
1406  if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1407  // Note we currently do not warn in case of splicing or over-expectation).
1408  if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1409  // The type is the same according to the C++ type_info, we must be in the case of
1410  // a template of Double32_t. This is actually a correct case.
1411  } else {
1412  Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1413  claim->GetName(), branchname, ptrClass->GetName());
1414  }
1415  } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1416  if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1417  // The type is the same according to the C++ type_info, we must be in the case of
1418  // a template of Double32_t. This is actually a correct case.
1419  } else {
1420  Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1421  actualClass->GetName(), branchname, claim->GetName());
1422  }
1423  }
1424  }
1425  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1426  Error("Branch", writeStlWithoutProxyMsg,
1427  claim->GetName(), branchname, claim->GetName());
1428  return 0;
1429  }
1430  return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1431 }
1432 
1433 ////////////////////////////////////////////////////////////////////////////////
1434 /// Same as TTree::Branch but automatic detection of the class name.
1435 /// See TTree::Branch for other details.
1436 
1437 TBranch* TTree::BranchImp(const char* branchname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1439  if (!ptrClass) {
1440  Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1441  return 0;
1442  }
1443  TClass* actualClass = 0;
1444  void** addr = (void**) addobj;
1445  if (addr && *addr) {
1446  actualClass = ptrClass->GetActualClass(*addr);
1447  if (!actualClass) {
1448  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",
1449  branchname, ptrClass->GetName());
1450  actualClass = ptrClass;
1451  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1452  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());
1453  return 0;
1454  }
1455  } else {
1456  actualClass = ptrClass;
1457  }
1458  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1459  Error("Branch", writeStlWithoutProxyMsg,
1460  actualClass->GetName(), branchname, actualClass->GetName());
1461  return 0;
1462  }
1463  return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1464 }
1465 
1466 ////////////////////////////////////////////////////////////////////////////////
1467 /// Same as TTree::Branch but automatic detection of the class name.
1468 /// See TTree::Branch for other details.
1469 
1470 TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1472  TClass* claim = TClass::GetClass(classname);
1473  if (!ptrClass) {
1474  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1475  Error("Branch", writeStlWithoutProxyMsg,
1476  claim->GetName(), branchname, claim->GetName());
1477  return 0;
1478  } else if (claim == 0) {
1479  Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1480  return 0;
1481  }
1482  ptrClass = claim;
1483  }
1484  TClass* actualClass = 0;
1485  if (!addobj) {
1486  Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1487  return 0;
1488  }
1489  actualClass = ptrClass->GetActualClass(addobj);
1490  if (ptrClass && claim) {
1491  if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1492  // Note we currently do not warn in case of splicing or over-expectation).
1493  if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1494  // The type is the same according to the C++ type_info, we must be in the case of
1495  // a template of Double32_t. This is actually a correct case.
1496  } else {
1497  Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1498  claim->GetName(), branchname, ptrClass->GetName());
1499  }
1500  } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1501  if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1502  // The type is the same according to the C++ type_info, we must be in the case of
1503  // a template of Double32_t. This is actually a correct case.
1504  } else {
1505  Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1506  actualClass->GetName(), branchname, claim->GetName());
1507  }
1508  }
1509  }
1510  if (!actualClass) {
1511  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",
1512  branchname, ptrClass->GetName());
1513  actualClass = ptrClass;
1514  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1515  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());
1516  return 0;
1517  }
1518  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1519  Error("Branch", writeStlWithoutProxyMsg,
1520  actualClass->GetName(), branchname, actualClass->GetName());
1521  return 0;
1522  }
1523  return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1524 }
1525 
1526 ////////////////////////////////////////////////////////////////////////////////
1527 /// Same as TTree::Branch but automatic detection of the class name.
1528 /// See TTree::Branch for other details.
1529 
1530 TBranch* TTree::BranchImpRef(const char* branchname, TClass* ptrClass, EDataType datatype, void* addobj, Int_t bufsize, Int_t splitlevel)
1532  if (!ptrClass) {
1533  if (datatype == kOther_t || datatype == kNoType_t) {
1534  Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1535  } else {
1536  TString varname; varname.Form("%s/%c",branchname,DataTypeToChar(datatype));
1537  return Branch(branchname,addobj,varname.Data(),bufsize);
1538  }
1539  return 0;
1540  }
1541  TClass* actualClass = 0;
1542  if (!addobj) {
1543  Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1544  return 0;
1545  }
1546  actualClass = ptrClass->GetActualClass(addobj);
1547  if (!actualClass) {
1548  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",
1549  branchname, ptrClass->GetName());
1550  actualClass = ptrClass;
1551  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1552  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());
1553  return 0;
1554  }
1555  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1556  Error("Branch", writeStlWithoutProxyMsg,
1557  actualClass->GetName(), branchname, actualClass->GetName());
1558  return 0;
1559  }
1560  return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1561 }
1562 
1563 ////////////////////////////////////////////////////////////////////////////////
1564 /// Deprecated function. Use next function instead.
1565 
1566 Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1568  return Branch((TCollection*) li, bufsize, splitlevel);
1569 }
1570 
1571 ////////////////////////////////////////////////////////////////////////////////
1572 /// Create one branch for each element in the collection.
1573 ///
1574 /// Each entry in the collection becomes a top level branch if the
1575 /// corresponding class is not a collection. If it is a collection, the entry
1576 /// in the collection becomes in turn top level branches, etc.
1577 /// The splitlevel is decreased by 1 every time a new collection is found.
1578 /// For example if list is a TObjArray*
1579 /// - if splitlevel = 1, one top level branch is created for each element
1580 /// of the TObjArray.
1581 /// - if splitlevel = 2, one top level branch is created for each array element.
1582 /// if, in turn, one of the array elements is a TCollection, one top level
1583 /// branch will be created for each element of this collection.
1584 ///
1585 /// In case a collection element is a TClonesArray, the special Tree constructor
1586 /// for TClonesArray is called.
1587 /// The collection itself cannot be a TClonesArray.
1588 ///
1589 /// The function returns the total number of branches created.
1590 ///
1591 /// If name is given, all branch names will be prefixed with name_.
1592 ///
1593 /// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1594 ///
1595 /// IMPORTANT NOTE2: The branches created by this function will have names
1596 /// corresponding to the collection or object names. It is important
1597 /// to give names to collections to avoid misleading branch names or
1598 /// identical branch names. By default collections have a name equal to
1599 /// the corresponding class name, e.g. the default name for a TList is "TList".
1600 ///
1601 /// And in general in any cases two or more master branches contain subbranches
1602 /// with identical names, one must add a "." (dot) character at the end
1603 /// of the master branch name. This will force the name of the subbranch
1604 /// to be master.subbranch instead of simply subbranch.
1605 /// This situation happens when the top level object (say event)
1606 /// has two or more members referencing the same class.
1607 /// For example, if a Tree has two branches B1 and B2 corresponding
1608 /// to objects of the same class MyClass, one can do:
1609 /// ~~~ {.cpp}
1610 /// tree.Branch("B1.","MyClass",&b1,8000,1);
1611 /// tree.Branch("B2.","MyClass",&b2,8000,1);
1612 /// ~~~
1613 /// if MyClass has 3 members a,b,c, the two instructions above will generate
1614 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1615 ///
1616 /// Example:
1617 /// ~~~ {.cpp}
1618 /// {
1619 /// TTree T("T","test list");
1620 /// TList *list = new TList();
1621 ///
1622 /// TObjArray *a1 = new TObjArray();
1623 /// a1->SetName("a1");
1624 /// list->Add(a1);
1625 /// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1626 /// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1627 /// a1->Add(ha1a);
1628 /// a1->Add(ha1b);
1629 /// TObjArray *b1 = new TObjArray();
1630 /// b1->SetName("b1");
1631 /// list->Add(b1);
1632 /// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1633 /// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1634 /// b1->Add(hb1a);
1635 /// b1->Add(hb1b);
1636 ///
1637 /// TObjArray *a2 = new TObjArray();
1638 /// a2->SetName("a2");
1639 /// list->Add(a2);
1640 /// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1641 /// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1642 /// a2->Add(ha2a);
1643 /// a2->Add(ha2b);
1644 ///
1645 /// T.Branch(list,16000,2);
1646 /// T.Print();
1647 /// }
1648 /// ~~~
1649 
1650 Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1652 
1653  if (!li) {
1654  return 0;
1655  }
1656  TObject* obj = 0;
1657  Int_t nbranches = GetListOfBranches()->GetEntries();
1658  if (li->InheritsFrom(TClonesArray::Class())) {
1659  Error("Branch", "Cannot call this constructor for a TClonesArray");
1660  return 0;
1661  }
1662  Int_t nch = strlen(name);
1663  TString branchname;
1664  TIter next(li);
1665  while ((obj = next())) {
1666  if ((splitlevel > 1) && obj->InheritsFrom(TCollection::Class()) && !obj->InheritsFrom(TClonesArray::Class())) {
1667  TCollection* col = (TCollection*) obj;
1668  if (nch) {
1669  branchname.Form("%s_%s_", name, col->GetName());
1670  } else {
1671  branchname.Form("%s_", col->GetName());
1672  }
1673  Branch(col, bufsize, splitlevel - 1, branchname);
1674  } else {
1675  if (nch && (name[nch-1] == '_')) {
1676  branchname.Form("%s%s", name, obj->GetName());
1677  } else {
1678  if (nch) {
1679  branchname.Form("%s_%s", name, obj->GetName());
1680  } else {
1681  branchname.Form("%s", obj->GetName());
1682  }
1683  }
1684  if (splitlevel > 99) {
1685  branchname += ".";
1686  }
1687  Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1688  }
1689  }
1690  return GetListOfBranches()->GetEntries() - nbranches;
1691 }
1692 
1693 ////////////////////////////////////////////////////////////////////////////////
1694 /// Create one branch for each element in the folder.
1695 /// Returns the total number of branches created.
1696 
1697 Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1699  TObject* ob = gROOT->FindObjectAny(foldername);
1700  if (!ob) {
1701  return 0;
1702  }
1703  if (ob->IsA() != TFolder::Class()) {
1704  return 0;
1705  }
1706  Int_t nbranches = GetListOfBranches()->GetEntries();
1707  TFolder* folder = (TFolder*) ob;
1708  TIter next(folder->GetListOfFolders());
1709  TObject* obj = 0;
1710  char* curname = new char[1000];
1711  char occur[20];
1712  while ((obj = next())) {
1713  snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1714  if (obj->IsA() == TFolder::Class()) {
1715  Branch(curname, bufsize, splitlevel - 1);
1716  } else {
1717  void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1718  for (Int_t i = 0; i < 1000; ++i) {
1719  if (curname[i] == 0) {
1720  break;
1721  }
1722  if (curname[i] == '/') {
1723  curname[i] = '.';
1724  }
1725  }
1726  Int_t noccur = folder->Occurence(obj);
1727  if (noccur > 0) {
1728  snprintf(occur,20, "_%d", noccur);
1729  strlcat(curname, occur,1000);
1730  }
1731  TBranchElement* br = (TBranchElement*) Bronch(curname, obj->ClassName(), add, bufsize, splitlevel - 1);
1732  if (br) br->SetBranchFolder();
1733  }
1734  }
1735  delete[] curname;
1736  return GetListOfBranches()->GetEntries() - nbranches;
1737 }
1738 
1739 ////////////////////////////////////////////////////////////////////////////////
1740 /// Create a new TTree Branch.
1741 ///
1742 /// This Branch constructor is provided to support non-objects in
1743 /// a Tree. The variables described in leaflist may be simple
1744 /// variables or structures. // See the two following
1745 /// constructors for writing objects in a Tree.
1746 ///
1747 /// By default the branch buffers are stored in the same file as the Tree.
1748 /// use TBranch::SetFile to specify a different file
1749 ///
1750 /// * address is the address of the first item of a structure.
1751 /// * leaflist is the concatenation of all the variable names and types
1752 /// separated by a colon character :
1753 /// The variable name and the variable type are separated by a slash (/).
1754 /// The variable type may be 0,1 or 2 characters. If no type is given,
1755 /// the type of the variable is assumed to be the same as the previous
1756 /// variable. If the first variable does not have a type, it is assumed
1757 /// of type F by default. The list of currently supported types is given below:
1758 /// - `C` : a character string terminated by the 0 character
1759 /// - `B` : an 8 bit signed integer (`Char_t`)
1760 /// - `b` : an 8 bit unsigned integer (`UChar_t`)
1761 /// - `S` : a 16 bit signed integer (`Short_t`)
1762 /// - `s` : a 16 bit unsigned integer (`UShort_t`)
1763 /// - `I` : a 32 bit signed integer (`Int_t`)
1764 /// - `i` : a 32 bit unsigned integer (`UInt_t`)
1765 /// - `F` : a 32 bit floating point (`Float_t`)
1766 /// - `D` : a 64 bit floating point (`Double_t`)
1767 /// - `L` : a 64 bit signed integer (`Long64_t`)
1768 /// - `l` : a 64 bit unsigned integer (`ULong64_t`)
1769 /// - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
1770 ///
1771 /// Arrays of values are supported with the following syntax:
1772 /// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1773 /// if nelem is a leaf name, it is used as the variable size of the array,
1774 /// otherwise return 0.
1775 /// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1776 /// it is used as the fixed size of the array.
1777 /// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1778 /// where nelem and nelem2 are non-negative integer) then
1779 /// it is used as a 2 dimensional array of fixed size.
1780 ///
1781 /// Any of other form is not supported.
1782 ///
1783 /// Note that the TTree will assume that all the item are contiguous in memory.
1784 /// On some platform, this is not always true of the member of a struct or a class,
1785 /// due to padding and alignment. Sorting your data member in order of decreasing
1786 /// sizeof usually leads to their being contiguous in memory.
1787 ///
1788 /// * bufsize is the buffer size in bytes for this branch
1789 /// The default value is 32000 bytes and should be ok for most cases.
1790 /// You can specify a larger value (e.g. 256000) if your Tree is not split
1791 /// and each entry is large (Megabytes)
1792 /// A small value for bufsize is optimum if you intend to access
1793 /// the entries in the Tree randomly and your Tree is in split mode.
1794 
1795 TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1797  TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1798  if (branch->IsZombie()) {
1799  delete branch;
1800  branch = 0;
1801  return 0;
1802  }
1803  fBranches.Add(branch);
1804  return branch;
1805 }
1806 
1807 ////////////////////////////////////////////////////////////////////////////////
1808 /// Create a new branch with the object of class classname at address addobj.
1809 ///
1810 /// WARNING:
1811 ///
1812 /// Starting with Root version 3.01, the Branch function uses the new style
1813 /// branches (TBranchElement). To get the old behaviour, you can:
1814 /// - call BranchOld or
1815 /// - call TTree::SetBranchStyle(0)
1816 ///
1817 /// Note that with the new style, classname does not need to derive from TObject.
1818 /// It must derived from TObject if the branch style has been set to 0 (old)
1819 ///
1820 /// Note: See the comments in TBranchElement::SetAddress() for a more
1821 /// detailed discussion of the meaning of the addobj parameter in
1822 /// the case of new-style branches.
1823 ///
1824 /// Use splitlevel < 0 instead of splitlevel=0 when the class
1825 /// has a custom Streamer
1826 ///
1827 /// Note: if the split level is set to the default (99), TTree::Branch will
1828 /// not issue a warning if the class can not be split.
1829 
1830 TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1832  if (fgBranchStyle == 1) {
1833  return Bronch(name, classname, addobj, bufsize, splitlevel);
1834  } else {
1835  if (splitlevel < 0) {
1836  splitlevel = 0;
1837  }
1838  return BranchOld(name, classname, addobj, bufsize, splitlevel);
1839  }
1840 }
1841 
1842 ////////////////////////////////////////////////////////////////////////////////
1843 /// Create a new TTree BranchObject.
1844 ///
1845 /// Build a TBranchObject for an object of class classname.
1846 /// addobj is the address of a pointer to an object of class classname.
1847 /// IMPORTANT: classname must derive from TObject.
1848 /// The class dictionary must be available (ClassDef in class header).
1849 ///
1850 /// This option requires access to the library where the corresponding class
1851 /// is defined. Accessing one single data member in the object implies
1852 /// reading the full object.
1853 /// See the next Branch constructor for a more efficient storage
1854 /// in case the entry consists of arrays of identical objects.
1855 ///
1856 /// By default the branch buffers are stored in the same file as the Tree.
1857 /// use TBranch::SetFile to specify a different file
1858 ///
1859 /// IMPORTANT NOTE about branch names:
1860 ///
1861 /// In case two or more master branches contain subbranches with
1862 /// identical names, one must add a "." (dot) character at the end
1863 /// of the master branch name. This will force the name of the subbranch
1864 /// to be master.subbranch instead of simply subbranch.
1865 /// This situation happens when the top level object (say event)
1866 /// has two or more members referencing the same class.
1867 /// For example, if a Tree has two branches B1 and B2 corresponding
1868 /// to objects of the same class MyClass, one can do:
1869 /// ~~~ {.cpp}
1870 /// tree.Branch("B1.","MyClass",&b1,8000,1);
1871 /// tree.Branch("B2.","MyClass",&b2,8000,1);
1872 /// ~~~
1873 /// if MyClass has 3 members a,b,c, the two instructions above will generate
1874 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1875 ///
1876 /// bufsize is the buffer size in bytes for this branch
1877 /// The default value is 32000 bytes and should be ok for most cases.
1878 /// You can specify a larger value (e.g. 256000) if your Tree is not split
1879 /// and each entry is large (Megabytes)
1880 /// A small value for bufsize is optimum if you intend to access
1881 /// the entries in the Tree randomly and your Tree is in split mode.
1882 
1883 TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
1885  TClass* cl = TClass::GetClass(classname);
1886  if (!cl) {
1887  Error("BranchOld", "Cannot find class: '%s'", classname);
1888  return 0;
1889  }
1890  if (!cl->IsTObject()) {
1891  if (fgBranchStyle == 0) {
1892  Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1893  "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
1894  "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
1895  } else {
1896  Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1897  "\tYou can not use BranchOld to store objects of this type.",classname);
1898  }
1899  return 0;
1900  }
1901  TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
1902  fBranches.Add(branch);
1903  if (!splitlevel) {
1904  return branch;
1905  }
1906  // We are going to fully split the class now.
1907  TObjArray* blist = branch->GetListOfBranches();
1908  const char* rdname = 0;
1909  const char* dname = 0;
1910  TString branchname;
1911  char** apointer = (char**) addobj;
1912  TObject* obj = (TObject*) *apointer;
1913  Bool_t delobj = kFALSE;
1914  if (!obj) {
1915  obj = (TObject*) cl->New();
1916  delobj = kTRUE;
1917  }
1918  // Build the StreamerInfo if first time for the class.
1919  BuildStreamerInfo(cl, obj);
1920  // Loop on all public data members of the class and its base classes.
1921  Int_t lenName = strlen(name);
1922  Int_t isDot = 0;
1923  if (name[lenName-1] == '.') {
1924  isDot = 1;
1925  }
1926  TBranch* branch1 = 0;
1927  TRealData* rd = 0;
1928  TRealData* rdi = 0;
1929  TIter nexti(cl->GetListOfRealData());
1930  TIter next(cl->GetListOfRealData());
1931  // Note: This loop results in a full split because the
1932  // real data list includes all data members of
1933  // data members.
1934  while ((rd = (TRealData*) next())) {
1935  if (rd->TestBit(TRealData::kTransient)) continue;
1936 
1937  // Loop over all data members creating branches for each one.
1938  TDataMember* dm = rd->GetDataMember();
1939  if (!dm->IsPersistent()) {
1940  // Do not process members with an "!" as the first character in the comment field.
1941  continue;
1942  }
1943  if (rd->IsObject()) {
1944  // We skip data members of class type.
1945  // But we do build their real data, their
1946  // streamer info, and write their streamer
1947  // info to the current directory's file.
1948  // Oh yes, and we also do this for all of
1949  // their base classes.
1950  TClass* clm = TClass::GetClass(dm->GetFullTypeName());
1951  if (clm) {
1952  BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
1953  }
1954  continue;
1955  }
1956  rdname = rd->GetName();
1957  dname = dm->GetName();
1958  if (cl->CanIgnoreTObjectStreamer()) {
1959  // Skip the TObject base class data members.
1960  // FIXME: This prevents a user from ever
1961  // using these names themself!
1962  if (!strcmp(dname, "fBits")) {
1963  continue;
1964  }
1965  if (!strcmp(dname, "fUniqueID")) {
1966  continue;
1967  }
1968  }
1969  TDataType* dtype = dm->GetDataType();
1970  Int_t code = 0;
1971  if (dtype) {
1972  code = dm->GetDataType()->GetType();
1973  }
1974  // Encode branch name. Use real data member name
1975  branchname = rdname;
1976  if (isDot) {
1977  if (dm->IsaPointer()) {
1978  // FIXME: This is wrong! The asterisk is not usually in the front!
1979  branchname.Form("%s%s", name, &rdname[1]);
1980  } else {
1981  branchname.Form("%s%s", name, &rdname[0]);
1982  }
1983  }
1984  // FIXME: Change this to a string stream.
1985  TString leaflist;
1986  Int_t offset = rd->GetThisOffset();
1987  char* pointer = ((char*) obj) + offset;
1988  if (dm->IsaPointer()) {
1989  // We have a pointer to an object or a pointer to an array of basic types.
1990  TClass* clobj = 0;
1991  if (!dm->IsBasic()) {
1992  clobj = TClass::GetClass(dm->GetTypeName());
1993  }
1994  if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
1995  // We have a pointer to a clones array.
1996  char* cpointer = (char*) pointer;
1997  char** ppointer = (char**) cpointer;
1998  TClonesArray* li = (TClonesArray*) *ppointer;
1999  if (splitlevel != 2) {
2000  if (isDot) {
2001  branch1 = new TBranchClones(branch,branchname, pointer, bufsize);
2002  } else {
2003  // FIXME: This is wrong! The asterisk is not usually in the front!
2004  branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
2005  }
2006  blist->Add(branch1);
2007  } else {
2008  if (isDot) {
2009  branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
2010  } else {
2011  // FIXME: This is wrong! The asterisk is not usually in the front!
2012  branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
2013  }
2014  blist->Add(branch1);
2015  }
2016  } else if (clobj) {
2017  // We have a pointer to an object.
2018  //
2019  // It must be a TObject object.
2020  if (!clobj->IsTObject()) {
2021  continue;
2022  }
2023  branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
2024  if (isDot) {
2025  branch1->SetName(branchname);
2026  } else {
2027  // FIXME: This is wrong! The asterisk is not usually in the front!
2028  // Do not use the first character (*).
2029  branch1->SetName(&branchname.Data()[1]);
2030  }
2031  blist->Add(branch1);
2032  } else {
2033  // We have a pointer to an array of basic types.
2034  //
2035  // Check the comments in the text of the code for an index specification.
2036  const char* index = dm->GetArrayIndex();
2037  if (index[0]) {
2038  // We are a pointer to a varying length array of basic types.
2039  //check that index is a valid data member name
2040  //if member is part of an object (e.g. fA and index=fN)
2041  //index must be changed from fN to fA.fN
2042  TString aindex (rd->GetName());
2043  Ssiz_t rdot = aindex.Last('.');
2044  if (rdot>=0) {
2045  aindex.Remove(rdot+1);
2046  aindex.Append(index);
2047  }
2048  nexti.Reset();
2049  while ((rdi = (TRealData*) nexti())) {
2050  if (rdi->TestBit(TRealData::kTransient)) continue;
2051 
2052  if (!strcmp(rdi->GetName(), index)) {
2053  break;
2054  }
2055  if (!strcmp(rdi->GetName(), aindex)) {
2056  index = rdi->GetName();
2057  break;
2058  }
2059  }
2060 
2061  char vcode = DataTypeToChar((EDataType)code);
2062  // Note that we differentiate between strings and
2063  // char array by the fact that there is NO specified
2064  // size for a string (see next if (code == 1)
2065 
2066  if (vcode) {
2067  leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2068  } else {
2069  Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2070  leaflist = "";
2071  }
2072  } else {
2073  // We are possibly a character string.
2074  if (code == 1) {
2075  // We are a character string.
2076  leaflist.Form("%s/%s", dname, "C");
2077  } else {
2078  // Invalid array specification.
2079  // FIXME: We need an error message here.
2080  continue;
2081  }
2082  }
2083  // There are '*' in both the branchname and leaflist, remove them.
2084  TString bname( branchname );
2085  bname.ReplaceAll("*","");
2086  leaflist.ReplaceAll("*","");
2087  // Add the branch to the tree and indicate that the address
2088  // is that of a pointer to be dereferenced before using.
2089  branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2090  TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2092  leaf->SetAddress((void**) pointer);
2093  blist->Add(branch1);
2094  }
2095  } else if (dm->IsBasic()) {
2096  // We have a basic type.
2097 
2098  char vcode = DataTypeToChar((EDataType)code);
2099  if (vcode) {
2100  leaflist.Form("%s/%c", rdname, vcode);
2101  } else {
2102  Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2103  leaflist = "";
2104  }
2105  branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2106  branch1->SetTitle(rdname);
2107  blist->Add(branch1);
2108  } else {
2109  // We have a class type.
2110  // Note: This cannot happen due to the rd->IsObject() test above.
2111  // FIXME: Put an error message here just in case.
2112  }
2113  if (branch1) {
2114  branch1->SetOffset(offset);
2115  } else {
2116  Warning("BranchOld", "Cannot process member: '%s'", rdname);
2117  }
2118  }
2119  if (delobj) {
2120  delete obj;
2121  obj = 0;
2122  }
2123  return branch;
2124 }
2125 
2126 ////////////////////////////////////////////////////////////////////////////////
2127 /// Build the optional branch supporting the TRefTable.
2128 /// This branch will keep all the information to find the branches
2129 /// containing referenced objects.
2130 ///
2131 /// At each Tree::Fill, the branch numbers containing the
2132 /// referenced objects are saved to the TBranchRef basket.
2133 /// When the Tree header is saved (via TTree::Write), the branch
2134 /// is saved keeping the information with the pointers to the branches
2135 /// having referenced objects.
2136 
2139  if (!fBranchRef) {
2140  fBranchRef = new TBranchRef(this);
2141  }
2142  return fBranchRef;
2143 }
2144 
2145 ////////////////////////////////////////////////////////////////////////////////
2146 /// Create a new TTree BranchElement.
2147 ///
2148 /// ## WARNING about this new function
2149 ///
2150 /// This function is designed to replace the internal
2151 /// implementation of the old TTree::Branch (whose implementation
2152 /// has been moved to BranchOld).
2153 ///
2154 /// NOTE: The 'Bronch' method supports only one possible calls
2155 /// signature (where the object type has to be specified
2156 /// explicitly and the address must be the address of a pointer).
2157 /// For more flexibility use 'Branch'. Use Bronch only in (rare)
2158 /// cases (likely to be legacy cases) where both the new and old
2159 /// implementation of Branch needs to be used at the same time.
2160 ///
2161 /// This function is far more powerful than the old Branch
2162 /// function. It supports the full C++, including STL and has
2163 /// the same behaviour in split or non-split mode. classname does
2164 /// not have to derive from TObject. The function is based on
2165 /// the new TStreamerInfo.
2166 ///
2167 /// Build a TBranchElement for an object of class classname.
2168 ///
2169 /// addr is the address of a pointer to an object of class
2170 /// classname. The class dictionary must be available (ClassDef
2171 /// in class header).
2172 ///
2173 /// Note: See the comments in TBranchElement::SetAddress() for a more
2174 /// detailed discussion of the meaning of the addr parameter.
2175 ///
2176 /// This option requires access to the library where the
2177 /// corresponding class is defined. Accessing one single data
2178 /// member in the object implies reading the full object.
2179 ///
2180 /// By default the branch buffers are stored in the same file as the Tree.
2181 /// use TBranch::SetFile to specify a different file
2182 ///
2183 /// IMPORTANT NOTE about branch names:
2184 ///
2185 /// In case two or more master branches contain subbranches with
2186 /// identical names, one must add a "." (dot) character at the end
2187 /// of the master branch name. This will force the name of the subbranch
2188 /// to be master.subbranch instead of simply subbranch.
2189 /// This situation happens when the top level object (say event)
2190 /// has two or more members referencing the same class.
2191 /// For example, if a Tree has two branches B1 and B2 corresponding
2192 /// to objects of the same class MyClass, one can do:
2193 /// ~~~ {.cpp}
2194 /// tree.Branch("B1.","MyClass",&b1,8000,1);
2195 /// tree.Branch("B2.","MyClass",&b2,8000,1);
2196 /// ~~~
2197 /// if MyClass has 3 members a,b,c, the two instructions above will generate
2198 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2199 ///
2200 /// bufsize is the buffer size in bytes for this branch
2201 /// The default value is 32000 bytes and should be ok for most cases.
2202 /// You can specify a larger value (e.g. 256000) if your Tree is not split
2203 /// and each entry is large (Megabytes)
2204 /// A small value for bufsize is optimum if you intend to access
2205 /// the entries in the Tree randomly and your Tree is in split mode.
2206 ///
2207 /// Use splitlevel < 0 instead of splitlevel=0 when the class
2208 /// has a custom Streamer
2209 ///
2210 /// Note: if the split level is set to the default (99), TTree::Branch will
2211 /// not issue a warning if the class can not be split.
2212 
2213 TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2215  return BronchExec(name, classname, addr, kTRUE, bufsize, splitlevel);
2216 }
2217 
2218 ////////////////////////////////////////////////////////////////////////////////
2219 /// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2220 
2221 TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, Bool_t isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2223  TClass* cl = TClass::GetClass(classname);
2224  if (!cl) {
2225  Error("Bronch", "Cannot find class:%s", classname);
2226  return 0;
2227  }
2228 
2229  //if splitlevel <= 0 and class has a custom Streamer, we must create
2230  //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2231  //with the custom Streamer. The penalty is that one cannot process
2232  //this Tree without the class library containing the class.
2233 
2234  char* objptr = 0;
2235  if (!isptrptr) {
2236  objptr = (char*)addr;
2237  } else if (addr) {
2238  objptr = *((char**) addr);
2239  }
2240 
2241  if (cl == TClonesArray::Class()) {
2242  TClonesArray* clones = (TClonesArray*) objptr;
2243  if (!clones) {
2244  Error("Bronch", "Pointer to TClonesArray is null");
2245  return 0;
2246  }
2247  if (!clones->GetClass()) {
2248  Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2249  return 0;
2250  }
2251  if (!clones->GetClass()->HasDataMemberInfo()) {
2252  Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2253  return 0;
2254  }
2255  bool hasCustomStreamer = clones->GetClass()->TestBit(TClass::kHasCustomStreamerMember);
2256  if (splitlevel > 0) {
2257  if (hasCustomStreamer)
2258  Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2259  } else {
2260  if (hasCustomStreamer) clones->BypassStreamer(kFALSE);
2261  TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2262  fBranches.Add(branch);
2263  return branch;
2264  }
2265  }
2266 
2267  if (cl->GetCollectionProxy()) {
2268  TVirtualCollectionProxy* collProxy = cl->GetCollectionProxy();
2269  //if (!collProxy) {
2270  // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2271  //}
2272  TClass* inklass = collProxy->GetValueClass();
2273  if (!inklass && (collProxy->GetType() == 0)) {
2274  Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2275  return 0;
2276  }
2277  if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == 0)) {
2278  ROOT::ESTLType stl = cl->GetCollectionType();
2279  if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2280  if (!inklass->HasDataMemberInfo()) {
2281  Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2282  return 0;
2283  }
2284  if (inklass->TestBit(TClass::kHasCustomStreamerMember)) {
2285  Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2286  }
2287  }
2288  }
2289  //-------------------------------------------------------------------------
2290  // If the splitting switch is enabled, the split level is big enough and
2291  // the collection contains pointers we can split it
2292  //////////////////////////////////////////////////////////////////////////
2293 
2294  TBranch *branch;
2295  if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2296  branch = new TBranchSTL( this, name, collProxy, bufsize, splitlevel );
2297  else
2298  branch = new TBranchElement(this, name, collProxy, bufsize, splitlevel);
2299  fBranches.Add(branch);
2300  if (isptrptr) {
2301  branch->SetAddress(addr);
2302  } else {
2303  branch->SetObject(addr);
2304  }
2305  return branch;
2306  }
2307 
2308  Bool_t hasCustomStreamer = kFALSE;
2309  if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2310  Error("Bronch", "Cannot find dictionary for class: %s", classname);
2311  return 0;
2312  }
2313 
2315  // Not an STL container and the linkdef file had a "-" after the class name.
2316  hasCustomStreamer = kTRUE;
2317  }
2318 
2319  if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2320  TBranchObject* branch = new TBranchObject(this, name, classname, addr, bufsize, 0, /*compress=*/ -1, isptrptr);
2321  fBranches.Add(branch);
2322  return branch;
2323  }
2324 
2325  if (cl == TClonesArray::Class()) {
2326  // Special case of TClonesArray.
2327  // No dummy object is created.
2328  // The streamer info is not rebuilt unoptimized.
2329  // No dummy top-level branch is created.
2330  // No splitting is attempted.
2331  TBranchElement* branch = new TBranchElement(this, name, (TClonesArray*) objptr, bufsize, splitlevel%kSplitCollectionOfPointers);
2332  fBranches.Add(branch);
2333  if (isptrptr) {
2334  branch->SetAddress(addr);
2335  } else {
2336  branch->SetObject(addr);
2337  }
2338  return branch;
2339  }
2340 
2341  //
2342  // If we are not given an object to use as an i/o buffer
2343  // then create a temporary one which we will delete just
2344  // before returning.
2345  //
2346 
2347  Bool_t delobj = kFALSE;
2348 
2349  if (!objptr) {
2350  objptr = (char*) cl->New();
2351  delobj = kTRUE;
2352  }
2353 
2354  //
2355  // Avoid splitting unsplittable classes.
2356  //
2357 
2358  if ((splitlevel > 0) && !cl->CanSplit()) {
2359  if (splitlevel != 99) {
2360  Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2361  }
2362  splitlevel = 0;
2363  }
2364 
2365  //
2366  // Make sure the streamer info is built and fetch it.
2367  //
2368  // If we are splitting, then make sure the streamer info
2369  // is built unoptimized (data members are not combined).
2370  //
2371 
2372  TStreamerInfo* sinfo = BuildStreamerInfo(cl, objptr, splitlevel==0);
2373  if (!sinfo) {
2374  Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2375  return 0;
2376  }
2377 
2378  //
2379  // Do we have a final dot in our name?
2380  //
2381 
2382  // Note: The branch constructor which takes a folder as input
2383  // creates top-level branch names with dots in them to
2384  // indicate the folder hierarchy.
2385  char* dot = (char*) strchr(name, '.');
2386  Int_t nch = strlen(name);
2387  Bool_t dotlast = kFALSE;
2388  if (nch && (name[nch-1] == '.')) {
2389  dotlast = kTRUE;
2390  }
2391 
2392  //
2393  // Create a dummy top level branch object.
2394  //
2395 
2396  Int_t id = -1;
2397  if (splitlevel > 0) {
2398  id = -2;
2399  }
2400  TBranchElement* branch = new TBranchElement(this, name, sinfo, id, objptr, bufsize, splitlevel);
2401  fBranches.Add(branch);
2402 
2403  //
2404  // Do splitting, if requested.
2405  //
2406 
2407  if (splitlevel%kSplitCollectionOfPointers > 0) {
2408  // Loop on all public data members of the class and its base classes and create branches for each one.
2409  TObjArray* blist = branch->GetListOfBranches();
2410  TIter next(sinfo->GetElements());
2411  TStreamerElement* element = 0;
2412  TString bname;
2413  for (id = 0; (element = (TStreamerElement*) next()); ++id) {
2414  if (element->IsA() == TStreamerArtificial::Class()) {
2415  continue;
2416  }
2417  if (element->TestBit(TStreamerElement::kRepeat)) {
2418  continue;
2419  }
2420  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
2421  continue;
2422  }
2423  char* pointer = (char*) (objptr + element->GetOffset());
2424  // FIXME: This is not good enough, an STL container can be
2425  // a base, and the test will fail.
2426  // See TBranchElement::InitializeOffsets() for the
2427  // correct test.
2428  Bool_t isBase = (element->IsA() == TStreamerBase::Class());
2429  if (isBase) {
2430  TClass* clbase = element->GetClassPointer();
2431  if ((clbase == TObject::Class()) && cl->CanIgnoreTObjectStreamer()) {
2432  // Note: TStreamerInfo::Compile() leaves this element
2433  // out of the optimized info, although it does
2434  // exists in the non-compiled and non-optimized info.
2435  // FIXME: The test that TStreamerInfo::Compile() uses
2436  // is element->GetType() < 0, so that is what
2437  // we should do as well.
2438  continue;
2439  }
2440  if (clbase->GetListOfRealData()->GetSize() == 0) {
2441  // Do not create a branch for empty bases.
2442  continue;
2443  }
2444  }
2445  if (dot) {
2446  if (dotlast) {
2447  bname.Form("%s%s", name, element->GetFullName());
2448  } else {
2449  // FIXME: We are in the case where we have a top-level
2450  // branch name that was created by the branch
2451  // constructor which takes a folder as input.
2452  // The internal dots in the name are in place of
2453  // of the original slashes and represent the
2454  // folder hierarchy.
2455  if (isBase) {
2456  // FIXME: This is very strange, this is the only case where
2457  // we create a branch for a base class that does
2458  // not have the base class name in the branch name.
2459  // FIXME: This is also quite bad since classes with two
2460  // or more base classes end up with sub-branches
2461  // that have the same name.
2462  bname = name;
2463  } else {
2464  bname.Form("%s.%s", name, element->GetFullName());
2465  }
2466  }
2467  } else {
2468  // Note: For a base class element, this results in the branchname
2469  // being the name of the base class.
2470  bname.Form("%s", element->GetFullName());
2471  }
2472 
2473  if( splitlevel > kSplitCollectionOfPointers && element->GetClass() &&
2474  element->GetClass()->GetCollectionProxy() &&
2475  element->GetClass()->GetCollectionProxy()->HasPointers() )
2476  {
2477  TBranchSTL* brSTL = new TBranchSTL( branch, bname, element->GetClass()->GetCollectionProxy(), bufsize, splitlevel-1, sinfo, id );
2478  blist->Add(brSTL);
2479  }
2480  else
2481  {
2482  TBranchElement* bre = new TBranchElement(branch, bname, sinfo, id, pointer, bufsize, splitlevel - 1);
2483  bre->SetParentClass(cl);
2484  blist->Add(bre);
2485  }
2486  }
2487  }
2488 
2489  //
2490  // Setup our offsets into the user's i/o buffer.
2491  //
2492 
2493  if (isptrptr) {
2494  branch->SetAddress(addr);
2495  } else {
2496  branch->SetObject(addr);
2497  }
2498 
2499  if (delobj) {
2500  cl->Destructor(objptr);
2501  objptr = 0;
2502  }
2503 
2504  return branch;
2505 }
2506 
2507 ////////////////////////////////////////////////////////////////////////////////
2508 /// Browse content of the TTree.
2509 
2510 void TTree::Browse(TBrowser* b)
2512  fBranches.Browse(b);
2513  if (fUserInfo) {
2514  if (strcmp("TList",fUserInfo->GetName())==0) {
2515  fUserInfo->SetName("UserInfo");
2516  b->Add(fUserInfo);
2517  fUserInfo->SetName("TList");
2518  } else {
2519  b->Add(fUserInfo);
2520  }
2521  }
2522 }
2523 
2524 ////////////////////////////////////////////////////////////////////////////////
2525 /// Build a Tree Index (default is TTreeIndex).
2526 /// See a description of the parameters and functionality in
2527 /// TTreeIndex::TTreeIndex().
2528 ///
2529 /// The return value is the number of entries in the Index (< 0 indicates failure).
2530 ///
2531 /// A TTreeIndex object pointed by fTreeIndex is created.
2532 /// This object will be automatically deleted by the TTree destructor.
2533 /// See also comments in TTree::SetTreeIndex().
2534 
2535 Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2537  fTreeIndex = GetPlayer()->BuildIndex(this, majorname, minorname);
2538  if (fTreeIndex->IsZombie()) {
2539  delete fTreeIndex;
2540  fTreeIndex = 0;
2541  return 0;
2542  }
2543  return fTreeIndex->GetN();
2544 }
2545 
2546 ////////////////////////////////////////////////////////////////////////////////
2547 /// Build StreamerInfo for class cl.
2548 /// pointer is an optional argument that may contain a pointer to an object of cl.
2549 
2550 TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, Bool_t canOptimize /* = kTRUE */ )
2552  if (!cl) {
2553  return 0;
2554  }
2555  cl->BuildRealData(pointer);
2557 
2558  // Create StreamerInfo for all base classes.
2559  TBaseClass* base = 0;
2560  TIter nextb(cl->GetListOfBases());
2561  while((base = (TBaseClass*) nextb())) {
2562  if (base->IsSTLContainer()) {
2563  continue;
2564  }
2565  TClass* clm = TClass::GetClass(base->GetName());
2566  BuildStreamerInfo(clm, pointer, canOptimize);
2567  }
2568  if (sinfo && fDirectory) {
2569  sinfo->ForceWriteInfo(fDirectory->GetFile());
2570  }
2571  return sinfo;
2572 }
2573 
2574 ////////////////////////////////////////////////////////////////////////////////
2575 /// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2576 /// Create a new file. If the original file is named "myfile.root",
2577 /// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2578 ///
2579 /// Returns a pointer to the new file.
2580 ///
2581 /// Currently, the automatic change of file is restricted
2582 /// to the case where the tree is in the top level directory.
2583 /// The file should not contain sub-directories.
2584 ///
2585 /// Before switching to a new file, the tree header is written
2586 /// to the current file, then the current file is closed.
2587 ///
2588 /// To process the multiple files created by ChangeFile, one must use
2589 /// a TChain.
2590 ///
2591 /// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2592 /// By default a Root session starts with fFileNumber=0. One can set
2593 /// fFileNumber to a different value via TTree::SetFileNumber.
2594 /// In case a file named "_N" already exists, the function will try
2595 /// a file named "__N", then "___N", etc.
2596 ///
2597 /// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2598 /// The default value of fgMaxTreeSize is 100 Gigabytes.
2599 ///
2600 /// If the current file contains other objects like TH1 and TTree,
2601 /// these objects are automatically moved to the new file.
2602 ///
2603 /// IMPORTANT NOTE:
2604 ///
2605 /// Be careful when writing the final Tree header to the file!
2606 ///
2607 /// Don't do:
2608 /// ~~~ {.cpp}
2609 /// TFile *file = new TFile("myfile.root","recreate");
2610 /// TTree *T = new TTree("T","title");
2611 /// T->Fill(); //loop
2612 /// file->Write();
2613 /// file->Close();
2614 /// ~~~
2615 /// but do the following:
2616 /// ~~~ {.cpp}
2617 /// TFile *file = new TFile("myfile.root","recreate");
2618 /// TTree *T = new TTree("T","title");
2619 /// T->Fill(); //loop
2620 /// file = T->GetCurrentFile(); //to get the pointer to the current file
2621 /// file->Write();
2622 /// file->Close();
2623 /// ~~~
2624 
2627  file->cd();
2628  Write();
2629  Reset();
2630  char* fname = new char[2000];
2631  ++fFileNumber;
2632  char uscore[10];
2633  for (Int_t i = 0; i < 10; ++i) {
2634  uscore[i] = 0;
2635  }
2636  Int_t nus = 0;
2637  // Try to find a suitable file name that does not already exist.
2638  while (nus < 10) {
2639  uscore[nus] = '_';
2640  fname[0] = 0;
2641  strlcpy(fname, file->GetName(),2000);
2642 
2643  if (fFileNumber > 1) {
2644  char* cunder = strrchr(fname, '_');
2645  if (cunder) {
2646  snprintf(cunder,2000-Int_t(cunder-fname), "%s%d", uscore, fFileNumber);
2647  const char* cdot = strrchr(file->GetName(), '.');
2648  if (cdot) {
2649  strlcat(fname, cdot,2000);
2650  }
2651  } else {
2652  char fcount[10];
2653  snprintf(fcount,10, "%s%d", uscore, fFileNumber);
2654  strlcat(fname, fcount,2000);
2655  }
2656  } else {
2657  char* cdot = strrchr(fname, '.');
2658  if (cdot) {
2659  snprintf(cdot,2000-Int_t(fname-cdot), "%s%d", uscore, fFileNumber);
2660  strlcat(fname, strrchr(file->GetName(), '.'),2000);
2661  } else {
2662  char fcount[10];
2663  snprintf(fcount,10, "%s%d", uscore, fFileNumber);
2664  strlcat(fname, fcount,2000);
2665  }
2666  }
2667  if (gSystem->AccessPathName(fname)) {
2668  break;
2669  }
2670  ++nus;
2671  Warning("ChangeFile", "file %s already exist, trying with %d underscores", fname, nus+1);
2672  }
2673  Int_t compress = file->GetCompressionSettings();
2674  TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2675  if (newfile == 0) {
2676  Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2677  } else {
2678  Printf("Fill: Switching to new file: %s", fname);
2679  }
2680  // The current directory may contain histograms and trees.
2681  // These objects must be moved to the new file.
2682  TBranch* branch = 0;
2683  TObject* obj = 0;
2684  while ((obj = file->GetList()->First())) {
2685  file->Remove(obj);
2686  // Histogram: just change the directory.
2687  if (obj->InheritsFrom("TH1")) {
2688  gROOT->ProcessLine(TString::Format("((%s*)0x%lx)->SetDirectory((TDirectory*)0x%lx);", obj->ClassName(), (Long_t) obj, (Long_t) newfile));
2689  continue;
2690  }
2691  // Tree: must save all trees in the old file, reset them.
2692  if (obj->InheritsFrom(TTree::Class())) {
2693  TTree* t = (TTree*) obj;
2694  if (t != this) {
2695  t->AutoSave();
2696  t->Reset();
2697  t->fFileNumber = fFileNumber;
2698  }
2699  t->SetDirectory(newfile);
2700  TIter nextb(t->GetListOfBranches());
2701  while ((branch = (TBranch*)nextb())) {
2702  branch->SetFile(newfile);
2703  }
2704  if (t->GetBranchRef()) {
2705  t->GetBranchRef()->SetFile(newfile);
2706  }
2707  continue;
2708  }
2709  // Not a TH1 or a TTree, move object to new file.
2710  if (newfile) newfile->Append(obj);
2711  file->Remove(obj);
2712  }
2713  delete file;
2714  file = 0;
2715  delete[] fname;
2716  fname = 0;
2717  return newfile;
2718 }
2719 
2720 ////////////////////////////////////////////////////////////////////////////////
2721 /// Check whether or not the address described by the last 3 parameters
2722 /// matches the content of the branch. If a Data Model Evolution conversion
2723 /// is involved, reset the fInfo of the branch.
2724 /// The return values are:
2725 //
2726 /// - kMissingBranch (-5) : Missing branch
2727 /// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2728 /// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2729 /// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2730 /// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2731 /// - kMatch (0) : perfect match
2732 /// - kMatchConversion (1) : match with (I/O) conversion
2733 /// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2734 /// - kMakeClass (3) : MakeClass mode so we can not check.
2735 /// - kVoidPtr (4) : void* passed so no check was made.
2736 /// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2737 
2738 Int_t TTree::CheckBranchAddressType(TBranch* branch, TClass* ptrClass, EDataType datatype, Bool_t isptr)
2740  if (GetMakeClass()) {
2741  // If we are in MakeClass mode so we do not really use classes.
2742  return kMakeClass;
2743  }
2744 
2745  // Let's determine what we need!
2746  TClass* expectedClass = 0;
2747  EDataType expectedType = kOther_t;
2748  if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2749  // Something went wrong, the warning message has already be issued.
2750  return kInternalError;
2751  }
2752  if (expectedClass && datatype == kOther_t && ptrClass == 0) {
2753  if (branch->InheritsFrom( TBranchElement::Class() )) {
2754  TBranchElement* bEl = (TBranchElement*)branch;
2755  bEl->SetTargetClass( expectedClass->GetName() );
2756  }
2757  if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2758  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2759  "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2760  "Please generate the dictionary for this class (%s)",
2761  branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2763  }
2764  if (!expectedClass->IsLoaded()) {
2765  // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2766  // (we really don't know). So let's express that.
2767  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2768  "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."
2769  "Please generate the dictionary for this class (%s)",
2770  branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2771  } else {
2772  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2773  "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2774  }
2775  return kClassMismatch;
2776  }
2777  if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2778  // Top Level branch
2779  if (!isptr) {
2780  Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2781  }
2782  }
2783  if (expectedType == kFloat16_t) {
2784  expectedType = kFloat_t;
2785  }
2786  if (expectedType == kDouble32_t) {
2787  expectedType = kDouble_t;
2788  }
2789  if (datatype == kFloat16_t) {
2790  datatype = kFloat_t;
2791  }
2792  if (datatype == kDouble32_t) {
2793  datatype = kDouble_t;
2794  }
2795 
2796  /////////////////////////////////////////////////////////////////////////////
2797  // Deal with the class renaming
2798  /////////////////////////////////////////////////////////////////////////////
2799 
2800  if( expectedClass && ptrClass &&
2801  expectedClass != ptrClass &&
2802  branch->InheritsFrom( TBranchElement::Class() ) &&
2803  ptrClass->GetSchemaRules() &&
2804  ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2805  TBranchElement* bEl = (TBranchElement*)branch;
2806 
2807  if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2808  if (gDebug > 7)
2809  Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2810  "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2811 
2812  bEl->SetTargetClass( ptrClass->GetName() );
2813  return kMatchConversion;
2814 
2815  } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2816  !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2817  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());
2818 
2819  bEl->SetTargetClass( expectedClass->GetName() );
2820  return kClassMismatch;
2821  }
2822  else {
2823 
2824  bEl->SetTargetClass( ptrClass->GetName() );
2825  return kMatchConversion;
2826  }
2827 
2828  } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2829 
2830  if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2831  branch->InheritsFrom( TBranchElement::Class() ) &&
2832  expectedClass->GetCollectionProxy()->GetValueClass() &&
2833  ptrClass->GetCollectionProxy()->GetValueClass() )
2834  {
2835  // In case of collection, we know how to convert them, if we know how to convert their content.
2836  // NOTE: we need to extend this to std::pair ...
2837 
2838  TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2839  TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2840 
2841  if (inmemValueClass->GetSchemaRules() &&
2842  inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2843  {
2844  TBranchElement* bEl = (TBranchElement*)branch;
2845  bEl->SetTargetClass( ptrClass->GetName() );
2847  }
2848  }
2849 
2850  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());
2851  if (branch->InheritsFrom( TBranchElement::Class() )) {
2852  TBranchElement* bEl = (TBranchElement*)branch;
2853  bEl->SetTargetClass( expectedClass->GetName() );
2854  }
2855  return kClassMismatch;
2856 
2857  } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2858  if (datatype != kChar_t) {
2859  // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2860  Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2861  TDataType::GetTypeName(datatype), datatype, TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2862  return kMismatch;
2863  }
2864  } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2865  (ptrClass && (expectedType != kOther_t && expectedType != kNoType_t && datatype != kInt_t)) ) {
2866  // Sometime a null pointer can look an int, avoid complaining in that case.
2867  if (expectedClass) {
2868  Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
2869  TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
2870  if (branch->InheritsFrom( TBranchElement::Class() )) {
2871  TBranchElement* bEl = (TBranchElement*)branch;
2872  bEl->SetTargetClass( expectedClass->GetName() );
2873  }
2874  } else {
2875  // 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
2876  // a struct).
2877  bool found = false;
2878  if (ptrClass->IsLoaded()) {
2879  TIter next(ptrClass->GetListOfRealData());
2880  TRealData *rdm;
2881  while ((rdm = (TRealData*)next())) {
2882  if (rdm->GetThisOffset() == 0) {
2883  TDataType *dmtype = rdm->GetDataMember()->GetDataType();
2884  if (dmtype) {
2885  EDataType etype = (EDataType)dmtype->GetType();
2886  if (etype == expectedType) {
2887  found = true;
2888  }
2889  }
2890  break;
2891  }
2892  }
2893  } else {
2894  TIter next(ptrClass->GetListOfDataMembers());
2895  TDataMember *dm;
2896  while ((dm = (TDataMember*)next())) {
2897  if (dm->GetOffset() == 0) {
2898  TDataType *dmtype = dm->GetDataType();
2899  if (dmtype) {
2900  EDataType etype = (EDataType)dmtype->GetType();
2901  if (etype == expectedType) {
2902  found = true;
2903  }
2904  }
2905  break;
2906  }
2907  }
2908  }
2909  if (found) {
2910  // let's check the size.
2911  TLeaf *last = (TLeaf*)branch->GetListOfLeaves()->Last();
2912  long len = last->GetOffset() + last->GetLenType() * last->GetLen();
2913  if (len <= ptrClass->Size()) {
2914  return kMatch;
2915  }
2916  }
2917  Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2918  ptrClass->GetName(), TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2919  }
2920  return kMismatch;
2921  }
2922  if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2923  Error("SetBranchAddress", writeStlWithoutProxyMsg,
2924  expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
2925  if (branch->InheritsFrom( TBranchElement::Class() )) {
2926  TBranchElement* bEl = (TBranchElement*)branch;
2927  bEl->SetTargetClass( expectedClass->GetName() );
2928  }
2930  }
2931  if (expectedClass && branch->InheritsFrom( TBranchElement::Class() )) {
2932  TBranchElement* bEl = (TBranchElement*)branch;
2933  bEl->SetTargetClass( expectedClass->GetName() );
2934  }
2935  return kMatch;
2936 }
2937 
2938 ////////////////////////////////////////////////////////////////////////////////
2939 /// Create a clone of this tree and copy nentries.
2940 ///
2941 /// By default copy all entries.
2942 /// The compression level of the cloned tree is set to the destination
2943 /// file's compression level.
2944 ///
2945 /// NOTE: Only active branches are copied.
2946 /// NOTE: If the TTree is a TChain, the structure of the first TTree
2947 /// is used for the copy.
2948 ///
2949 /// IMPORTANT: The cloned tree stays connected with this tree until
2950 /// this tree is deleted. In particular, any changes in
2951 /// branch addresses in this tree are forwarded to the
2952 /// clone trees, unless a branch in a clone tree has had
2953 /// its address changed, in which case that change stays in
2954 /// effect. When this tree is deleted, all the addresses of
2955 /// the cloned tree are reset to their default values.
2956 ///
2957 /// If 'option' contains the word 'fast' and nentries is -1, the
2958 /// cloning will be done without unzipping or unstreaming the baskets
2959 /// (i.e., a direct copy of the raw bytes on disk).
2960 ///
2961 /// When 'fast' is specified, 'option' can also contain a sorting
2962 /// order for the baskets in the output file.
2963 ///
2964 /// There are currently 3 supported sorting order:
2965 ///
2966 /// - SortBasketsByOffset (the default)
2967 /// - SortBasketsByBranch
2968 /// - SortBasketsByEntry
2969 ///
2970 /// When using SortBasketsByOffset the baskets are written in the
2971 /// output file in the same order as in the original file (i.e. the
2972 /// baskets are sorted by their offset in the original file; Usually
2973 /// this also means that the baskets are sorted by the index/number of
2974 /// the _last_ entry they contain)
2975 ///
2976 /// When using SortBasketsByBranch all the baskets of each individual
2977 /// branches are stored contiguously. This tends to optimize reading
2978 /// speed when reading a small number (1->5) of branches, since all
2979 /// their baskets will be clustered together instead of being spread
2980 /// across the file. However it might decrease the performance when
2981 /// reading more branches (or the full entry).
2982 ///
2983 /// When using SortBasketsByEntry the baskets with the lowest starting
2984 /// entry are written first. (i.e. the baskets are sorted by the
2985 /// index/number of the first entry they contain). This means that on
2986 /// the file the baskets will be in the order in which they will be
2987 /// needed when reading the whole tree sequentially.
2988 ///
2989 /// For examples of CloneTree, see tutorials:
2990 ///
2991 /// - copytree:
2992 /// A macro to copy a subset of a TTree to a new TTree.
2993 /// The input file has been generated by the program in
2994 /// $ROOTSYS/test/Event with: Event 1000 1 1 1
2995 ///
2996 /// - copytree2:
2997 /// A macro to copy a subset of a TTree to a new TTree.
2998 /// One branch of the new Tree is written to a separate file.
2999 /// The input file has been generated by the program in
3000 /// $ROOTSYS/test/Event with: Event 1000 1 1 1
3001 
3002 TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3004  // Options
3005  Bool_t fastClone = kFALSE;
3006 
3007  TString opt = option;
3008  opt.ToLower();
3009  if (opt.Contains("fast")) {
3010  fastClone = kTRUE;
3011  }
3012 
3013  // If we are a chain, switch to the first tree.
3014  if ((fEntries > 0) && (LoadTree(0) < 0)) {
3015  // FIXME: We need an error message here.
3016  return 0;
3017  }
3018 
3019  // Note: For a tree we get the this pointer, for
3020  // a chain we get the chain's current tree.
3021  TTree* thistree = GetTree();
3022 
3023  // Note: For a chain, the returned clone will be
3024  // a clone of the chain's first tree.
3025  TTree* newtree = (TTree*) thistree->Clone();
3026  if (!newtree) {
3027  return 0;
3028  }
3029 
3030  // The clone should not delete any objects allocated by SetAddress().
3031  TObjArray* branches = newtree->GetListOfBranches();
3032  Int_t nb = branches->GetEntriesFast();
3033  for (Int_t i = 0; i < nb; ++i) {
3034  TBranch* br = (TBranch*) branches->UncheckedAt(i);
3035  if (br->InheritsFrom(TBranchElement::Class())) {
3036  ((TBranchElement*) br)->ResetDeleteObject();
3037  }
3038  }
3039 
3040  // Add the new tree to the list of clones so that
3041  // we can later inform it of changes to branch addresses.
3042  thistree->AddClone(newtree);
3043  if (thistree != this) {
3044  // In case this object is a TChain, add the clone
3045  // also to the TChain's list of clones.
3046  AddClone(newtree);
3047  }
3048 
3049  newtree->Reset();
3050 
3051  TDirectory* ndir = newtree->GetDirectory();
3052  TFile* nfile = 0;
3053  if (ndir) {
3054  nfile = ndir->GetFile();
3055  }
3056  Int_t newcomp = -1;
3057  if (nfile) {
3058  newcomp = nfile->GetCompressionSettings();
3059  }
3060 
3061  //
3062  // Delete non-active branches from the clone.
3063  //
3064  // Note: If we are a chain, this does nothing
3065  // since chains have no leaves.
3066  TObjArray* leaves = newtree->GetListOfLeaves();
3067  Int_t nleaves = leaves->GetEntriesFast();
3068  for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3069  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3070  if (!leaf) {
3071  continue;
3072  }
3073  TBranch* branch = leaf->GetBranch();
3074  if (branch && (newcomp > -1)) {
3075  branch->SetCompressionSettings(newcomp);
3076  }
3077  if (!branch || !branch->TestBit(kDoNotProcess)) {
3078  continue;
3079  }
3080  // size might change at each iteration of the loop over the leaves.
3081  nb = branches->GetEntriesFast();
3082  for (Long64_t i = 0; i < nb; ++i) {
3083  TBranch* br = (TBranch*) branches->UncheckedAt(i);
3084  if (br == branch) {
3085  branches->RemoveAt(i);
3086  delete br;
3087  br = 0;
3088  branches->Compress();
3089  break;
3090  }
3091  TObjArray* lb = br->GetListOfBranches();
3092  Int_t nb1 = lb->GetEntriesFast();
3093  for (Int_t j = 0; j < nb1; ++j) {
3094  TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3095  if (!b1) {
3096  continue;
3097  }
3098  if (b1 == branch) {
3099  lb->RemoveAt(j);
3100  delete b1;
3101  b1 = 0;
3102  lb->Compress();
3103  break;
3104  }
3105  TObjArray* lb1 = b1->GetListOfBranches();
3106  Int_t nb2 = lb1->GetEntriesFast();
3107  for (Int_t k = 0; k < nb2; ++k) {
3108  TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3109  if (!b2) {
3110  continue;
3111  }
3112  if (b2 == branch) {
3113  lb1->RemoveAt(k);
3114  delete b2;
3115  b2 = 0;
3116  lb1->Compress();
3117  break;
3118  }
3119  }
3120  }
3121  }
3122  }
3123  leaves->Compress();
3124 
3125  // Copy MakeClass status.
3126  newtree->SetMakeClass(fMakeClass);
3127 
3128  // Copy branch addresses.
3129  CopyAddresses(newtree);
3130 
3131  //
3132  // Copy entries if requested.
3133  //
3134 
3135  if (nentries != 0) {
3136  if (fastClone && (nentries < 0)) {
3137  if ( newtree->CopyEntries( this, -1, option ) < 0 ) {
3138  // There was a problem!
3139  Error("CloneTTree", "TTree has not been cloned\n");
3140  delete newtree;
3141  newtree = 0;
3142  return 0;
3143  }
3144  } else {
3145  newtree->CopyEntries( this, nentries, option );
3146  }
3147  }
3148 
3149  return newtree;
3150 }
3151 
3152 ////////////////////////////////////////////////////////////////////////////////
3153 /// Set branch addresses of passed tree equal to ours.
3154 /// If undo is true, reset the branch address instead of copying them.
3155 /// This insures 'separation' of a cloned tree from its original
3156 
3157 void TTree::CopyAddresses(TTree* tree, Bool_t undo)
3159  // Copy branch addresses starting from branches.
3160  TObjArray* branches = GetListOfBranches();
3161  Int_t nbranches = branches->GetEntriesFast();
3162  for (Int_t i = 0; i < nbranches; ++i) {
3163  TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3164  if (branch->TestBit(kDoNotProcess)) {
3165  continue;
3166  }
3167  if (undo) {
3168  TBranch* br = tree->GetBranch(branch->GetName());
3169  tree->ResetBranchAddress(br);
3170  } else {
3171  char* addr = branch->GetAddress();
3172  if (!addr) {
3173  if (branch->IsA() == TBranch::Class()) {
3174  // If the branch was created using a leaflist, the branch itself may not have
3175  // an address but the leaf might already.
3176  TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3177  if (!firstleaf || firstleaf->GetValuePointer()) {
3178  // Either there is no leaf (and thus no point in copying the address)
3179  // or the leaf has an address but we can not copy it via the branche
3180  // this will be copied via the next loop (over the leaf).
3181  continue;
3182  }
3183  }
3184  // Note: This may cause an object to be allocated.
3185  branch->SetAddress(0);
3186  addr = branch->GetAddress();
3187  }
3188  // FIXME: The GetBranch() function is braindead and may
3189  // not find the branch!
3190  TBranch* br = tree->GetBranch(branch->GetName());
3191  if (br) {
3192  br->SetAddress(addr);
3193  // The copy does not own any object allocated by SetAddress().
3194  if (br->InheritsFrom(TBranchElement::Class())) {
3195  ((TBranchElement*) br)->ResetDeleteObject();
3196  }
3197  } else {
3198  Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3199  }
3200  }
3201  }
3202 
3203  // Copy branch addresses starting from leaves.
3204  TObjArray* tleaves = tree->GetListOfLeaves();
3205  Int_t ntleaves = tleaves->GetEntriesFast();
3206  for (Int_t i = 0; i < ntleaves; ++i) {
3207  TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3208  TBranch* tbranch = tleaf->GetBranch();
3209  TBranch* branch = GetBranch(tbranch->GetName());
3210  if (!branch) {
3211  continue;
3212  }
3213  TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3214  if (!leaf) {
3215  continue;
3216  }
3217  if (branch->TestBit(kDoNotProcess)) {
3218  continue;
3219  }
3220  if (undo) {
3221  // Now we know whether the address has been transfered
3222  tree->ResetBranchAddress(tbranch);
3223  } else {
3224  if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3225  // We should attempts to set the address of the branch.
3226  // something like:
3227  //(TBranchElement*)branch->GetMother()->SetAddress(0)
3228  //plus a few more subtilities (see TBranchElement::GetEntry).
3229  //but for now we go the simplest route:
3230  //
3231  // Note: This may result in the allocation of an object.
3232  branch->SetupAddresses();
3233  }
3234  if (branch->GetAddress()) {
3235  tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3236  TBranch* br = tree->GetBranch(branch->GetName());
3237  if (br) {
3238  // The copy does not own any object allocated by SetAddress().
3239  // FIXME: We do too much here, br may not be a top-level branch.
3240  if (br->InheritsFrom(TBranchElement::Class())) {
3241  ((TBranchElement*) br)->ResetDeleteObject();
3242  }
3243  } else {
3244  Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3245  }
3246  } else {
3247  tleaf->SetAddress(leaf->GetValuePointer());
3248  }
3249  }
3250  }
3251 
3252  if (undo &&
3253  ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3254  ) {
3255  tree->ResetBranchAddresses();
3256  }
3257 }
3258 
3259 namespace {
3260 
3261  enum EOnIndexError { kDrop, kKeep, kBuild };
3263  static Bool_t R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3264  {
3265  // Return true if we should continue to handle indices, false otherwise.
3266 
3267  Bool_t withIndex = kTRUE;
3268 
3269  if ( newtree->GetTreeIndex() ) {
3270  if ( oldtree->GetTree()->GetTreeIndex() == 0 ) {
3271  switch (onIndexError) {
3272  case kDrop:
3273  delete newtree->GetTreeIndex();
3274  newtree->SetTreeIndex(0);
3275  withIndex = kFALSE;
3276  break;
3277  case kKeep:
3278  // Nothing to do really.
3279  break;
3280  case kBuild:
3281  // Build the index then copy it
3282  if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3283  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3284  // Clean up
3285  delete oldtree->GetTree()->GetTreeIndex();
3286  oldtree->GetTree()->SetTreeIndex(0);
3287  }
3288  break;
3289  }
3290  } else {
3291  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3292  }
3293  } else if ( oldtree->GetTree()->GetTreeIndex() != 0 ) {
3294  // We discover the first index in the middle of the chain.
3295  switch (onIndexError) {
3296  case kDrop:
3297  // Nothing to do really.
3298  break;
3299  case kKeep: {
3300  TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3301  index->SetTree(newtree);
3302  newtree->SetTreeIndex(index);
3303  break;
3304  }
3305  case kBuild:
3306  if (newtree->GetEntries() == 0) {
3307  // Start an index.
3308  TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3309  index->SetTree(newtree);
3310  newtree->SetTreeIndex(index);
3311  } else {
3312  // Build the index so far.
3313  if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3314  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3315  }
3316  }
3317  break;
3318  }
3319  } else if ( onIndexError == kDrop ) {
3320  // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3321  // index
3322  withIndex = kFALSE;
3323  }
3324  return withIndex;
3325  }
3326 }
3327 
3328 ////////////////////////////////////////////////////////////////////////////////
3329 /// Copy nentries from given tree to this tree.
3330 /// This routines assumes that the branches that intended to be copied are
3331 /// already connected. The typical case is that this tree was created using
3332 /// tree->CloneTree(0).
3333 ///
3334 /// By default copy all entries.
3335 ///
3336 /// Returns number of bytes copied to this tree.
3337 ///
3338 /// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3339 /// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3340 /// raw bytes on disk).
3341 ///
3342 /// When 'fast' is specified, 'option' can also contains a sorting order for the
3343 /// baskets in the output file.
3344 ///
3345 /// There are currently 3 supported sorting order:
3346 ///
3347 /// - SortBasketsByOffset (the default)
3348 /// - SortBasketsByBranch
3349 /// - SortBasketsByEntry
3350 ///
3351 /// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3352 ///
3353 /// If the tree or any of the underlying tree of the chain has an index, that index and any
3354 /// index in the subsequent underlying TTree objects will be merged.
3355 ///
3356 /// There are currently three 'options' to control this merging:
3357 /// - NoIndex : all the TTreeIndex object are dropped.
3358 /// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3359 /// they are all dropped.
3360 /// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3361 /// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3362 /// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3363 
3364 Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3366  if (!tree) {
3367  return 0;
3368  }
3369  // Options
3370  TString opt = option;
3371  opt.ToLower();
3372  Bool_t fastClone = opt.Contains("fast");
3373  Bool_t withIndex = !opt.Contains("noindex");
3374  EOnIndexError onIndexError;
3375  if (opt.Contains("asisindex")) {
3376  onIndexError = kKeep;
3377  } else if (opt.Contains("buildindex")) {
3378  onIndexError = kBuild;
3379  } else if (opt.Contains("dropindex")) {
3380  onIndexError = kDrop;
3381  } else {
3382  onIndexError = kBuild;
3383  }
3384  Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3385  Int_t cacheSize = -1;
3386  if (cacheSizeLoc != TString::kNPOS) {
3387  // If the parse faile, cacheSize stays at -1.
3388  Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3389  TSubString cacheSizeStr( opt(cacheSizeLoc+10,cacheSizeEnd) );
3390  auto parseResult = ROOT::FromHumanReadableSize(cacheSizeStr,cacheSize);
3391  if (parseResult == ROOT::EFromHumanReadableSize::kParseFail) {
3392  Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3393  } else if (parseResult == ROOT::EFromHumanReadableSize::kOverflow) {
3394  double m;
3395  const char *munit = nullptr;
3396  ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3397 
3398  Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3399  }
3400  }
3401  if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %d\n",cacheSize);
3402 
3403  Long64_t nbytes = 0;
3404  Long64_t treeEntries = tree->GetEntriesFast();
3405  if (nentries < 0) {
3406  nentries = treeEntries;
3407  } else if (nentries > treeEntries) {
3408  nentries = treeEntries;
3409  }
3410 
3411  if (fastClone && (nentries < 0 || nentries == tree->GetEntriesFast())) {
3412  // Quickly copy the basket without decompression and streaming.
3413  Long64_t totbytes = GetTotBytes();
3414  for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3415  if (tree->LoadTree(i) < 0) {
3416  break;
3417  }
3418  if ( withIndex ) {
3419  withIndex = R__HandleIndex( onIndexError, this, tree );
3420  }
3421  if (this->GetDirectory()) {
3422  TFile* file2 = this->GetDirectory()->GetFile();
3423  if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3424  if (this->GetDirectory() == (TDirectory*) file2) {
3425  this->ChangeFile(file2);
3426  }
3427  }
3428  }
3429  TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3430  if (cloner.IsValid()) {
3431  this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3432  if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3433  cloner.Exec();
3434  } else {
3435  if (i == 0) {
3436  Warning("CopyEntries","%s",cloner.GetWarning());
3437  // If the first cloning does not work, something is really wrong
3438  // (since apriori the source and target are exactly the same structure!)
3439  return -1;
3440  } else {
3441  if (cloner.NeedConversion()) {
3442  TTree *localtree = tree->GetTree();
3443  Long64_t tentries = localtree->GetEntries();
3444  for (Long64_t ii = 0; ii < tentries; ii++) {
3445  if (localtree->GetEntry(ii) <= 0) {
3446  break;
3447  }
3448  this->Fill();
3449  }
3450  if (this->GetTreeIndex()) {
3451  this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), kTRUE);
3452  }
3453  } else {
3454  Warning("CopyEntries","%s",cloner.GetWarning());
3455  if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3456  Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3457  } else {
3458  Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3459  }
3460  }
3461  }
3462  }
3463 
3464  }
3465  if (this->GetTreeIndex()) {
3466  this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3467  }
3468  nbytes = GetTotBytes() - totbytes;
3469  } else {
3470  if (nentries < 0) {
3471  nentries = treeEntries;
3472  } else if (nentries > treeEntries) {
3473  nentries = treeEntries;
3474  }
3475  Int_t treenumber = -1;
3476  for (Long64_t i = 0; i < nentries; i++) {
3477  if (tree->LoadTree(i) < 0) {
3478  break;
3479  }
3480  if (treenumber != tree->GetTreeNumber()) {
3481  if ( withIndex ) {
3482  withIndex = R__HandleIndex( onIndexError, this, tree );
3483  }
3484  treenumber = tree->GetTreeNumber();
3485  }
3486  if (tree->GetEntry(i) <= 0) {
3487  break;
3488  }
3489  nbytes += this->Fill();
3490  }
3491  if (this->GetTreeIndex()) {
3492  this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3493  }
3494  }
3495  return nbytes;
3496 }
3497 
3498 ////////////////////////////////////////////////////////////////////////////////
3499 /// Copy a tree with selection.
3500 ///
3501 /// IMPORTANT:
3502 ///
3503 /// The returned copied tree stays connected with the original tree
3504 /// until the original tree is deleted. In particular, any changes
3505 /// to the branch addresses in the original tree are also made to
3506 /// the copied tree. Any changes made to the branch addresses of the
3507 /// copied tree are overridden anytime the original tree changes its
3508 /// branch addresses. When the original tree is deleted, all the
3509 /// branch addresses of the copied tree are set to zero.
3510 ///
3511 /// For examples of CopyTree, see the tutorials:
3512 ///
3513 /// - copytree:
3514 /// Example macro to copy a subset of a tree to a new tree.
3515 /// The input file was generated by running the program in
3516 /// $ROOTSYS/test/Event in this way:
3517 /// ~~~ {.cpp}
3518 /// ./Event 1000 1 1 1
3519 /// ~~~
3520 /// - copytree2
3521 /// Example macro to copy a subset of a tree to a new tree.
3522 /// One branch of the new tree is written to a separate file.
3523 /// The input file was generated by running the program in
3524 /// $ROOTSYS/test/Event in this way:
3525 /// ~~~ {.cpp}
3526 /// ./Event 1000 1 1 1
3527 /// ~~~
3528 /// - copytree3
3529 /// Example macro to copy a subset of a tree to a new tree.
3530 /// Only selected entries are copied to the new tree.
3531 /// NOTE that only the active branches are copied.
3532 
3533 TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3535  GetPlayer();
3536  if (fPlayer) {
3537  return fPlayer->CopyTree(selection, option, nentries, firstentry);
3538  }
3539  return 0;
3540 }
3541 
3542 ////////////////////////////////////////////////////////////////////////////////
3543 /// Create a basket for this tree and given branch.
3544 
3547  if (!branch) {
3548  return 0;
3549  }
3550  return new TBasket(branch->GetName(), GetName(), branch);
3551 }
3552 
3553 ////////////////////////////////////////////////////////////////////////////////
3554 /// Delete this tree from memory or/and disk.
3555 ///
3556 /// - if option == "all" delete Tree object from memory AND from disk
3557 /// all baskets on disk are deleted. All keys with same name
3558 /// are deleted.
3559 /// - if option =="" only Tree object in memory is deleted.
3560 
3561 void TTree::Delete(Option_t* option /* = "" */)
3563  TFile *file = GetCurrentFile();
3564 
3565  // delete all baskets and header from file
3566  if (file && !strcmp(option,"all")) {
3567  if (!file->IsWritable()) {
3568  Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3569  return;
3570  }
3571 
3572  //find key and import Tree header in memory
3573  TKey *key = fDirectory->GetKey(GetName());
3574  if (!key) return;
3575 
3576  TDirectory *dirsav = gDirectory;
3577  file->cd();
3578 
3579  //get list of leaves and loop on all the branches baskets
3580  TIter next(GetListOfLeaves());
3581  TLeaf *leaf;
3582  char header[16];
3583  Int_t ntot = 0;
3584  Int_t nbask = 0;
3585  Int_t nbytes,objlen,keylen;
3586  while ((leaf = (TLeaf*)next())) {
3587  TBranch *branch = leaf->GetBranch();
3588  Int_t nbaskets = branch->GetMaxBaskets();
3589  for (Int_t i=0;i<nbaskets;i++) {
3590  Long64_t pos = branch->GetBasketSeek(i);
3591  if (!pos) continue;
3592  TFile *branchFile = branch->GetFile();
3593  if (!branchFile) continue;
3594  branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3595  if (nbytes <= 0) continue;
3596  branchFile->MakeFree(pos,pos+nbytes-1);
3597  ntot += nbytes;
3598  nbask++;
3599  }
3600  }
3601 
3602  // delete Tree header key and all keys with the same name
3603  // A Tree may have been saved many times. Previous cycles are invalid.
3604  while (key) {
3605  ntot += key->GetNbytes();
3606  key->Delete();
3607  delete key;
3608  key = fDirectory->GetKey(GetName());
3609  }
3610  if (dirsav) dirsav->cd();
3611  if (gDebug) printf(" Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3612  }
3613 
3614  if (fDirectory) {
3615  fDirectory->Remove(this);
3616  //delete the file cache if it points to this Tree
3617  MoveReadCache(file,0);
3618  fDirectory = 0;
3620  }
3621 
3622  // Delete object from CINT symbol table so it can not be used anymore.
3623  gCling->DeleteGlobal(this);
3624 
3625  // Warning: We have intentional invalidated this object while inside a member function!
3626  delete this;
3627 }
3628 
3629  ///////////////////////////////////////////////////////////////////////////////
3630  /// Called by TKey and TObject::Clone to automatically add us to a directory
3631  /// when we are read from a file.
3632 
3635  if (fDirectory == dir) return;
3636  if (fDirectory) {
3637  fDirectory->Remove(this);
3638  // Delete or move the file cache if it points to this Tree
3639  TFile *file = fDirectory->GetFile();
3640  MoveReadCache(file,dir);
3641  }
3642  fDirectory = dir;
3643  TBranch* b = 0;
3644  TIter next(GetListOfBranches());
3645  while((b = (TBranch*) next())) {
3646  b->UpdateFile();
3647  }
3648  if (fBranchRef) {
3650  }
3651  if (fDirectory) fDirectory->Append(this);
3652 }
3653 
3654 ////////////////////////////////////////////////////////////////////////////////
3655 /// Draw expression varexp for specified entries.
3656 /// Returns -1 in case of error or number of selected events in case of success.
3657 ///
3658 /// This function accepts TCut objects as arguments.
3659 /// Useful to use the string operator +
3660 ///
3661 /// Example:
3662 ///
3663 /// ntuple.Draw("x",cut1+cut2+cut3);
3664 
3665 Long64_t TTree::Draw(const char* varexp, const TCut& selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
3667  return TTree::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
3668 }
3669 
3670 ////////////////////////////////////////////////////////////////////////////////
3671 /// Draw expression varexp for specified entries.
3672 /// Returns -1 in case of error or number of selected events in case of success.
3673 ///
3674 /// varexp is an expression of the general form
3675 /// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3676 /// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3677 /// on the y-axis versus "e2" on the x-axis
3678 /// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3679 /// versus "e2" versus "e3" on the x-, y-, z-axis, respectively.
3680 /// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3681 /// versus "e2" versus "e3" and "e4" mapped on the color number.
3682 /// (to create histograms in the 2, 3, and 4 dimensional case, see section "Saving
3683 /// the result of Draw to an histogram")
3684 ///
3685 /// Example:
3686 /// - varexp = x simplest case: draw a 1-Dim distribution of column named x
3687 /// - varexp = sqrt(x) : draw distribution of sqrt(x)
3688 /// - varexp = x*y/z
3689 /// - varexp = y:sqrt(x) 2-Dim distribution of y versus sqrt(x)
3690 /// - varexp = px:py:pz:2.5*E produces a 3-d scatter-plot of px vs py ps pz
3691 /// and the color number of each marker will be 2.5*E.
3692 /// If the color number is negative it is set to 0.
3693 /// If the color number is greater than the current number of colors
3694 /// it is set to the highest color number.The default number of
3695 /// colors is 50. see TStyle::SetPalette for setting a new color palette.
3696 ///
3697 /// Note that the variables e1, e2 or e3 may contain a selection.
3698 /// example, if e1= x*(y<0), the value histogrammed will be x if y<0
3699 /// and will be 0 otherwise.
3700 ///
3701 /// The expressions can use all the operations and build-in functions
3702 /// supported by TFormula (See TFormula::Analyze), including free
3703 /// standing function taking numerical arguments (TMath::Bessel).
3704 /// In addition, you can call member functions taking numerical
3705 /// arguments. For example:
3706 /// ~~~ {.cpp}
3707 /// TMath::BreitWigner(fPx,3,2)
3708 /// event.GetHistogram().GetXaxis().GetXmax()
3709 /// ~~~
3710 /// Note: You can only pass expression that depend on the TTree's data
3711 /// to static functions and you can only call non-static member function
3712 /// with 'fixed' parameters.
3713 ///
3714 /// selection is an expression with a combination of the columns.
3715 /// In a selection all the C++ operators are authorized.
3716 /// The value corresponding to the selection expression is used as a weight
3717 /// to fill the histogram.
3718 /// If the expression includes only boolean operations, the result
3719 /// is 0 or 1. If the result is 0, the histogram is not filled.
3720 /// In general, the expression may be of the form:
3721 /// ~~~ {.cpp}
3722 /// value*(boolean expression)
3723 /// ~~~
3724 /// if boolean expression is true, the histogram is filled with
3725 /// a `weight = value`.
3726 ///
3727 /// Examples:
3728 /// - selection1 = "x<y && sqrt(z)>3.2"
3729 /// - selection2 = "(x+y)*(sqrt(z)>3.2)"
3730 ///
3731 /// - selection1 returns a weight = 0 or 1
3732 /// - selection2 returns a weight = x+y if sqrt(z)>3.2
3733 /// returns a weight = 0 otherwise.
3734 ///
3735 /// option is the drawing option.
3736 /// - See TH1::Draw for the list of all drawing options.
3737 /// - If option COL is specified when varexp has three fields:
3738 /// ~~~ {.cpp}
3739 /// tree.Draw("e1:e2:e3","","col");
3740 /// ~~~
3741 /// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the color
3742 /// table. The colors for e3 are evaluated once in linear scale before
3743 /// painting. Therefore changing the pad to log scale along Z as no effect
3744 /// on the colors.
3745 /// - If option contains the string "goff", no graphics is generated.
3746 ///
3747 /// `nentries` is the number of entries to process (default is all)
3748 /// first is the first entry to process (default is 0)
3749 ///
3750 /// This function returns the number of selected entries. It returns -1
3751 /// if an error occurs.
3752 ///
3753 /// ## Drawing expressions using arrays and array elements
3754 ///
3755 /// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3756 /// or a TClonesArray.
3757 /// In a TTree::Draw expression you can now access fMatrix using the following
3758 /// syntaxes:
3759 ///
3760 /// | String passed | What is used for each entry of the tree
3761 /// |-----------------|--------------------------------------------------------|
3762 /// | `fMatrix` | the 9 elements of fMatrix |
3763 /// | `fMatrix[][]` | the 9 elements of fMatrix |
3764 /// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3765 /// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3766 /// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3767 /// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3768 ///
3769 /// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3770 ///
3771 /// In summary, if a specific index is not specified for a dimension, TTree::Draw
3772 /// will loop through all the indices along this dimension. Leaving off the
3773 /// last (right most) dimension of specifying then with the two characters '[]'
3774 /// is equivalent. For variable size arrays (and TClonesArray) the range
3775 /// of the first dimension is recalculated for each entry of the tree.
3776 /// You can also specify the index as an expression of any other variables from the
3777 /// tree.
3778 ///
3779 /// TTree::Draw also now properly handling operations involving 2 or more arrays.
3780 ///
3781 /// Let assume a second matrix fResults[5][2], here are a sample of some
3782 /// of the possible combinations, the number of elements they produce and
3783 /// the loop used:
3784 ///
3785 /// | expression | element(s) | Loop |
3786 /// |----------------------------------|------------|--------------------------|
3787 /// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
3788 /// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
3789 /// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
3790 /// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
3791 /// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
3792 /// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
3793 /// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
3794 /// | `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.|
3795 ///
3796 ///
3797 /// In summary, TTree::Draw loops through all unspecified dimensions. To
3798 /// figure out the range of each loop, we match each unspecified dimension
3799 /// from left to right (ignoring ALL dimensions for which an index has been
3800 /// specified), in the equivalent loop matched dimensions use the same index
3801 /// and are restricted to the smallest range (of only the matched dimensions).
3802 /// When involving variable arrays, the range can of course be different
3803 /// for each entry of the tree.
3804 ///
3805 /// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
3806 /// ~~~ {.cpp}
3807 /// for (Int_t i0; i < min(3,2); i++) {
3808 /// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
3809 /// }
3810 /// ~~~
3811 /// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
3812 /// ~~~ {.cpp}
3813 /// for (Int_t i0; i < min(3,5); i++) {
3814 /// for (Int_t i1; i1 < 2; i1++) {
3815 /// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
3816 /// }
3817 /// }
3818 /// ~~~
3819 /// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
3820 /// ~~~ {.cpp}
3821 /// for (Int_t i0; i < min(3,5); i++) {
3822 /// for (Int_t i1; i1 < min(3,2); i1++) {
3823 /// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
3824 /// }
3825 /// }
3826 /// ~~~
3827 /// So the loop equivalent to "fMatrix[][fResults[][]]" is:
3828 /// ~~~ {.cpp}
3829 /// for (Int_t i0; i0 < 3; i0++) {
3830 /// for (Int_t j2; j2 < 5; j2++) {
3831 /// for (Int_t j3; j3 < 2; j3++) {
3832 /// i1 = fResults[j2][j3];
3833 /// use the value of fMatrix[i0][i1]
3834 /// }
3835 /// }
3836 /// ~~~
3837 /// ## Retrieving the result of Draw
3838 ///
3839 /// By default the temporary histogram created is called "htemp", but only in
3840 /// the one dimensional Draw("e1") it contains the TTree's data points. For
3841 /// a two dimensional Draw, the data is filled into a TGraph which is named
3842 /// "Graph". They can be retrieved by calling
3843 /// ~~~ {.cpp}
3844 /// TH1F *htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
3845 /// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3846 /// ~~~
3847 /// For a three and four dimensional Draw the TPolyMarker3D is unnamed, and
3848 /// cannot be retrieved.
3849 ///
3850 /// gPad always contains a TH1 derived object called "htemp" which allows to
3851 /// access the axes:
3852 /// ~~~ {.cpp}
3853 /// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3854 /// TH2F *htemp = (TH2F*)gPad->GetPrimitive("htemp"); // empty, but has axes
3855 /// TAxis *xaxis = htemp->GetXaxis();
3856 /// ~~~
3857 /// ## Saving the result of Draw to an histogram
3858 ///
3859 /// If varexp0 contains >>hnew (following the variable(s) name(s),
3860 /// the new histogram created is called hnew and it is kept in the current
3861 /// directory (and also the current pad). This works for all dimensions.
3862 ///
3863 /// Example:
3864 /// ~~~ {.cpp}
3865 /// tree.Draw("sqrt(x)>>hsqrt","y>0")
3866 /// ~~~
3867 /// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
3868 /// directory. To retrieve it do:
3869 /// ~~~ {.cpp}
3870 /// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
3871 /// ~~~
3872 /// The binning information is taken from the environment variables
3873 /// ~~~ {.cpp}
3874 /// Hist.Binning.?D.?
3875 /// ~~~
3876 /// In addition, the name of the histogram can be followed by up to 9
3877 /// numbers between '(' and ')', where the numbers describe the
3878 /// following:
3879 ///
3880 /// - 1 - bins in x-direction
3881 /// - 2 - lower limit in x-direction
3882 /// - 3 - upper limit in x-direction
3883 /// - 4-6 same for y-direction
3884 /// - 7-9 same for z-direction
3885 ///
3886 /// When a new binning is used the new value will become the default.
3887 /// Values can be skipped.
3888 ///
3889 /// Example:
3890 /// ~~~ {.cpp}
3891 /// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
3892 /// // plot sqrt(x) between 10 and 20 using 500 bins
3893 /// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
3894 /// // plot sqrt(x) against sin(y)
3895 /// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
3896 /// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
3897 /// ~~~
3898 /// By default, the specified histogram is reset.
3899 /// To continue to append data to an existing histogram, use "+" in front
3900 /// of the histogram name.
3901 ///
3902 /// A '+' in front of the histogram name is ignored, when the name is followed by
3903 /// binning information as described in the previous paragraph.
3904 /// ~~~ {.cpp}
3905 /// tree.Draw("sqrt(x)>>+hsqrt","y>0")
3906 /// ~~~
3907 /// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
3908 /// and 3-D histograms.
3909 ///
3910 /// ## Accessing collection objects
3911 ///
3912 /// TTree::Draw default's handling of collections is to assume that any
3913 /// request on a collection pertain to it content. For example, if fTracks
3914 /// is a collection of Track objects, the following:
3915 /// ~~~ {.cpp}
3916 /// tree->Draw("event.fTracks.fPx");
3917 /// ~~~
3918 /// will plot the value of fPx for each Track objects inside the collection.
3919 /// Also
3920 /// ~~~ {.cpp}
3921 /// tree->Draw("event.fTracks.size()");
3922 /// ~~~
3923 /// would plot the result of the member function Track::size() for each
3924 /// Track object inside the collection.
3925 /// To access information about the collection itself, TTree::Draw support
3926 /// the '@' notation. If a variable which points to a collection is prefixed
3927 /// or postfixed with '@', the next part of the expression will pertain to
3928 /// the collection object. For example:
3929 /// ~~~ {.cpp}
3930 /// tree->Draw("event.@fTracks.size()");
3931 /// ~~~
3932 /// will plot the size of the collection referred to by `fTracks` (i.e the number
3933 /// of Track objects).
3934 ///
3935 /// ## Drawing 'objects'
3936 ///
3937 /// When a class has a member function named AsDouble or AsString, requesting
3938 /// to directly draw the object will imply a call to one of the 2 functions.
3939 /// If both AsDouble and AsString are present, AsDouble will be used.
3940 /// AsString can return either a char*, a std::string or a TString.s
3941 /// For example, the following
3942 /// ~~~ {.cpp}
3943 /// tree->Draw("event.myTTimeStamp");
3944 /// ~~~
3945 /// will draw the same histogram as
3946 /// ~~~ {.cpp}
3947 /// tree->Draw("event.myTTimeStamp.AsDouble()");
3948 /// ~~~
3949 /// In addition, when the object is a type TString or std::string, TTree::Draw
3950 /// will call respectively `TString::Data` and `std::string::c_str()`
3951 ///
3952 /// If the object is a TBits, the histogram will contain the index of the bit
3953 /// that are turned on.
3954 ///
3955 /// ## Retrieving information about the tree itself.
3956 ///
3957 /// You can refer to the tree (or chain) containing the data by using the
3958 /// string 'This'.
3959 /// You can then could any TTree methods. For example:
3960 /// ~~~ {.cpp}
3961 /// tree->Draw("This->GetReadEntry()");
3962 /// ~~~
3963 /// will display the local entry numbers be read.
3964 /// ~~~ {.cpp}
3965 /// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
3966 /// ~~~
3967 /// will display the name of the first 'user info' object.
3968 ///
3969 /// ## Special functions and variables
3970 ///
3971 /// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
3972 /// to access the entry number being read. For example to draw every
3973 /// other entry use:
3974 /// ~~~ {.cpp}
3975 /// tree.Draw("myvar","Entry$%2==0");
3976 /// ~~~
3977 /// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
3978 /// - `LocalEntry$` : return the current entry number in the current tree of a
3979 /// chain (`== GetTree()->GetReadEntry()`)
3980 /// - `Entries$` : return the total number of entries (== TTree::GetEntries())
3981 /// - `LocalEntries$` : return the total number of entries in the current tree
3982 /// of a chain (== GetTree()->TTree::GetEntries())
3983 /// - `Length$` : return the total number of element of this formula for this
3984 /// entry (`==TTreeFormula::GetNdata()`)
3985 /// - `Iteration$` : return the current iteration over this formula for this
3986 /// entry (i.e. varies from 0 to `Length$`).
3987 /// - `Length$(formula )` : return the total number of element of the formula
3988 /// given as a parameter.
3989 /// - `Sum$(formula )` : return the sum of the value of the elements of the
3990 /// formula given as a parameter. For example the mean for all the elements in
3991 /// one entry can be calculated with: `Sum$(formula )/Length$(formula )`
3992 /// - `Min$(formula )` : return the minimun (within one TTree entry) of the value of the
3993 /// elements of the formula given as a parameter.
3994 /// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
3995 /// elements of the formula given as a parameter.
3996 /// - `MinIf$(formula,condition)`
3997 /// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
3998 /// of the value of the elements of the formula given as a parameter
3999 /// if they match the condition. If no element matches the condition,
4000 /// the result is zero. To avoid the resulting peak at zero, use the
4001 /// pattern:
4002 /// ~~~ {.cpp}
4003 /// tree->Draw("MinIf$(formula,condition)","condition");
4004 /// ~~~
4005 /// which will avoid calculation `MinIf$` for the entries that have no match
4006 /// for the condition.
4007 /// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
4008 /// for the current iteration otherwise return the value of "alternate".
4009 /// For example, with arr1[3] and arr2[2]
4010 /// ~~~ {.cpp}
4011 /// tree->Draw("arr1+Alt$(arr2,0)");
4012 /// ~~~
4013 /// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
4014 /// Or with a variable size array arr3
4015 /// ~~~ {.cpp}
4016 /// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
4017 /// ~~~
4018 /// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
4019 /// As a comparison
4020 /// ~~~ {.cpp}
4021 /// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
4022 /// ~~~
4023 /// will draw the sum arr3 for the index 0 to 2 only if the
4024 /// actual_size_of_arr3 is greater or equal to 3.
4025 /// Note that the array in 'primary' is flattened/linearized thus using
4026 /// `Alt$` with multi-dimensional arrays of different dimensions in unlikely
4027 /// to yield the expected results. To visualize a bit more what elements
4028 /// would be matched by TTree::Draw, TTree::Scan can be used:
4029 /// ~~~ {.cpp}
4030 /// tree->Scan("arr1:Alt$(arr2,0)");
4031 /// ~~~
4032 /// will print on one line the value of arr1 and (arr2,0) that will be
4033 /// matched by
4034 /// ~~~ {.cpp}
4035 /// tree->Draw("arr1-Alt$(arr2,0)");
4036 /// ~~~
4037 /// The ternary operator is not directly supported in TTree::Draw however, to plot the
4038 /// equivalent of `var2<20 ? -99 : var1`, you can use:
4039 /// ~~~ {.cpp}
4040 /// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4041 /// ~~~
4042 ///
4043 /// ## Drawing a user function accessing the TTree data directly
4044 ///
4045 /// If the formula contains a file name, TTree::MakeProxy will be used
4046 /// to load and execute this file. In particular it will draw the
4047 /// result of a function with the same name as the file. The function
4048 /// will be executed in a context where the name of the branches can
4049 /// be used as a C++ variable.
4050 ///
4051 /// For example draw px using the file hsimple.root (generated by the
4052 /// hsimple.C tutorial), we need a file named hsimple.cxx:
4053 /// ~~~ {.cpp}
4054 /// double hsimple() {
4055 /// return px;
4056 /// }
4057 /// ~~~
4058 /// MakeProxy can then be used indirectly via the TTree::Draw interface
4059 /// as follow:
4060 /// ~~~ {.cpp}
4061 /// new TFile("hsimple.root")
4062 /// ntuple->Draw("hsimple.cxx");
4063 /// ~~~
4064 /// A more complete example is available in the tutorials directory:
4065 /// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4066 /// which reimplement the selector found in `h1analysis.C`
4067 ///
4068 /// The main features of this facility are:
4069 ///
4070 /// * on-demand loading of branches
4071 /// * ability to use the 'branchname' as if it was a data member
4072 /// * protection against array out-of-bound
4073 /// * ability to use the branch data as object (when the user code is available)
4074 ///
4075 /// See TTree::MakeProxy for more details.
4076 ///
4077 /// ## Making a Profile histogram
4078 ///
4079 /// In case of a 2-Dim expression, one can generate a TProfile histogram
4080 /// instead of a TH2F histogram by specifying option=prof or option=profs
4081 /// or option=profi or option=profg ; the trailing letter select the way
4082 /// the bin error are computed, See TProfile2D::SetErrorOption for
4083 /// details on the differences.
4084 /// The option=prof is automatically selected in case of y:x>>pf
4085 /// where pf is an existing TProfile histogram.
4086 ///
4087 /// ## Making a 2D Profile histogram
4088 ///
4089 /// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4090 /// instead of a TH3F histogram by specifying option=prof or option=profs.
4091 /// or option=profi or option=profg ; the trailing letter select the way
4092 /// the bin error are computed, See TProfile2D::SetErrorOption for
4093 /// details on the differences.
4094 /// The option=prof is automatically selected in case of z:y:x>>pf
4095 /// where pf is an existing TProfile2D histogram.
4096 ///
4097 /// ## Making a 5D plot using GL
4098 ///
4099 /// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4100 /// using OpenGL. See $ROOTSYS/tutorials/tree/staff.C as example.
4101 ///
4102 /// ## Making a parallel coordinates plot
4103 ///
4104 /// In case of a 2-Dim or more expression with the option=para, one can generate
4105 /// a parallel coordinates plot. With that option, the number of dimensions is
4106 /// arbitrary. Giving more than 4 variables without the option=para or
4107 /// option=candle or option=goff will produce an error.
4108 ///
4109 /// ## Making a candle sticks chart
4110 ///
4111 /// In case of a 2-Dim or more expression with the option=candle, one can generate
4112 /// a candle sticks chart. With that option, the number of dimensions is
4113 /// arbitrary. Giving more than 4 variables without the option=para or
4114 /// option=candle or option=goff will produce an error.
4115 ///
4116 /// ## Normalizing the output histogram to 1
4117 ///
4118 /// When option contains "norm" the output histogram is normalized to 1.
4119 ///
4120 /// ## Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4121 ///
4122 /// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4123 /// instead of histogramming one variable.
4124 /// If varexp0 has the form >>elist , a TEventList object named "elist"
4125 /// is created in the current directory. elist will contain the list
4126 /// of entry numbers satisfying the current selection.
4127 /// If option "entrylist" is used, a TEntryList object is created
4128 /// If the selection contains arrays, vectors or any container class and option
4129 /// "entrylistarray" is used, a TEntryListArray object is created
4130 /// containing also the subentries satisfying the selection, i.e. the indices of
4131 /// the branches which hold containers classes.
4132 /// Example:
4133 /// ~~~ {.cpp}
4134 /// tree.Draw(">>yplus","y>0")
4135 /// ~~~
4136 /// will create a TEventList object named "yplus" in the current directory.
4137 /// In an interactive session, one can type (after TTree::Draw)
4138 /// ~~~ {.cpp}
4139 /// yplus.Print("all")
4140 /// ~~~
4141 /// to print the list of entry numbers in the list.
4142 /// ~~~ {.cpp}
4143 /// tree.Draw(">>yplus", "y>0", "entrylist")
4144 /// ~~~
4145 /// will create a TEntryList object names "yplus" in the current directory
4146 /// ~~~ {.cpp}
4147 /// tree.Draw(">>yplus", "y>0", "entrylistarray")
4148 /// ~~~
4149 /// will create a TEntryListArray object names "yplus" in the current directory
4150 ///
4151 /// By default, the specified entry list is reset.
4152 /// To continue to append data to an existing list, use "+" in front
4153 /// of the list name;
4154 /// ~~~ {.cpp}
4155 /// tree.Draw(">>+yplus","y>0")
4156 /// ~~~
4157 /// will not reset yplus, but will enter the selected entries at the end
4158 /// of the existing list.
4159 ///
4160 /// ## Using a TEventList, TEntryList or TEntryListArray as Input
4161 ///
4162 /// Once a TEventList or a TEntryList object has been generated, it can be used as input
4163 /// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4164 /// current event list
4165 ///
4166 /// Example 1:
4167 /// ~~~ {.cpp}
4168 /// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4169 /// tree->SetEventList(elist);
4170 /// tree->Draw("py");
4171 /// ~~~
4172 /// Example 2:
4173 /// ~~~ {.cpp}
4174 /// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4175 /// tree->SetEntryList(elist);
4176 /// tree->Draw("py");
4177 /// ~~~
4178 /// If a TEventList object is used as input, a new TEntryList object is created
4179 /// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4180 /// for this transformation. This new object is owned by the chain and is deleted
4181 /// with it, unless the user extracts it by calling GetEntryList() function.
4182 /// See also comments to SetEventList() function of TTree and TChain.
4183 ///
4184 /// If arrays are used in the selection criteria and TEntryListArray is not used,
4185 /// all the entries that have at least one element of the array that satisfy the selection
4186 /// are entered in the list.
4187 ///
4188 /// Example:
4189 /// ~~~ {.cpp}
4190 /// tree.Draw(">>pyplus","fTracks.fPy>0");
4191 /// tree->SetEventList(pyplus);
4192 /// tree->Draw("fTracks.fPy");
4193 /// ~~~
4194 /// will draw the fPy of ALL tracks in event with at least one track with
4195 /// a positive fPy.
4196 ///
4197 /// To select only the elements that did match the original selection
4198 /// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4199 ///
4200 /// Example:
4201 /// ~~~ {.cpp}
4202 /// tree.Draw(">>pyplus","fTracks.fPy>0");
4203 /// pyplus->SetReapplyCut(kTRUE);
4204 /// tree->SetEventList(pyplus);
4205 /// tree->Draw("fTracks.fPy");
4206 /// ~~~
4207 /// will draw the fPy of only the tracks that have a positive fPy.
4208 ///
4209 /// To draw only the elements that match a selection in case of arrays,
4210 /// you can also use TEntryListArray (faster in case of a more general selection).
4211 ///
4212 /// Example:
4213 /// ~~~ {.cpp}
4214 /// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4215 /// tree->SetEntryList(pyplus);
4216 /// tree->Draw("fTracks.fPy");
4217 /// ~~~
4218 /// will draw the fPy of only the tracks that have a positive fPy,
4219 /// but without redoing the selection.
4220 ///
4221 /// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4222 ///
4223 /// ## How to obtain more info from TTree::Draw
4224 ///
4225 /// Once TTree::Draw has been called, it is possible to access useful
4226 /// information still stored in the TTree object via the following functions:
4227 ///
4228 /// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4229 /// - GetV1() // returns a pointer to the double array of V1
4230 /// - GetV2() // returns a pointer to the double array of V2
4231 /// - GetV3() // returns a pointer to the double array of V3
4232 /// - GetV4() // returns a pointer to the double array of V4
4233 /// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4234 ///
4235 /// where V1,V2,V3 correspond to the expressions in
4236 /// ~~~ {.cpp}
4237 /// TTree::Draw("V1:V2:V3:V4",selection);
4238 /// ~~~
4239 /// If the expression has more than 4 component use GetVal(index)
4240 ///
4241 /// Example:
4242 /// ~~~ {.cpp}
4243 /// Root > ntuple->Draw("py:px","pz>4");
4244 /// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4245 /// ntuple->GetV2(), ntuple->GetV1());
4246 /// Root > gr->Draw("ap"); //draw graph in current pad
4247 /// ~~~
4248 ///
4249 /// A more complete complete tutorial (treegetval.C) shows how to use the
4250 /// GetVal() method.
4251 ///
4252 /// creates a TGraph object with a number of points corresponding to the
4253 /// number of entries selected by the expression "pz>4", the x points of the graph
4254 /// being the px values of the Tree and the y points the py values.
4255 ///
4256 /// Important note: By default TTree::Draw creates the arrays obtained
4257 /// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4258 /// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4259 /// values calculated.
4260 /// By default fEstimate=1000000 and can be modified
4261 /// via TTree::SetEstimate. To keep in memory all the results (in case
4262 /// where there is only one result per entry), use
4263 /// ~~~ {.cpp}
4264 /// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4265 /// ~~~
4266 /// You must call SetEstimate if the expected number of selected rows
4267 /// you need to look at is greater than 1000000.
4268 ///
4269 /// You can use the option "goff" to turn off the graphics output
4270 /// of TTree::Draw in the above example.
4271 ///
4272 /// ## Automatic interface to TTree::Draw via the TTreeViewer
4273 ///
4274 /// A complete graphical interface to this function is implemented
4275 /// in the class TTreeViewer.
4276 /// To start the TTreeViewer, three possibilities:
4277 /// - select TTree context menu item "StartViewer"
4278 /// - type the command "TTreeViewer TV(treeName)"
4279 /// - execute statement "tree->StartViewer();"
4280 
4281 Long64_t TTree::Draw(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
4283  GetPlayer();
4284  if (fPlayer)
4285  return fPlayer->DrawSelect(varexp,selection,option,nentries,firstentry);
4286  return -1;
4287 }
4288 
4289 ////////////////////////////////////////////////////////////////////////////////
4290 /// Remove some baskets from memory.
4291 
4292 void TTree::DropBaskets()
4294  TBranch* branch = 0;
4296  for (Int_t i = 0; i < nb; ++i) {
4297  branch = (TBranch*) fBranches.UncheckedAt(i);
4298  branch->DropBaskets("all");
4299  }
4300 }
4301 
4302 ////////////////////////////////////////////////////////////////////////////////
4303 /// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4304 
4307  // Be careful not to remove current read/write buffers.
4308  Int_t ndrop = 0;
4309  Int_t nleaves = fLeaves.GetEntriesFast();
4310  for (Int_t i = 0; i < nleaves; ++i) {
4311  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4312  TBranch* branch = (TBranch*) leaf->GetBranch();
4313  Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4314  for (Int_t j = 0; j < nbaskets - 1; ++j) {
4315  if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4316  continue;
4317  }
4318  TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4319  if (basket) {
4320  ndrop += basket->DropBuffers();
4322  return;
4323  }
4324  }
4325  }
4326  }
4327 }
4328 
4329 ////////////////////////////////////////////////////////////////////////////////
4330 /// Fill all branches.
4331 ///
4332 /// This function loops on all the branches of this tree. For
4333 /// each branch, it copies to the branch buffer (basket) the current
4334 /// values of the leaves data types. If a leaf is a simple data type,
4335 /// a simple conversion to a machine independent format has to be done.
4336 ///
4337 /// This machine independent version of the data is copied into a
4338 /// basket (each branch has its own basket). When a basket is full
4339 /// (32k worth of data by default), it is then optionally compressed
4340 /// and written to disk (this operation is also called committing or
4341 /// 'flushing' the basket). The committed baskets are then
4342 /// immediately removed from memory.
4343 ///
4344 /// The function returns the number of bytes committed to the
4345 /// individual branches.
4346 ///
4347 /// If a write error occurs, the number of bytes returned is -1.
4348 ///
4349 /// If no data are written, because, e.g., the branch is disabled,
4350 /// the number of bytes returned is 0.
4351 ///
4352 /// __The baskets are flushed and the Tree header saved at regular intervals__
4353 ///
4354 /// At regular intervals, when the amount of data written so far is
4355 /// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4356 /// This makes future reading faster as it guarantees that baskets belonging to nearby
4357 /// entries will be on the same disk region.
4358 /// When the first call to flush the baskets happen, we also take this opportunity
4359 /// to optimize the baskets buffers.
4360 /// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4361 /// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4362 /// in case the program writing the Tree crashes.
4363 /// The decisions to FlushBaskets and Auto Save can be made based either on the number
4364 /// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4365 /// written (fAutoFlush and fAutoSave positive).
4366 /// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4367 /// base on the number of events written instead of the number of bytes written.
4368 ///
4369 /// Note that calling FlushBaskets too often increases the IO time.
4370 ///
4371 /// Note that calling AutoSave too often increases the IO time and also the file size.
4372 
4375  Int_t nbytes = 0;
4376  Int_t nerror = 0;
4378  if (nb == 1) {
4379  // Case of one single super branch. Automatically update
4380  // all the branch addresses if a new object was created.
4381  TBranch* branch = (TBranch*) fBranches.UncheckedAt(0);
4382  branch->UpdateAddress();
4383  }
4384  if (fBranchRef) {
4385  fBranchRef->Clear();
4386  }
4387  for (Int_t i = 0; i < nb; ++i) {
4388  // Loop over all branches, filling and accumulating bytes written and error counts.
4389  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
4390  if (branch->TestBit(kDoNotProcess)) {
4391  continue;
4392  }
4393  Int_t nwrite = branch->Fill();
4394  if (nwrite < 0) {
4395  if (nerror < 2) {
4396  Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4397  " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4398  " Instead of doing:\n"
4399  " TTree *T = new TTree(...)\n"
4400  " TFile *f = new TFile(...)\n"
4401  " you should do:\n"
4402  " TFile *f = new TFile(...)\n"
4403  " TTree *T = new TTree(...)",
4404  GetName(), branch->GetName(), nwrite,fEntries+1);
4405  } else {
4406  Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,fEntries+1);
4407  }
4408  ++nerror;
4409  } else {
4410  nbytes += nwrite;
4411  }
4412  }
4413  if (fBranchRef) {
4414  fBranchRef->Fill();
4415  }
4416  ++fEntries;
4417  if (fEntries > fMaxEntries) {
4418  KeepCircular();
4419  }
4420  if (gDebug > 0) printf("TTree::Fill - A: %d %lld %lld %lld %lld %lld %lld \n",
4422 
4423  if (fAutoFlush != 0 || fAutoSave != 0) {
4424  // Is it time to flush or autosave baskets?
4425  if (fFlushedBytes == 0) {
4426  // Decision can be based initially either on the number of bytes
4427  // or the number of entries written.
4428  if ((fAutoFlush<0 && fZipBytes > -fAutoFlush) ||
4429  (fAutoSave <0 && fZipBytes > -fAutoSave ) ||
4430  (fAutoFlush>0 && fEntries%TMath::Max((Long64_t)1,fAutoFlush) == 0) ||
4431  (fAutoSave >0 && fEntries%TMath::Max((Long64_t)1,fAutoSave) == 0) ) {
4432 
4433  //First call FlushBasket to make sure that fTotBytes is up to date.
4434  FlushBaskets();
4435  OptimizeBaskets(fTotBytes,1,"");
4436  if (gDebug > 0) Info("TTree::Fill","OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",fEntries,fZipBytes,fFlushedBytes);
4438  fAutoFlush = fEntries; // Use test on entries rather than bytes
4439 
4440  // subsequently in run
4441  if (fAutoSave < 0) {
4442  // Set fAutoSave to the largest integer multiple of
4443  // fAutoFlush events such that fAutoSave*fFlushedBytes
4444  // < (minus the input value of fAutoSave)
4445  if (fZipBytes != 0) {
4447  } else if (fTotBytes != 0) {
4449  } else {
4450  TBufferFile b(TBuffer::kWrite, 10000);
4451  TTree::Class()->WriteBuffer(b, (TTree*) this);
4452  Long64_t total = b.Length();
4454  }
4455  } else if(fAutoSave > 0) {
4457  }
4458  if (fAutoSave!=0 && fEntries >= fAutoSave) AutoSave(); // FlushBaskets not called in AutoSave
4459  if (gDebug > 0) Info("TTree::Fill","First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4460  }
4461  } else if (fNClusterRange && fAutoFlush && ( (fEntries-fClusterRangeEnd[fNClusterRange-1]) % fAutoFlush == 0) ) {
4462  if (fAutoSave != 0 && fEntries%fAutoSave == 0) {
4463  //We are at an AutoSave point. AutoSave flushes baskets and saves the Tree header
4464  AutoSave("flushbaskets");
4465  if (gDebug > 0) Info("TTree::Fill","AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n",fEntries,fZipBytes,fSavedBytes);
4466  } else {
4467  //We only FlushBaskets
4468  FlushBaskets();
4469  if (gDebug > 0) Info("TTree::Fill","FlushBasket called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",fEntries,fZipBytes,fFlushedBytes);
4470  }
4472  } else if (fNClusterRange == 0 && fEntries > 1 && fAutoFlush && fEntries%fAutoFlush == 0) {
4473  if (fAutoSave != 0 && fEntries%fAutoSave == 0) {
4474  //We are at an AutoSave point. AutoSave flushes baskets and saves the Tree header
4475  AutoSave("flushbaskets");
4476  if (gDebug > 0) Info("TTree::Fill","AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n",fEntries,fZipBytes,fSavedBytes);
4477  } else {
4478  //We only FlushBaskets
4479  FlushBaskets();
4480  if (gDebug > 0) Info("TTree::Fill","FlushBasket called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",fEntries,fZipBytes,fFlushedBytes);
4481  }
4483  }
4484  }
4485  // Check that output file is still below the maximum size.
4486  // If above, close the current file and continue on a new file.
4487  // Currently, the automatic change of file is restricted
4488  // to the case where the tree is in the top level directory.
4489  if (!fDirectory) {
4490  return nbytes;
4491  }
4492  TFile* file = fDirectory->GetFile();
4493  if (file && (file->GetEND() > fgMaxTreeSize)) {
4494  if (fDirectory == (TDirectory*) file) {
4495  ChangeFile(file);
4496  }
4497  }
4498  if (nerror) {
4499  return -1;
4500  }
4501  return nbytes;
4502 }
4503 
4504 ////////////////////////////////////////////////////////////////////////////////
4505 /// Search in the array for a branch matching the branch name,
4506 /// with the branch possibly expressed as a 'full' path name (with dots).
4507 
4508 static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4509  if (list==0 || branchname == 0 || branchname[0] == '\0') return 0;
4510 
4511  Int_t nbranches = list->GetEntries();
4512 
4513  UInt_t brlen = strlen(branchname);
4514 
4515  for(Int_t index = 0; index < nbranches; ++index) {
4516  TBranch *where = (TBranch*)list->UncheckedAt(index);
4517 
4518  const char *name = where->GetName();
4519  UInt_t len = strlen(name);
4520  if (len && name[len-1]==']') {
4521  const char *dim = strchr(name,'[');
4522  if (dim) {
4523  len = dim - name;
4524  }
4525  }
4526  if (brlen == len && strncmp(branchname,name,len)==0) {
4527  return where;
4528  }
4529  TBranch *next = 0;
4530  if ((brlen >= len) && (branchname[len] == '.')
4531  && strncmp(name, branchname, len) == 0) {
4532  // The prefix subbranch name match the branch name.
4533 
4534  next = where->FindBranch(branchname);
4535  if (!next) {
4536  next = where->FindBranch(branchname+len+1);
4537  }
4538  if (next) return next;
4539  }
4540  const char *dot = strchr((char*)branchname,'.');
4541  if (dot) {
4542  if (len==(size_t)(dot-branchname) &&
4543  strncmp(branchname,name,dot-branchname)==0 ) {
4544  return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4545  }
4546  }
4547  }
4548  return 0;
4549 }
4550 
4551 ////////////////////////////////////////////////////////////////////////////////
4552 /// Return the branch that correspond to the path 'branchname', which can
4553 /// include the name of the tree or the omitted name of the parent branches.
4554 /// In case of ambiguity, returns the first match.
4555 
4556 TBranch* TTree::FindBranch(const char* branchname)
4558  // We already have been visited while recursively looking
4559  // through the friends tree, let return
4561  return 0;
4562  }
4563 
4564  TBranch* branch = 0;
4565  // If the first part of the name match the TTree name, look for the right part in the
4566  // list of branches.
4567  // This will allow the branchname to be preceded by
4568  // the name of this tree.
4569  if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4570  branch = R__FindBranchHelper( GetListOfBranches(), branchname + fName.Length() + 1);
4571  if (branch) return branch;
4572  }
4573  // If we did not find it, let's try to find the full name in the list of branches.
4574  branch = R__FindBranchHelper(GetListOfBranches(), branchname);
4575  if (branch) return branch;
4576 
4577  // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4578  TIter next(GetListOfBranches());
4579  while ((branch = (TBranch*) next())) {
4580  TBranch* nestedbranch = branch->FindBranch(branchname);
4581  if (nestedbranch) {
4582  return nestedbranch;
4583  }
4584  }
4585 
4586  // Search in list of friends.
4587  if (!fFriends) {
4588  return 0;
4589  }
4590  TFriendLock lock(this, kFindBranch);
4591  TIter nextf(fFriends);
4592  TFriendElement* fe = 0;
4593  while ((fe = (TFriendElement*) nextf())) {
4594  TTree* t = fe->GetTree();
4595  if (!t) {
4596  continue;
4597  }
4598  // If the alias is present replace it with the real name.
4599  const char *subbranch = strstr(branchname, fe->GetName());
4600  if (subbranch != branchname) {
4601  subbranch = 0;
4602  }
4603  if (subbranch) {
4604  subbranch += strlen(fe->GetName());
4605  if (*subbranch != '.') {
4606  subbranch = 0;
4607  } else {
4608  ++subbranch;
4609  }
4610  }
4611  std::ostringstream name;
4612  if (subbranch) {
4613  name << t->GetName() << "." << subbranch;
4614  } else {
4615  name << branchname;
4616  }
4617  branch = t->FindBranch(name.str().c_str());
4618  if (branch) {
4619  return branch;
4620  }
4621  }
4622  return 0;
4623 }
4624 
4625 ////////////////////////////////////////////////////////////////////////////////
4626 /// Find leaf..
4627 
4628 TLeaf* TTree::FindLeaf(const char* searchname)
4630  // We already have been visited while recursively looking
4631  // through the friends tree, let's return.
4632  if (kFindLeaf & fFriendLockStatus) {
4633  return 0;
4634  }
4635 
4636  // This will allow the branchname to be preceded by
4637  // the name of this tree.
4638  char* subsearchname = (char*) strstr(searchname, GetName());
4639  if (subsearchname != searchname) {
4640  subsearchname = 0;
4641  }
4642  if (subsearchname) {
4643  subsearchname += strlen(GetName());
4644  if (*subsearchname != '.') {
4645  subsearchname = 0;
4646  } else {
4647  ++subsearchname;
4648  if (subsearchname[0]==0) {
4649  subsearchname = 0;
4650  }
4651  }
4652  }
4653 
4654  TString leafname;
4655  TString leaftitle;
4656  TString longname;
4657  TString longtitle;
4658 
4659  // For leaves we allow for one level up to be prefixed to the name.
4660  TIter next(GetListOfLeaves());
4661  TLeaf* leaf = 0;
4662  while ((leaf = (TLeaf*) next())) {
4663  leafname = leaf->GetName();
4664  Ssiz_t dim = leafname.First('[');
4665  if (dim >= 0) leafname.Remove(dim);
4666 
4667  if (leafname == searchname) {
4668  return leaf;
4669  }
4670  if (subsearchname && leafname == subsearchname) {
4671  return leaf;
4672  }
4673  // The TLeafElement contains the branch name
4674  // in its name, let's use the title.
4675  leaftitle = leaf->GetTitle();
4676  dim = leaftitle.First('[');
4677  if (dim >= 0) leaftitle.Remove(dim);
4678 
4679  if (leaftitle == searchname) {
4680  return leaf;
4681  }
4682  if (subsearchname && leaftitle == subsearchname) {
4683  return leaf;
4684  }
4685  TBranch* branch = leaf->GetBranch();
4686  if (branch) {
4687  longname.Form("%s.%s",branch->GetName(),leafname.Data());
4688  dim = longname.First('[');
4689  if (dim>=0) longname.Remove(dim);
4690  if (longname == searchname) {
4691  return leaf;
4692  }
4693  if (subsearchname && longname == subsearchname) {
4694  return leaf;
4695  }
4696  longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
4697  dim = longtitle.First('[');
4698  if (dim>=0) longtitle.Remove(dim);
4699  if (longtitle == searchname) {
4700  return leaf;
4701  }
4702  if (subsearchname && longtitle == subsearchname) {
4703  return leaf;
4704  }
4705  // The following is for the case where the branch is only
4706  // a sub-branch. Since we do not see it through
4707  // TTree::GetListOfBranches, we need to see it indirectly.
4708  // This is the less sturdy part of this search ... it may
4709  // need refining ...
4710  if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
4711  return leaf;
4712  }
4713  if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
4714  return leaf;
4715  }
4716  }
4717  }
4718  // Search in list of friends.
4719  if (!fFriends) {
4720  return 0;
4721  }
4722  TFriendLock lock(this, kFindLeaf);
4723  TIter nextf(fFriends);
4724  TFriendElement* fe = 0;
4725  while ((fe = (TFriendElement*) nextf())) {
4726  TTree* t = fe->GetTree();
4727  if (!t) {
4728  continue;
4729  }
4730  // If the alias is present replace it with the real name.
4731  subsearchname = (char*) strstr(searchname, fe->GetName());
4732  if (subsearchname != searchname) {
4733  subsearchname = 0;
4734  }
4735  if (subsearchname) {
4736  subsearchname += strlen(fe->GetName());
4737  if (*subsearchname != '.') {
4738  subsearchname = 0;
4739  } else {
4740  ++subsearchname;
4741  }
4742  }
4743  if (subsearchname) {
4744  leafname.Form("%s.%s",t->GetName(),subsearchname);
4745  } else {
4746  leafname = searchname;
4747  }
4748  leaf = t->FindLeaf(leafname);
4749  if (leaf) {
4750  return leaf;
4751  }
4752  }
4753  return 0;
4754 }
4755 
4756 ////////////////////////////////////////////////////////////////////////////////
4757 /// Fit a projected item(s) from a tree.
4758 ///
4759 /// funcname is a TF1 function.
4760 ///
4761 /// See TTree::Draw() for explanations of the other parameters.
4762 ///
4763 /// By default the temporary histogram created is called htemp.
4764 /// If varexp contains >>hnew , the new histogram created is called hnew
4765 /// and it is kept in the current directory.
4766 ///
4767 /// The function returns the number of selected entries.
4768 ///
4769 /// Example:
4770 /// ~~~ {.cpp}
4771 /// tree.Fit(pol4,"sqrt(x)>>hsqrt","y>0")
4772 /// ~~~
4773 /// will fit sqrt(x) and save the histogram as "hsqrt" in the current
4774 /// directory.
4775 ///
4776 /// See also TTree::UnbinnedFit
4777 ///
4778 /// ## Return status
4779 ///
4780 /// The function returns the status of the histogram fit (see TH1::Fit)
4781 /// If no entries were selected, the function returns -1;
4782 /// (i.e. fitResult is null if the fit is OK)
4783 
4784 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)
4786  GetPlayer();
4787  if (fPlayer) {
4788  return fPlayer->Fit(funcname, varexp, selection, option, goption, nentries, firstentry);
4789  }
4790  return -1;
4791 }
4792 
4793 ////////////////////////////////////////////////////////////////////////////////
4794 /// Write to disk all the basket that have not yet been individually written.
4795 ///
4796 /// Return the number of bytes written or -1 in case of write error.
4797 
4798 Int_t TTree::FlushBaskets() const
4800  if (!fDirectory) return 0;
4801  Int_t nbytes = 0;
4802  Int_t nerror = 0;
4803  TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
4804  Int_t nb = lb->GetEntriesFast();
4805  for (Int_t j = 0; j < nb; j++) {
4806  TBranch* branch = (TBranch*) lb->UncheckedAt(j);
4807  if (branch) {
4808  Int_t nwrite = branch->FlushBaskets();
4809  if (nwrite<0) {
4810  ++nerror;
4811  } else {
4812  nbytes += nwrite;
4813  }
4814  }
4815  }
4816  if (nerror) {
4817  return -1;
4818  } else {
4819  return nbytes;
4820  }
4821 }
4822 
4823 ////////////////////////////////////////////////////////////////////////////////
4824 /// Returns the expanded value of the alias. Search in the friends if any.
4825 
4826 const char* TTree::GetAlias(const char* aliasName) const
4828  // We already have been visited while recursively looking
4829  // through the friends tree, let's return.
4830  if (kGetAlias & fFriendLockStatus) {
4831  return 0;
4832  }
4833  if (fAliases) {
4834  TObject* alias = fAliases->FindObject(aliasName);
4835  if (alias) {
4836  return alias->GetTitle();
4837  }
4838  }
4839  if (!fFriends) {
4840  return 0;
4841  }
4842  TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
4843  TIter nextf(fFriends);
4844  TFriendElement* fe = 0;
4845  while ((fe = (TFriendElement*) nextf())) {
4846  TTree* t = fe->GetTree();
4847  if (t) {
4848  const char* alias = t->GetAlias(aliasName);
4849  if (alias) {
4850  return alias;
4851  }
4852  const char* subAliasName = strstr(aliasName, fe->GetName());
4853  if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
4854  alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
4855  if (alias) {
4856  return alias;
4857  }
4858  }
4859  }
4860  }
4861  return 0;
4862 }
4863 
4864 ////////////////////////////////////////////////////////////////////////////////
4865 /// Return pointer to the branch with the given name in this tree or its friends.
4866 
4867 TBranch* TTree::GetBranch(const char* name)
4869  if (name == 0) return 0;
4870 
4871  // We already have been visited while recursively
4872  // looking through the friends tree, let's return.
4873  if (kGetBranch & fFriendLockStatus) {
4874  return 0;
4875  }
4876 
4877  // Search using branches.
4879  for (Int_t i = 0; i < nb; i++) {
4880  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
4881  if (!strcmp(branch->GetName(), name)) {
4882  return branch;
4883  }
4884  TObjArray* lb = branch->GetListOfBranches();
4885  Int_t nb1 = lb->GetEntriesFast();
4886  for (Int_t j = 0; j < nb1; j++) {
4887  TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
4888  if (!strcmp(b1->GetName(), name)) {
4889  return b1;
4890  }
4891  TObjArray* lb1 = b1->GetListOfBranches();
4892  Int_t nb2 = lb1->GetEntriesFast();
4893  for (Int_t k = 0; k < nb2; k++) {
4894  TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
4895  if (!strcmp(b2->GetName(), name)) {
4896  return b2;
4897  }
4898  }
4899  }
4900  }
4901 
4902  // Search using leaves.
4903  TObjArray* leaves = GetListOfLeaves();
4904  Int_t nleaves = leaves->GetEntriesFast();
4905  for (Int_t i = 0; i < nleaves; i++) {
4906  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
4907  TBranch* branch = leaf->GetBranch();
4908  if (!strcmp(branch->GetName(), name)) {
4909  return branch;
4910  }
4911  }
4912 
4913  if (!fFriends) {
4914  return 0;
4915  }
4916 
4917  // Search in list of friends.
4918  TFriendLock lock(this, kGetBranch);
4919  TIter next(fFriends);
4920  TFriendElement* fe = 0;
4921  while ((fe = (TFriendElement*) next())) {
4922  TTree* t = fe->GetTree();
4923  if (t) {
4924  TBranch* branch = t->GetBranch(name);
4925  if (branch) {
4926  return branch;
4927  }
4928  }
4929  }
4930 
4931  // Second pass in the list of friends when
4932  // the branch name is prefixed by the tree name.
4933  next.Reset();
4934  while ((fe = (TFriendElement*) next())) {
4935  TTree* t = fe->GetTree();
4936  if (!t) {
4937  continue;
4938  }
4939  char* subname = (char*) strstr(name, fe->GetName());
4940  if (subname != name) {
4941  continue;
4942  }
4943  Int_t l = strlen(fe->GetName());
4944  subname += l;
4945  if (*subname != '.') {
4946  continue;
4947  }
4948  subname++;
4949  TBranch* branch = t->GetBranch(subname);
4950  if (branch) {
4951  return branch;
4952  }
4953  }
4954  return 0;
4955 }
4956 
4957 ////////////////////////////////////////////////////////////////////////////////
4958 /// Return status of branch with name branchname.
4959 ///
4960 /// - 0 if branch is not activated
4961 /// - 1 if branch is activated
4962 
4963 Bool_t TTree::GetBranchStatus(const char* branchname) const
4965  TBranch* br = const_cast<TTree*>(this)->GetBranch(branchname);
4966  if (br) {
4967  return br->TestBit(kDoNotProcess) == 0;
4968  }
4969  return 0;
4970 }
4971 
4972 ////////////////////////////////////////////////////////////////////////////////
4973 /// Static function returning the current branch style.
4974 ///
4975 /// - style = 0 old Branch
4976 /// - style = 1 new Bronch
4977 
4980  return fgBranchStyle;
4981 }
4982 
4983 ////////////////////////////////////////////////////////////////////////////////
4984 /// Used for automatic sizing of the cache.
4985 ///
4986 /// Estimates a suitable size for the tree cache based on AutoFlush.
4987 /// A cache sizing factor is taken from the configuration. If this yields zero
4988 /// and withDefault is true the historical algorithm for default size is used.
4989 
4990 Long64_t TTree::GetCacheAutoSize(Bool_t withDefault /* = kFALSE */ ) const
4992  const char *stcs;
4993  Double_t cacheFactor = 0.0;
4994  if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) {
4995  cacheFactor = gEnv->GetValue("TTreeCache.Size", 1.0);
4996  } else {
4997  cacheFactor = TString(stcs).Atof();
4998  }
4999 
5000  if (cacheFactor < 0.0) {
5001  // ignore negative factors
5002  cacheFactor = 0.0;
5003  }
5004 
5005  Long64_t cacheSize = 0;
5006 
5007  if (fAutoFlush < 0) cacheSize = Long64_t(-cacheFactor*fAutoFlush);
5008  else if (fAutoFlush == 0) cacheSize = 0;
5009  else cacheSize = Long64_t(cacheFactor*1.5*fAutoFlush*fZipBytes/(fEntries+1));
5010 
5011  if (cacheSize >= (INT_MAX / 4)) {
5012  cacheSize = INT_MAX / 4;
5013  }
5014 
5015  if (cacheSize < 0) {
5016  cacheSize = 0;
5017  }
5018 
5019  if (cacheSize == 0 && withDefault) {
5020  if (fAutoFlush < 0) cacheSize = -fAutoFlush;
5021  else if (fAutoFlush == 0) cacheSize = 0;
5022  else cacheSize = Long64_t(1.5*fAutoFlush*fZipBytes/(fEntries+1));
5023  }
5024 
5025  return cacheSize;
5026 }
5027 
5028 ////////////////////////////////////////////////////////////////////////////////
5029 /// Return an iterator over the cluster of baskets starting at firstentry.
5030 ///
5031 /// This iterator is not yet supported for TChain object.
5032 /// ~~~ {.cpp}
5033 /// TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
5034 /// Long64_t clusterStart;
5035 /// while( (clusterStart = clusterIter()) < tree->GetEntries() ) {
5036 /// printf("The cluster starts at %lld and ends at %lld (inclusive)\n",clusterStart,clusterIter.GetNextEntry()-1);
5037 /// }
5038 /// ~~~
5039 
5042  // create cache if wanted
5044 
5045  return TClusterIterator(this,firstentry);
5046 }
5047 
5048 ////////////////////////////////////////////////////////////////////////////////
5049 /// Return pointer to the current file.
5050 
5053  if (!fDirectory || fDirectory==gROOT) {
5054  return 0;
5055  }
5056  return fDirectory->GetFile();
5057 }
5058 
5059 ////////////////////////////////////////////////////////////////////////////////
5060 /// Return the number of entries matching the selection.
5061 /// Return -1 in case of errors.
5062 ///
5063 /// If the selection uses any arrays or containers, we return the number
5064 /// of entries where at least one element match the selection.
5065 /// GetEntries is implemented using the selector class TSelectorEntries,
5066 /// which can be used directly (see code in TTreePlayer::GetEntries) for
5067 /// additional option.
5068 /// If SetEventList was used on the TTree or TChain, only that subset
5069 /// of entries will be considered.
5070 
5071 Long64_t TTree::GetEntries(const char *selection)
5073  GetPlayer();
5074  if (fPlayer) {
5075  return fPlayer->GetEntries(selection);
5076  }
5077  return -1;
5078 }
5079 
5080 ////////////////////////////////////////////////////////////////////////////////
5081 /// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5082 /// any branch in the list of friend trees.
5083 
5086  if (fEntries) return fEntries;
5087  if (!fFriends) return 0;
5089  if (!fr) return 0;
5090  TTree *t = fr->GetTree();
5091  if (t==0) return 0;
5092  return t->GetEntriesFriend();
5093 }
5094 
5095 ////////////////////////////////////////////////////////////////////////////////
5096 /// Read all branches of entry and return total number of bytes read.
5097 ///
5098 /// - `getall = 0` : get only active branches
5099 /// - `getall = 1` : get all branches
5100 ///
5101 /// The function returns the number of bytes read from the input buffer.
5102 /// If entry does not exist the function returns 0.
5103 /// If an I/O error occurs, the function returns -1.
5104 ///
5105 /// If the Tree has friends, also read the friends entry.
5106 ///
5107 /// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5108 /// For example, if you have a Tree with several hundred branches, and you
5109 /// are interested only by branches named "a" and "b", do
5110 /// ~~~ {.cpp}
5111 /// mytree.SetBranchStatus("*",0); //disable all branches
5112 /// mytree.SetBranchStatus("a",1);
5113 /// mytree.SetBranchStatus("b",1);
5114 /// ~~~
5115 /// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5116 ///
5117 /// __WARNING!!__
5118 /// If your Tree has been created in split mode with a parent branch "parent.",
5119 /// ~~~ {.cpp}
5120 /// mytree.SetBranchStatus("parent",1);
5121 /// ~~~
5122 /// will not activate the sub-branches of "parent". You should do:
5123 /// ~~~ {.cpp}
5124 /// mytree.SetBranchStatus("parent*",1);
5125 /// ~~~
5126 /// Without the trailing dot in the branch creation you have no choice but to
5127 /// call SetBranchStatus explicitly for each of the sub branches.
5128 ///
5129 /// An alternative is to call directly
5130 /// ~~~ {.cpp}
5131 /// brancha.GetEntry(i)
5132 /// branchb.GetEntry(i);
5133 /// ~~~
5134 /// ## IMPORTANT NOTE
5135 ///
5136 /// By default, GetEntry reuses the space allocated by the previous object
5137 /// for each branch. You can force the previous object to be automatically
5138 /// deleted if you call mybranch.SetAutoDelete(kTRUE) (default is kFALSE).
5139 ///
5140 /// Example:
5141 ///
5142 /// Consider the example in $ROOTSYS/test/Event.h
5143 /// The top level branch in the tree T is declared with:
5144 /// ~~~ {.cpp}
5145 /// Event *event = 0; //event must be null or point to a valid object
5146 /// //it must be initialized
5147 /// T.SetBranchAddress("event",&event);
5148 /// ~~~
5149 /// When reading the Tree, one can choose one of these 3 options:
5150 ///
5151 /// ## OPTION 1
5152 ///
5153 /// ~~~ {.cpp}
5154 /// for (Long64_t i=0;i<nentries;i++) {
5155 /// T.GetEntry(i);
5156 /// // the object event has been filled at this point
5157 /// }
5158 /// ~~~
5159 /// The default (recommended). At the first entry an object of the class
5160 /// Event will be created and pointed by event. At the following entries,
5161 /// event will be overwritten by the new data. All internal members that are
5162 /// TObject* are automatically deleted. It is important that these members
5163 /// be in a valid state when GetEntry is called. Pointers must be correctly
5164 /// initialized. However these internal members will not be deleted if the
5165 /// characters "->" are specified as the first characters in the comment
5166 /// field of the data member declaration.
5167 ///
5168 /// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5169 /// In this case, it is assumed that the pointer is never null (case of
5170 /// pointer TClonesArray *fTracks in the Event example). If "->" is not
5171 /// specified, the pointer member is read via buf >> pointer. In this case
5172 /// the pointer may be null. Note that the option with "->" is faster to
5173 /// read or write and it also consumes less space in the file.
5174 ///
5175 /// ## OPTION 2
5176 ///
5177 /// The option AutoDelete is set
5178 /// ~~~ {.cpp}
5179 /// TBranch *branch = T.GetBranch("event");
5180 /// branch->SetAddress(&event);
5181 /// branch->SetAutoDelete(kTRUE);
5182 /// for (Long64_t i=0;i<nentries;i++) {
5183 /// T.GetEntry(i);
5184 /// // the object event has been filled at this point
5185 /// }
5186 /// ~~~
5187 /// In this case, at each iteration, the object event is deleted by GetEntry
5188 /// and a new instance of Event is created and filled.
5189 ///
5190 /// ## OPTION 3
5191 /// ~~~ {.cpp}
5192 /// Same as option 1, but you delete yourself the event.
5193 ///
5194 /// for (Long64_t i=0;i<nentries;i++) {
5195 /// delete event;
5196 /// event = 0; // EXTREMELY IMPORTANT
5197 /// T.GetEntry(i);
5198 /// // the object event has been filled at this point
5199 /// }
5200 /// ~~~
5201 /// It is strongly recommended to use the default option 1. It has the
5202 /// additional advantage that functions like TTree::Draw (internally calling
5203 /// TTree::GetEntry) will be functional even when the classes in the file are
5204 /// not available.
5205 ///
5206 /// Note: See the comments in TBranchElement::SetAddress() for the
5207 /// object ownership policy of the underlying (user) data.
5208 
5209 Int_t TTree::GetEntry(Long64_t entry, Int_t getall)
5211 
5212  // We already have been visited while recursively looking
5213  // through the friends tree, let return
5214  if (kGetEntry & fFriendLockStatus) return 0;
5215 
5216  if (entry < 0 || entry >= fEntries) return 0;
5217  Int_t i;
5218  Int_t nbytes = 0;
5219  fReadEntry = entry;
5220 
5221  // create cache if wanted
5223 
5224  Int_t nbranches = fBranches.GetEntriesFast();
5225  Int_t nb=0;
5226 
5227  auto seqprocessing = [&]() {
5228  TBranch *branch;
5229  for (i=0;i<nbranches;i++) {
5230  branch = (TBranch*)fBranches.UncheckedAt(i);
5231  nb = branch->GetEntry(entry, getall);
5232  if (nb < 0) break;
5233  nbytes += nb;
5234  }
5235  };
5236 
5237 #ifdef R__USE_IMT
5240 
5241  // Enable this IMT use case (activate its locks)
5243 
5244  Int_t errnb = 0;
5245  std::atomic<Int_t> pos(0);
5246  std::atomic<Int_t> nbpar(0);
5247  tbb::task_group g;
5248 
5249  for (i = 0; i < nbranches; i++) {
5250  g.run([&]() {
5251  // The branch to process is obtained when the task starts to run.
5252  // This way, since branches are sorted, we make sure that branches
5253  // leading to big tasks are processed first. If we assigned the
5254  // branch at task creation time, the scheduler would not necessarily
5255  // respect our sorting.
5256  Int_t j = pos.fetch_add(1);
5257 
5258  Int_t nbtask = 0;
5259  auto branch = fSortedBranches[j].second;
5260 
5261  if (gDebug > 0) {
5262  std::stringstream ss;
5263  ss << std::this_thread::get_id();
5264  Info("GetEntry", "[IMT] Thread %s", ss.str().c_str());
5265  Info("GetEntry", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5266  }
5267 
5268  std::chrono::time_point<std::chrono::system_clock> start, end;
5269 
5270  start = std::chrono::system_clock::now();
5271  nbtask = branch->GetEntry(entry, getall);
5272  end = std::chrono::system_clock::now();
5273 
5274  Long64_t tasktime = (Long64_t)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
5275  fSortedBranches[j].first += tasktime;
5276 
5277  if (nbtask < 0) errnb = nbtask;
5278  else nbpar += nbtask;
5279  });
5280  }
5281  g.wait();
5282 
5283  if (errnb < 0) {
5284  nb = errnb;
5285  }
5286  else {
5287  // Save the number of bytes read by the tasks
5288  nbytes = nbpar;
5289 
5290  // Re-sort branches if necessary
5294  }
5295  }
5296  }
5297  else {
5298  seqprocessing();
5299  }
5300 #else
5301  seqprocessing();
5302 #endif
5303  if (nb < 0) return nb;
5304 
5305  // GetEntry in list of friends
5306  if (!fFriends) return nbytes;
5307  TFriendLock lock(this,kGetEntry);
5308  TIter nextf(fFriends);
5309  TFriendElement *fe;
5310  while ((fe = (TFriendElement*)nextf())) {
5311  TTree *t = fe->GetTree();
5312  if (t) {
5314  nb = t->GetEntry(t->GetReadEntry(),getall);
5315  } else {
5316  if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5317  nb = t->GetEntry(t->GetReadEntry(),getall);
5318  } else nb = 0;
5319  }
5320  if (nb < 0) return nb;
5321  nbytes += nb;
5322  }
5323  }
5324  return nbytes;
5325 }
5326 
5327 ////////////////////////////////////////////////////////////////////////////////
5328 /// Initializes the vector of top-level branches and sorts it by branch size.
5329 
5332  Int_t nbranches = fBranches.GetEntriesFast();
5333  for (Int_t i = 0; i < nbranches; i++) {
5334  Long64_t bbytes = 0;
5335  TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5336  if (branch) bbytes = branch->GetTotBytes("*");
5337  fSortedBranches.emplace_back(bbytes, branch);
5338  }
5339 
5340  std::sort(fSortedBranches.begin(),
5341  fSortedBranches.end(),
5342  [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5343  return a.first > b.first;
5344  });
5345 
5346  for (Int_t i = 0; i < nbranches; i++) {
5347  fSortedBranches[i].first = 0LL;
5348  }
5349 }
5350 
5351 ////////////////////////////////////////////////////////////////////////////////
5352 /// Sorts top-level branches by the last average task time recorded per branch.
5353 
5356  Int_t nbranches = fBranches.GetEntriesFast();
5357  for (Int_t i = 0; i < nbranches; i++) {
5358  fSortedBranches[i].first *= kNEntriesResortInv;
5359  }
5360 
5361  std::sort(fSortedBranches.begin(),
5362  fSortedBranches.end(),
5363  [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5364  return a.first > b.first;
5365  });
5366 
5367  for (Int_t i = 0; i < nbranches; i++) {
5368  fSortedBranches[i].first = 0LL;
5369  }
5370 }
5371 
5372 ////////////////////////////////////////////////////////////////////////////////
5373 ///Returns the entry list, set to this tree
5374 
5377  return fEntryList;
5378 }
5379 
5380 ////////////////////////////////////////////////////////////////////////////////
5381 /// Return entry number corresponding to entry.
5382 ///
5383 /// if no TEntryList set returns entry
5384 /// else returns the entry number corresponding to the list index=entry
5385 
5388  if (!fEntryList) {
5389  return entry;
5390  }
5391 
5392  return fEntryList->GetEntry(entry);
5393 }
5394 
5395 ////////////////////////////////////////////////////////////////////////////////
5396 /// Return entry number corresponding to major and minor number.
5397 /// Note that this function returns only the entry number, not the data
5398 /// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5399 /// the BuildIndex function has created a table of Long64_t* of sorted values
5400 /// corresponding to val = major<<31 + minor;
5401 /// The function performs binary search in this sorted table.
5402 /// If it finds a pair that matches val, it returns directly the
5403 /// index in the table.
5404 /// If an entry corresponding to major and minor is not found, the function
5405 /// returns the index of the major,minor pair immediately lower than the
5406 /// requested value, ie it will return -1 if the pair is lower than
5407 /// the first entry in the index.
5408 ///
5409 /// See also GetEntryNumberWithIndex
5410 
5413  if (!fTreeIndex) {
5414  return -1;
5415  }
5416  return fTreeIndex->GetEntryNumberWithBestIndex(major, minor);
5417 }
5418 
5419 ////////////////////////////////////////////////////////////////////////////////
5420 /// Return entry number corresponding to major and minor number.
5421 /// Note that this function returns only the entry number, not the data
5422 /// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5423 /// the BuildIndex function has created a table of Long64_t* of sorted values
5424 /// corresponding to val = major<<31 + minor;
5425 /// The function performs binary search in this sorted table.
5426 /// If it finds a pair that matches val, it returns directly the
5427 /// index in the table, otherwise it returns -1.
5428 ///
5429 /// See also GetEntryNumberWithBestIndex
5430 
5433  if (!fTreeIndex) {
5434  return -1;
5435  }
5436  return fTreeIndex->GetEntryNumberWithIndex(major, minor);
5437 }
5438 
5439 ////////////////////////////////////////////////////////////////////////////////
5440 /// Read entry corresponding to major and minor number.
5441 ///
5442 /// The function returns the total number of bytes read.
5443 /// If the Tree has friend trees, the corresponding entry with
5444 /// the index values (major,minor) is read. Note that the master Tree
5445 /// and its friend may have different entry serial numbers corresponding
5446 /// to (major,minor).
5447 
5450  // We already have been visited while recursively looking
5451  // through the friends tree, let's return.
5453  return 0;
5454  }
5455  Long64_t serial = GetEntryNumberWithIndex(major, minor);
5456  if (serial < 0) {
5457  return -1;
5458  }
5459  // create cache if wanted
5461 
5462  Int_t i;
5463  Int_t nbytes = 0;
5464  fReadEntry = serial;
5465  TBranch *branch;
5466  Int_t nbranches = fBranches.GetEntriesFast();
5467  Int_t nb;
5468  for (i = 0; i < nbranches; ++i) {
5469  branch = (TBranch*)fBranches.UncheckedAt(i);
5470  nb = branch->GetEntry(serial);
5471  if (nb < 0) return nb;
5472  nbytes += nb;
5473  }
5474  // GetEntry in list of friends
5475  if (!fFriends) return nbytes;
5476  TFriendLock lock(this,kGetEntryWithIndex);
5477  TIter nextf(fFriends);
5478  TFriendElement* fe = 0;
5479  while ((fe = (TFriendElement*) nextf())) {
5480  TTree *t = fe->GetTree();
5481  if (t) {
5482  serial = t->GetEntryNumberWithIndex(major,minor);
5483  if (serial <0) return -nbytes;
5484  nb = t->GetEntry(serial);
5485  if (nb < 0) return nb;
5486  nbytes += nb;
5487  }
5488  }
5489  return nbytes;
5490 }
5491 
5492 ////////////////////////////////////////////////////////////////////////////////
5493 /// Return a pointer to the TTree friend whose name or alias is 'friendname.
5494 
5495 TTree* TTree::GetFriend(const char *friendname) const
5497 
5498  // We already have been visited while recursively
5499  // looking through the friends tree, let's return.
5500  if (kGetFriend & fFriendLockStatus) {
5501  return 0;
5502  }
5503  if (!fFriends) {
5504  return 0;
5505  }
5506  TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
5507  TIter nextf(fFriends);
5508  TFriendElement* fe = 0;
5509  while ((fe = (TFriendElement*) nextf())) {
5510  if (strcmp(friendname,fe->GetName())==0
5511  || strcmp(friendname,fe->GetTreeName())==0) {
5512  return fe->GetTree();
5513  }
5514  }
5515  // After looking at the first level,
5516  // let's see if it is a friend of friends.
5517  nextf.Reset();
5518  fe = 0;
5519  while ((fe = (TFriendElement*) nextf())) {
5520  TTree *res = fe->GetTree()->GetFriend(friendname);
5521  if (res) {
5522  return res;
5523  }
5524  }
5525  return 0;
5526 }
5527 
5528 ////////////////////////////////////////////////////////////////////////////////
5529 /// If the 'tree' is a friend, this method returns its alias name.
5530 ///
5531 /// This alias is an alternate name for the tree.
5532 ///
5533 /// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
5534 /// to specify in which particular tree the branch or leaf can be found if
5535 /// the friend trees have branches or leaves with the same name as the master
5536 /// tree.
5537 ///
5538 /// It can also be used in conjunction with an alias created using
5539 /// TTree::SetAlias in a TTreeFormula, e.g.:
5540 /// ~~~ {.cpp}
5541 /// maintree->Draw("treealias.fPx - treealias.myAlias");
5542 /// ~~~
5543 /// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
5544 /// was created using TTree::SetAlias on the friend tree.
5545 ///
5546 /// However, note that 'treealias.myAlias' will be expanded literally,
5547 /// without remembering that it comes from the aliased friend and thus
5548 /// the branch name might not be disambiguated properly, which means
5549 /// that you may not be able to take advantage of this feature.
5550 ///
5551 
5552 const char* TTree::GetFriendAlias(TTree* tree) const
5554  if ((tree == this) || (tree == GetTree())) {
5555  return 0;
5556  }
5557 
5558  // We already have been visited while recursively
5559  // looking through the friends tree, let's return.
5561  return 0;
5562  }
5563  if (!fFriends) {
5564  return 0;
5565  }
5566  TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
5567  TIter nextf(fFriends);
5568  TFriendElement* fe = 0;
5569  while ((fe = (TFriendElement*) nextf())) {
5570  TTree* t = fe->GetTree();
5571  if (t == tree) {
5572  return fe->GetName();
5573  }
5574  // Case of a chain:
5575  if (t->GetTree() == tree) {
5576  return fe->GetName();
5577  }
5578  }
5579  // After looking at the first level,
5580  // let's see if it is a friend of friends.
5581  nextf.Reset();
5582  fe = 0;
5583  while ((fe = (TFriendElement*) nextf())) {
5584  const char* res = fe->GetTree()->GetFriendAlias(tree);
5585  if (res) {
5586  return res;
5587  }
5588  }
5589  return 0;
5590 }
5591 
5592 ////////////////////////////////////////////////////////////////////////////////
5593 /// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
5594 
5597  return new TTreeFriendLeafIter(this, dir);
5598 }
5599 
5600 ////////////////////////////////////////////////////////////////////////////////
5601 /// Return pointer to the 1st Leaf named name in any Branch of this
5602 /// Tree or any branch in the list of friend trees.
5603 ///
5604 /// The leaf name can contain the name of a friend tree with the
5605 /// syntax: friend_dir_and_tree.full_leaf_name
5606 /// the friend_dir_and_tree can be of the form:
5607 /// ~~~ {.cpp}
5608 /// TDirectoryName/TreeName
5609 /// ~~~
5610 
5611 TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
5613  TLeaf *leaf = 0;
5614  if (branchname) {
5615  TBranch *branch = FindBranch(branchname);
5616  if (branch) {
5617  leaf = branch->GetLeaf(leafname);
5618  if (leaf) {
5619  return leaf;
5620  }
5621  }
5622  }
5623  TIter nextl(GetListOfLeaves());
5624  while ((leaf = (TLeaf*)nextl())) {
5625  if (strcmp(leaf->GetName(),leafname)) continue;
5626  if (branchname) {
5627  UInt_t nbch = strlen(branchname);
5628  TBranch *br = leaf->GetBranch();
5629  const char* brname = br->GetName();
5630  TBranch *mother = br->GetMother();
5631  if (strncmp(brname,branchname,nbch)) {
5632  if (mother != br) {
5633  const char *mothername = mother->GetName();
5634  UInt_t motherlen = strlen(mothername);
5635  if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
5636  // 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.
5637  if (strncmp(brname,branchname+motherlen+1,nbch-motherlen-1)) {
5638  // No it does not
5639  continue;
5640  } // else we have match so we can proceed.
5641  } else {
5642  // no match
5643  continue;
5644  }
5645  } else {
5646  continue;
5647  }
5648  }
5649  // The start of the branch name is identical to the content
5650  // of 'aname' before the first '/'.
5651  // Let's make sure that it is not longer (we are trying
5652  // to avoid having jet2/value match the branch jet23
5653  if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
5654  continue;
5655  }
5656  }
5657  return leaf;
5658  }
5659  if (!fFriends) return 0;
5660  TFriendLock lock(this,kGetLeaf);
5661  TIter next(fFriends);
5662  TFriendElement *fe;
5663  while ((fe = (TFriendElement*)next())) {
5664  TTree *t = fe->GetTree();
5665  if (t) {
5666  leaf = t->GetLeaf(leafname);
5667  if (leaf) return leaf;
5668  }
5669  }
5670 
5671  //second pass in the list of friends when the leaf name
5672  //is prefixed by the tree name
5673  TString strippedArg;
5674  next.Reset();
5675  while ((fe = (TFriendElement*)next())) {
5676  TTree *t = fe->GetTree();
5677  if (t==0) continue;
5678  char *subname = (char*)strstr(leafname,fe->GetName());
5679  if (subname != leafname) continue;
5680  Int_t l = strlen(fe->GetName());
5681  subname += l;
5682  if (*subname != '.') continue;
5683  subname++;
5684  strippedArg += subname;
5685  leaf = t->GetLeaf(branchname,subname);
5686  if (leaf) return leaf;
5687  }
5688  return 0;
5689 }
5690 
5691 ////////////////////////////////////////////////////////////////////////////////
5692 /// Return pointer to the 1st Leaf named name in any Branch of this
5693 /// Tree or any branch in the list of friend trees.
5694 ///
5695 /// The leaf name can contain the name of a friend tree with the
5696 /// syntax: friend_dir_and_tree.full_leaf_name
5697 /// the friend_dir_and_tree can be of the form:
5698 ///
5699 /// TDirectoryName/TreeName
5700 
5701 TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
5703  if (leafname == 0) return 0;
5704 
5705  // We already have been visited while recursively looking
5706  // through the friends tree, let return
5707  if (kGetLeaf & fFriendLockStatus) {
5708  return 0;
5709  }
5710 
5711  return GetLeafImpl(branchname,leafname);
5712 }
5713 
5714 ////////////////////////////////////////////////////////////////////////////////
5715 /// Return pointer to the 1st Leaf named name in any Branch of this
5716 /// Tree or any branch in the list of friend trees.
5717 ///
5718 /// aname may be of the form branchname/leafname
5719 
5720 TLeaf* TTree::GetLeaf(const char* aname)
5722  if (aname == 0) return 0;
5723 
5724  // We already have been visited while recursively looking
5725  // through the friends tree, let return
5726  if (kGetLeaf & fFriendLockStatus) {
5727  return 0;
5728  }
5729  char* slash = (char*) strrchr(aname, '/');
5730  char* name = 0;
5731  UInt_t nbch = 0;
5732  if (slash) {
5733  name = slash + 1;
5734  nbch = slash - aname;
5735  TString brname(aname,nbch);
5736  return GetLeafImpl(brname.Data(),name);
5737  } else {
5738  return GetLeafImpl(0,aname);
5739  }
5740 }
5741 
5742 ////////////////////////////////////////////////////////////////////////////////
5743 /// Return maximum of column with name columname.
5744 /// if the Tree has an associated TEventList or TEntryList, the maximum
5745 /// is computed for the entries in this list.
5746 
5747 Double_t TTree::GetMaximum(const char* columname)
5749  TLeaf* leaf = this->GetLeaf(columname);
5750  if (!leaf) {
5751  return 0;
5752  }
5753 
5754  // create cache if wanted
5756 
5757  TBranch* branch = leaf->GetBranch();
5758  Double_t cmax = -DBL_MAX;
5759  for (Long64_t i = 0; i < fEntries; ++i) {
5760  Long64_t entryNumber = this->GetEntryNumber(i);
5761  if (entryNumber < 0) break;
5762  branch->GetEntry(entryNumber);
5763  for (Int_t j = 0; j < leaf->GetLen(); ++j) {
5764  Double_t val = leaf->GetValue(j);
5765  if (val > cmax) {
5766  cmax = val;
5767  }
5768  }
5769  }
5770  return cmax;
5771 }
5772 
5773 ////////////////////////////////////////////////////////////////////////////////
5774 /// Static function which returns the tree file size limit in bytes.
5775 
5778  return fgMaxTreeSize;
5779 }
5780 
5781 ////////////////////////////////////////////////////////////////////////////////
5782 /// Return minimum of column with name columname.
5783 /// if the Tree has an associated TEventList or TEntryList, the minimum
5784 /// is computed for the entries in this list.
5785 
5786 Double_t TTree::GetMinimum(const char* columname)
5788  TLeaf* leaf = this->GetLeaf(columname);
5789  if (!leaf) {
5790  return 0;
5791  }
5792 
5793  // create cache if wanted
5795 
5796  TBranch* branch = leaf->GetBranch();
5797  Double_t cmin = DBL_MAX;
5798  for (Long64_t i = 0; i < fEntries; ++i) {
5799  Long64_t entryNumber = this->GetEntryNumber(i);
5800  if (entryNumber < 0) break;
5801  branch->GetEntry(entryNumber);
5802  for (Int_t j = 0;j < leaf->GetLen(); ++j) {
5803  Double_t val = leaf->GetValue(j);
5804  if (val < cmin) {
5805  cmin = val;
5806  }
5807  }
5808  }
5809  return cmin;
5810 }
5811 
5812 ////////////////////////////////////////////////////////////////////////////////
5813 /// Load the TTreePlayer (if not already done).
5814 
5817  if (fPlayer) {
5818  return fPlayer;
5819  }
5821  return fPlayer;
5822 }
5823 
5824 ////////////////////////////////////////////////////////////////////////////////
5825 /// Find and return the TTreeCache registered with the file and which may
5826 /// contain branches for us. If create is true and there is no cache
5827 /// a new cache is created with default size.
5828 
5829 TTreeCache *TTree::GetReadCache(TFile *file, Bool_t create /* = kFALSE */ )
5831  TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
5832  if (pe && pe->GetTree() != this) pe = 0;
5833  if (create && !pe) {
5835  pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
5836  if (pe && pe->GetTree() != this) pe = 0;
5837  }
5838  return pe;
5839 }
5840 
5841 ////////////////////////////////////////////////////////////////////////////////
5842 /// Return a pointer to the list containing user objects associated to this tree.
5843 ///
5844 /// The list is automatically created if it does not exist.
5845 ///
5846 /// WARNING: By default the TTree destructor will delete all objects added
5847 /// to this list. If you do not want these objects to be deleted,
5848 /// call:
5849 ///
5850 /// mytree->GetUserInfo()->Clear();
5851 ///
5852 /// before deleting the tree.
5853 
5856  if (!fUserInfo) {
5857  fUserInfo = new TList();
5858  fUserInfo->SetName("UserInfo");
5859  }
5860  return fUserInfo;
5861 }
5862 
5863 ////////////////////////////////////////////////////////////////////////////////
5864 /// Appends the cluster range information stored in 'fromtree' to this tree,
5865 /// including the value of fAutoFlush.
5866 ///
5867 /// This is used when doing a fast cloning (by TTreeCloner).
5868 /// See also fAutoFlush and fAutoSave if needed.
5869 
5870 void TTree::ImportClusterRanges(TTree *fromtree)
5872  Long64_t autoflush = fromtree->GetAutoFlush();
5873  if (fNClusterRange || fromtree->fNClusterRange) {
5874  Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
5875  if (newsize > fMaxClusterRange) {
5876  if (fMaxClusterRange) {
5878  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
5880  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
5881  fMaxClusterRange = newsize;
5882  } else {
5883  fMaxClusterRange = newsize;
5886  }
5887  }
5890  ++fNClusterRange;
5891  for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
5893  fClusterSize[fNClusterRange] = fromtree->fClusterSize[i];
5894  ++fNClusterRange;
5895  }
5896  fAutoFlush = autoflush;
5897  } else {
5898  SetAutoFlush( autoflush );
5899  }
5900  Long64_t autosave = GetAutoSave();
5901  if (autoflush > 0 && autosave > 0) {
5902  SetAutoSave( autoflush*(autosave/autoflush) );
5903  }
5904 }
5905 
5906 ////////////////////////////////////////////////////////////////////////////////
5907 /// Keep a maximum of fMaxEntries in memory.
5908 
5909 void TTree::KeepCircular()
5912  Long64_t maxEntries = fMaxEntries - (fMaxEntries / 10);
5913  for (Int_t i = 0; i < nb; ++i) {
5914  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
5915  branch->KeepCircular(maxEntries);
5916  }
5917  if (fNClusterRange) {
5918  Long64_t entriesOffset = fEntries - maxEntries;
5919  Int_t oldsize = fNClusterRange;
5920  for(Int_t i = 0, j = 0; j < oldsize; ++j) {
5921  if (fClusterRangeEnd[j] > entriesOffset) {
5922  fClusterRangeEnd[i] = fClusterRangeEnd[j] - entriesOffset;
5923  ++i;
5924  } else {
5925  --fNClusterRange;
5926  }
5927  }
5928  }
5929  fEntries = maxEntries;
5930  fReadEntry = -1;
5931 }
5932 
5933 ////////////////////////////////////////////////////////////////////////////////
5934 /// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
5935 ///
5936 /// If maxmemory is non null and positive SetMaxVirtualSize is called
5937 /// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
5938 /// The function returns the total number of baskets read into memory
5939 /// if negative an error occurred while loading the branches.
5940 /// This method may be called to force branch baskets in memory
5941 /// when random access to branch entries is required.
5942 /// If random access to only a few branches is required, you should
5943 /// call directly TBranch::LoadBaskets.
5944 
5947  if (maxmemory > 0) SetMaxVirtualSize(maxmemory);
5948 
5949  TIter next(GetListOfLeaves());
5950  TLeaf *leaf;
5951  Int_t nimported = 0;
5952  while ((leaf=(TLeaf*)next())) {
5953  nimported += leaf->GetBranch()->LoadBaskets();//break;
5954  }
5955  return nimported;
5956 }
5957 
5958 ////////////////////////////////////////////////////////////////////////////////
5959 /// Set current entry.
5960 ///
5961 /// Returns -2 if entry does not exist (just as TChain::LoadTree()).
5962 ///
5963 /// Note: This function is overloaded in TChain.
5964 ///
5965 
5968  // We already have been visited while recursively looking
5969  // through the friends tree, let return
5970  if (kLoadTree & fFriendLockStatus) {
5971  // We need to return a negative value to avoid a circular list of friend
5972  // to think that there is always an entry somewhere in the list.
5973  return -1;
5974  }
5975 
5976  if (fNotify) {
5977  if (fReadEntry < 0) {
5978  fNotify->Notify();
5979  }
5980  }
5981  fReadEntry = entry;
5982 
5983  Bool_t friendHasEntry = kFALSE;
5984  if (fFriends) {
5985  // Set current entry in friends as well.
5986  //
5987  // An alternative would move this code to each of the
5988  // functions calling LoadTree (and to overload a few more).
5989  Bool_t needUpdate = kFALSE;
5990  {
5991  // This scope is need to insure the lock is released at the right time
5992  TIter nextf(fFriends);
5993  TFriendLock lock(this, kLoadTree);
5994  TFriendElement* fe = 0;
5995  while ((fe = (TFriendElement*) nextf())) {
5997  // This friend element was added by the chain that owns this
5998  // tree, the chain will deal with loading the correct entry.
5999  continue;
6000  }
6001  TTree* friendTree = fe->GetTree();
6002  if (friendTree == 0) {
6003  // Somehow we failed to retrieve the friend TTree.
6004  } else if (friendTree->IsA() == TTree::Class()) {
6005  // Friend is actually a tree.
6006  if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6007  friendHasEntry = kTRUE;
6008  }
6009  } else {
6010  // Friend is actually a chain.
6011  // FIXME: This logic should be in the TChain override.
6012  Int_t oldNumber = friendTree->GetTreeNumber();
6013  if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6014  friendHasEntry = kTRUE;
6015  }
6016  Int_t newNumber = friendTree->GetTreeNumber();
6017  if (oldNumber != newNumber) {
6018  // We can not just compare the tree pointers because they could be reused.
6019  // So we compare the tree number instead.
6020  needUpdate = kTRUE;
6021  }
6022  }
6023  } // for each friend
6024  }
6025  if (needUpdate) {
6026  //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
6027  if (fPlayer) {
6029  }
6030  //Notify user if requested
6031  if (fNotify) {
6032  fNotify->Notify();
6033  }
6034  }
6035  }
6036 
6037  if ((fReadEntry >= fEntries) && !friendHasEntry) {
6038  fReadEntry = -1;
6039  return -2;
6040  }
6041  return fReadEntry;
6042 }
6043 
6044 ////////////////////////////////////////////////////////////////////////////////
6045 /// Load entry on behalf of our master tree, we may use an index.
6046 ///
6047 /// Called by LoadTree() when the masterTree looks for the entry
6048 /// number in a friend tree (us) corresponding to the passed entry
6049 /// number in the masterTree.
6050 ///
6051 /// If we have no index, our entry number and the masterTree entry
6052 /// number are the same.
6053 ///
6054 /// If we *do* have an index, we must find the (major, minor) value pair
6055 /// in masterTree to locate our corresponding entry.
6056 ///
6057 
6058 Long64_t TTree::LoadTreeFriend(Long64_t entry, TTree* masterTree)
6060  if (!fTreeIndex) {
6061  return LoadTree(entry);
6062  }
6063  return LoadTree(fTreeIndex->GetEntryNumberFriend(masterTree));
6064 }
6065 
6066 ////////////////////////////////////////////////////////////////////////////////
6067 /// Generate a skeleton analysis class for this tree.
6068 ///
6069 /// The following files are produced: classname.h and classname.C.
6070 /// If classname is 0, classname will be called "nameoftree".
6071 ///
6072 /// The generated code in classname.h includes the following:
6073 ///
6074 /// - Identification of the original tree and the input file name.
6075 /// - Definition of an analysis class (data members and member functions).
6076 /// - The following member functions:
6077 /// - constructor (by default opening the tree file),
6078 /// - GetEntry(Long64_t entry),
6079 /// - Init(TTree* tree) to initialize a new TTree,
6080 /// - Show(Long64_t entry) to read and dump entry.
6081 ///
6082 /// The generated code in classname.C includes only the main
6083 /// analysis function Loop.
6084 ///
6085 /// To use this function:
6086 ///
6087 /// - Open your tree file (eg: TFile f("myfile.root");)
6088 /// - T->MakeClass("MyClass");
6089 ///
6090 /// where T is the name of the TTree in file myfile.root,
6091 /// and MyClass.h, MyClass.C the name of the files created by this function.
6092 /// In a ROOT session, you can do:
6093 /// ~~~ {.cpp}
6094 /// root > .L MyClass.C
6095 /// root > MyClass* t = new MyClass;
6096 /// root > t->GetEntry(12); // Fill data members of t with entry number 12.
6097 /// root > t->Show(); // Show values of entry 12.
6098 /// root > t->Show(16); // Read and show values of entry 16.
6099 /// root > t->Loop(); // Loop on all entries.
6100 /// ~~~
6101 /// NOTE: Do not use the code generated for a single TTree which is part
6102 /// of a TChain to process that entire TChain. The maximum dimensions
6103 /// calculated for arrays on the basis of a single TTree from the TChain
6104 /// might be (will be!) too small when processing all of the TTrees in
6105 /// the TChain. You must use myChain.MakeClass() to generate the code,
6106 /// not myTree.MakeClass(...).
6107 
6108 Int_t TTree::MakeClass(const char* classname, Option_t* option)
6110  GetPlayer();
6111  if (!fPlayer) {
6112  return 0;
6113  }
6114  return fPlayer->MakeClass(classname, option);
6115 }
6116 
6117 ////////////////////////////////////////////////////////////////////////////////
6118 /// Generate a skeleton function for this tree.
6119 ///
6120 /// The function code is written on filename.
6121 /// If filename is 0, filename will be called nameoftree.C
6122 ///
6123 /// The generated code includes the following:
6124 /// - Identification of the original Tree and Input file name,
6125 /// - Opening the Tree file,
6126 /// - Declaration of Tree variables,
6127 /// - Setting of branches addresses,
6128 /// - A skeleton for the entry loop.
6129 ///
6130 /// To use this function:
6131 ///
6132 /// - Open your Tree file (eg: TFile f("myfile.root");)
6133 /// - T->MakeCode("MyAnalysis.C");
6134 ///
6135 /// where T is the name of the TTree in file myfile.root
6136 /// and MyAnalysis.C the name of the file created by this function.
6137 ///
6138 /// NOTE: Since the implementation of this function, a new and better
6139 /// function TTree::MakeClass() has been developed.
6140 
6141 Int_t TTree::MakeCode(const char* filename)
6143  Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
6144 
6145  GetPlayer();
6146  if (!fPlayer) return 0;
6147  return fPlayer->MakeCode(filename);
6148 }
6149 
6150 ////////////////////////////////////////////////////////////////////////////////
6151 /// Generate a skeleton analysis class for this Tree using TBranchProxy.
6152 ///
6153 /// TBranchProxy is the base of a class hierarchy implementing an
6154 /// indirect access to the content of the branches of a TTree.
6155 ///
6156 /// "proxyClassname" is expected to be of the form:
6157 /// ~~~ {.cpp}
6158 /// [path/]fileprefix
6159 /// ~~~
6160 /// The skeleton will then be generated in the file:
6161 /// ~~~ {.cpp}
6162 /// fileprefix.h
6163 /// ~~~
6164 /// located in the current directory or in 'path/' if it is specified.
6165 /// The class generated will be named 'fileprefix'
6166 ///
6167 /// "macrofilename" and optionally "cutfilename" are expected to point
6168 /// to source files which will be included by the generated skeleton.
6169 /// Method of the same name as the file(minus the extension and path)
6170 /// will be called by the generated skeleton's Process method as follow:
6171 /// ~~~ {.cpp}
6172 /// [if (cutfilename())] htemp->Fill(macrofilename());
6173 /// ~~~
6174 /// "option" can be used select some of the optional features during
6175 /// the code generation. The possible options are:
6176 ///
6177 /// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6178 ///
6179 /// 'maxUnrolling' controls how deep in the class hierarchy does the
6180 /// system 'unroll' classes that are not split. Unrolling a class
6181 /// allows direct access to its data members (this emulates the behavior
6182 /// of TTreeFormula).
6183 ///
6184 /// The main features of this skeleton are:
6185 ///
6186 /// * on-demand loading of branches
6187 /// * ability to use the 'branchname' as if it was a data member
6188 /// * protection against array out-of-bounds errors
6189 /// * ability to use the branch data as an object (when the user code is available)
6190 ///
6191 /// For example with Event.root, if
6192 /// ~~~ {.cpp}
6193 /// Double_t somePx = fTracks.fPx[2];
6194 /// ~~~
6195 /// is executed by one of the method of the skeleton,
6196 /// somePx will updated with the current value of fPx of the 3rd track.
6197 ///
6198 /// Both macrofilename and the optional cutfilename are expected to be
6199 /// the name of source files which contain at least a free standing
6200 /// function with the signature:
6201 /// ~~~ {.cpp}
6202 /// x_t macrofilename(); // i.e function with the same name as the file
6203 /// ~~~
6204 /// and
6205 /// ~~~ {.cpp}
6206 /// y_t cutfilename(); // i.e function with the same name as the file
6207 /// ~~~
6208 /// x_t and y_t needs to be types that can convert respectively to a double
6209 /// and a bool (because the skeleton uses:
6210 ///
6211 /// if (cutfilename()) htemp->Fill(macrofilename());
6212 ///
6213 /// These two functions are run in a context such that the branch names are
6214 /// available as local variables of the correct (read-only) type.
6215 ///
6216 /// Note that if you use the same 'variable' twice, it is more efficient
6217 /// to 'cache' the value. For example:
6218 /// ~~~ {.cpp}
6219 /// Int_t n = fEventNumber; // Read fEventNumber
6220 /// if (n<10 || n>10) { ... }
6221 /// ~~~
6222 /// is more efficient than
6223 /// ~~~ {.cpp}
6224 /// if (fEventNumber<10 || fEventNumber>10)
6225 /// ~~~
6226 /// Also, optionally, the generated selector will also call methods named
6227 /// macrofilename_methodname in each of 6 main selector methods if the method
6228 /// macrofilename_methodname exist (Where macrofilename is stripped of its
6229 /// extension).
6230 ///
6231 /// Concretely, with the script named h1analysisProxy.C,
6232 ///
6233 /// - The method calls the method (if it exist)
6234 /// - Begin -> void h1analysisProxy_Begin(TTree*);
6235 /// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6236 /// - Notify -> Bool_t h1analysisProxy_Notify();
6237 /// - Process -> Bool_t h1analysisProxy_Process(Long64_t);
6238 /// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6239 /// - Terminate -> void h1analysisProxy_Terminate();
6240 ///
6241 /// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6242 /// it is included before the declaration of the proxy class. This can
6243 /// be used in particular to insure that the include files needed by
6244 /// the macro file are properly loaded.
6245 ///
6246 /// The default histogram is accessible via the variable named 'htemp'.
6247 ///
6248 /// If the library of the classes describing the data in the branch is
6249 /// loaded, the skeleton will add the needed #include statements and
6250 /// give the ability to access the object stored in the branches.
6251 ///
6252 /// To draw px using the file hsimple.root (generated by the
6253 /// hsimple.C tutorial), we need a file named hsimple.cxx:
6254 /// ~~~ {.cpp}
6255 /// double hsimple() {
6256 /// return px;
6257 /// }
6258 /// ~~~
6259 /// MakeProxy can then be used indirectly via the TTree::Draw interface
6260 /// as follow:
6261 /// ~~~ {.cpp}
6262 /// new TFile("hsimple.root")
6263 /// ntuple->Draw("hsimple.cxx");
6264 /// ~~~
6265 /// A more complete example is available in the tutorials directory:
6266 /// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6267 /// which reimplement the selector found in h1analysis.C
6268 
6269 Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6271  GetPlayer();
6272  if (!fPlayer) return 0;
6273  return fPlayer->MakeProxy(proxyClassname,macrofilename,cutfilename,option,maxUnrolling);
6274 }
6275 
6276 ////////////////////////////////////////////////////////////////////////////////
6277 /// Generate skeleton selector class for this tree.
6278 ///
6279 /// The following files are produced: selector.h and selector.C.
6280 /// If selector is 0, the selector will be called "nameoftree".
6281 /// The option can be used to specify the branches that will have a data member.
6282 /// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6283 /// members and branch pointers instead of TTreeReaders).
6284 /// - If option is empty, readers will be generated for each leaf.
6285 /// - If option is "@", readers will be generated for the topmost branches.
6286 /// - Individual branches can also be picked by their name:
6287 /// - "X" generates readers for leaves of X.
6288 /// - "@X" generates a reader for X as a whole.
6289 /// - "@X;Y" generates a reader for X as a whole and also readers for the
6290 /// leaves of Y.
6291 /// - For further examples see the figure below.
6292 ///
6293 /// \image html ttree_makeselector_option_examples.png
6294 ///
6295 /// The generated code in selector.h includes the following:
6296 /// - Identification of the original Tree and Input file name
6297 /// - Definition of selector class (data and functions)
6298 /// - The following class functions:
6299 /// - constructor and destructor
6300 /// - void Begin(TTree *tree)
6301 /// - void SlaveBegin(TTree *tree)
6302 /// - void Init(TTree *tree)
6303 /// - Bool_t Notify()
6304 /// - Bool_t Process(Long64_t entry)
6305 /// - void Terminate()
6306 /// - void SlaveTerminate()
6307 ///
6308 /// The class selector derives from TSelector.
6309 /// The generated code in selector.C includes empty functions defined above.
6310 ///
6311 /// To use this function:
6312 ///
6313 /// - connect your Tree file (eg: `TFile f("myfile.root");`)
6314 /// - `T->MakeSelector("myselect");`
6315 ///
6316 /// where T is the name of the Tree in file myfile.root
6317 /// and myselect.h, myselect.C the name of the files created by this function.
6318 /// In a ROOT session, you can do:
6319 /// ~~~ {.cpp}
6320 /// root > T->Process("myselect.C")
6321 /// ~~~
6322 
6323 Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6325  TString opt(option);
6326  if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6327  return MakeClass(selector, "selector");
6328  } else {
6329  GetPlayer();
6330  if (!fPlayer) return 0;
6331  return fPlayer->MakeReader(selector, option);
6332  }
6333 }
6334 
6335 ////////////////////////////////////////////////////////////////////////////////
6336 /// Check if adding nbytes to memory we are still below MaxVirtualsize.
6337 
6340  if ((fTotalBuffers + nbytes) < fMaxVirtualSize) {
6341  return kFALSE;
6342  }
6343  return kTRUE;
6344 }
6345 
6346 ////////////////////////////////////////////////////////////////////////////////
6347 /// Static function merging the trees in the TList into a new tree.
6348 ///
6349 /// Trees in the list can be memory or disk-resident trees.
6350 /// The new tree is created in the current directory (memory if gROOT).
6351 
6352 TTree* TTree::MergeTrees(TList* li, Option_t* options)
6354  if (!li) return 0;
6355  TIter next(li);
6356  TTree *newtree = 0;
6357  TObject *obj;
6358 
6359  while ((obj=next())) {
6360  if (!obj->InheritsFrom(TTree::Class())) continue;
6361  TTree *tree = (TTree*)obj;
6362  Long64_t nentries = tree->GetEntries();
6363  if (nentries == 0) continue;
6364  if (!newtree) {
6365  newtree = (TTree*)tree->CloneTree();
6366  if (!newtree) continue;
6367 
6368  // Once the cloning is done, separate the trees,
6369  // to avoid as many side-effects as possible
6370  // The list of clones is guaranteed to exist since we
6371  // just cloned the tree.
6372  tree->GetListOfClones()->Remove(newtree);
6373  tree->ResetBranchAddresses();
6374  newtree->ResetBranchAddresses();
6375  continue;
6376  }
6377 
6378  newtree->CopyAddresses(tree);
6379 
6380  newtree->CopyEntries(tree,-1,options);
6381 
6382  tree->ResetBranchAddresses(); // Disconnect from new tree.
6383  }
6384  if (newtree && newtree->GetTreeIndex()) {
6385  newtree->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
6386  }
6387  return newtree;
6388 }
6389 
6390 ////////////////////////////////////////////////////////////////////////////////
6391 /// Merge the trees in the TList into this tree.
6392 ///
6393 /// Returns the total number of entries in the merged tree.
6394 
6397  if (!li) return 0;
6398  Long64_t storeAutoSave = fAutoSave;
6399  // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6400  // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6401  // Also since this is part of a merging operation, the output file is not as precious as in
6402  // the general case since the input file should still be around.
6403  fAutoSave = 0;
6404  TIter next(li);
6405  TTree *tree;
6406  while ((tree = (TTree*)next())) {
6407  if (tree==this) continue;
6408  if (!tree->InheritsFrom(TTree::Class())) {
6409  Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6410  fAutoSave = storeAutoSave;
6411  return -1;
6412  }
6413 
6414  Long64_t nentries = tree->GetEntries();
6415  if (nentries == 0) continue;
6416 
6417  CopyAddresses(tree);
6418 
6419  CopyEntries(tree,-1,options);
6420 
6421  tree->ResetBranchAddresses();
6422  }
6423  fAutoSave = storeAutoSave;
6424  return GetEntries();
6425 }
6426 
6427 ////////////////////////////////////////////////////////////////////////////////
6428 /// Merge the trees in the TList into this tree.
6429 /// If info->fIsFirst is true, first we clone this TTree info the directory
6430 /// info->fOutputDirectory and then overlay the new TTree information onto
6431 /// this TTree object (so that this TTree object is now the appropriate to
6432 /// use for further merging).
6433 ///
6434 /// Returns the total number of entries in the merged tree.
6435 
6438  const char *options = info ? info->fOptions.Data() : "";
6439  if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
6441  TTree *newtree = CloneTree(-1, options);
6442  if (newtree) {
6443  newtree->Write();
6444  delete newtree;
6445  }
6446  // Make sure things are really written out to disk before attempting any reading.
6447  info->fOutputDirectory->GetFile()->Flush();
6448  info->fOutputDirectory->ReadTObject(this,this->GetName());
6449  }
6450  if (!li) return 0;
6451  Long64_t storeAutoSave = fAutoSave;
6452  // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6453  // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6454  // Also since this is part of a merging operation, the output file is not as precious as in
6455  // the general case since the input file should still be around.
6456  fAutoSave = 0;
6457  TIter next(li);
6458  TTree *tree;
6459  while ((tree = (TTree*)next())) {
6460  if (tree==this) continue;
6461  if (!tree->InheritsFrom(TTree::Class())) {
6462  Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6463  fAutoSave = storeAutoSave;
6464  return -1;
6465  }
6466  // Copy MakeClass status.
6467  tree->SetMakeClass(fMakeClass);
6468 
6469  // Copy branch addresses.
6470  CopyAddresses(tree);
6471 
6472  CopyEntries(tree,-1,options);
6473 
6474  tree->ResetBranchAddresses();
6475  }
6476  fAutoSave = storeAutoSave;
6477  return GetEntries();
6478 }
6479 
6480 ////////////////////////////////////////////////////////////////////////////////
6481 /// Move a cache from a file to the current file in dir.
6482 /// if src is null no operation is done, if dir is null or there is no
6483 /// current file the cache is deleted.
6484 
6485 void TTree::MoveReadCache(TFile *src, TDirectory *dir)
6487  if (!src) return;
6488  TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : 0;
6489  if (src == dst) return;
6490 
6491  TTreeCache *pf = GetReadCache(src);
6492  if (dst) {
6493  src->SetCacheRead(0,this);
6494  dst->SetCacheRead(pf, this);
6495  } else {
6496  if (pf) {
6497  pf->WaitFinishPrefetch();
6498  }
6499  src->SetCacheRead(0,this);
6500  delete pf;
6501  }
6502 }
6503 
6504 ////////////////////////////////////////////////////////////////////////////////
6505 /// Function called when loading a new class library.
6506 
6509  TIter next(GetListOfLeaves());
6510  TLeaf* leaf = 0;
6511  while ((leaf = (TLeaf*) next())) {
6512  leaf->Notify();
6513  leaf->GetBranch()->Notify();
6514  }
6515  return kTRUE;
6516 }
6517 
6518 ////////////////////////////////////////////////////////////////////////////////
6519 /// This function may be called after having filled some entries in a Tree
6520 /// Using the information in the existing branch buffers, it will reassign
6521 /// new branch buffer sizes to optimize time and memory.
6522 ///
6523 /// The function computes the best values for branch buffer sizes such that
6524 /// the total buffer sizes is less than maxMemory and nearby entries written
6525 /// at the same time.
6526 /// In case the branch compression factor for the data written so far is less
6527 /// than compMin, the compression is disabled.
6528 ///
6529 /// if option ="d" an analysis report is printed.
6530 
6531 void TTree::OptimizeBaskets(ULong64_t maxMemory, Float_t minComp, Option_t *option)
6533  //Flush existing baskets if the file is writable
6534  if (this->GetDirectory()->IsWritable()) this->FlushBaskets();
6535 
6536  TString opt( option );
6537  opt.ToLower();
6538  Bool_t pDebug = opt.Contains("d");
6539  TObjArray *leaves = this->GetListOfLeaves();
6540  Int_t nleaves = leaves->GetEntries();
6541  Double_t treeSize = (Double_t)this->GetTotBytes();
6542 
6543  if (nleaves == 0 || treeSize == 0) {
6544  // We're being called too early, we really have nothing to do ...
6545  return;
6546  }
6547  Double_t aveSize = treeSize/nleaves;
6548  UInt_t bmin = 512;
6549  UInt_t bmax = 256000;
6550  Double_t memFactor = 1;
6551  Int_t i, oldMemsize,newMemsize,oldBaskets,newBaskets;
6552  i = oldMemsize = newMemsize = oldBaskets = newBaskets = 0;
6553 
6554  //we make two passes
6555  //one pass to compute the relative branch buffer sizes
6556  //a second pass to compute the absolute values
6557  for (Int_t pass =0;pass<2;pass++) {
6558  oldMemsize = 0; //to count size of baskets in memory with old buffer size
6559  newMemsize = 0; //to count size of baskets in memory with new buffer size
6560  oldBaskets = 0; //to count number of baskets with old buffer size
6561  newBaskets = 0; //to count number of baskets with new buffer size
6562  for (i=0;i<nleaves;i++) {
6563  TLeaf *leaf = (TLeaf*)leaves->At(i);
6564  TBranch *branch = leaf->GetBranch();
6565  Double_t totBytes = (Double_t)branch->GetTotBytes();
6566  Double_t idealFactor = totBytes/aveSize;
6567  UInt_t sizeOfOneEntry;
6568  if (branch->GetEntries() == 0) {
6569  // There is no data, so let's make a guess ...
6570  sizeOfOneEntry = aveSize;
6571  } else {
6572  sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
6573  }
6574  Int_t oldBsize = branch->GetBasketSize();
6575  oldMemsize += oldBsize;
6576  oldBaskets += 1+Int_t(totBytes/oldBsize);
6577  Int_t nb = branch->GetListOfBranches()->GetEntries();
6578  if (nb > 0) {
6579  newBaskets += 1+Int_t(totBytes/oldBsize);
6580  continue;
6581  }
6582  Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
6583  if (bsize < 0) bsize = bmax;
6584  if (bsize > bmax) bsize = bmax;
6585  UInt_t newBsize = UInt_t(bsize);
6586  if (pass) { // only on the second pass so that it doesn't interfere with scaling
6587  if (branch->GetBasket(0) != 0) {
6588  newBsize = newBsize + (branch->GetBasket(0)->GetNevBuf() * sizeof(Int_t) * 2); // make room for meta data
6589  }
6590  // We used ATLAS fully-split xAOD for testing, which is a rather unbalanced TTree, 10K branches,
6591  // with 8K having baskets smaller than 512 bytes. To achieve good I/O performance ATLAS uses auto-flush 100,
6592  // resulting in the smallest baskets being ~300-400 bytes, so this change increases their memory by about 8k*150B =~ 1MB,
6593  // at the same time it significantly reduces the number of total baskets because it ensures that all 100 entries can be
6594  // stored in a single basket (the old optimization tended to make baskets too small). In a toy example with fixed sized
6595  // structures we found a factor of 2 fewer baskets needed in the new scheme.
6596  // rounds up, increases basket size to ensure all entries fit into single basket as intended
6597  newBsize = newBsize - newBsize%512 + 512;
6598  }
6599  if (newBsize < sizeOfOneEntry) newBsize = sizeOfOneEntry;
6600  if (newBsize < bmin) newBsize = bmin;
6601  if (newBsize > 10000000) newBsize = bmax;
6602  if (pass) {
6603  if (pDebug) printf("Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
6604  branch->SetBasketSize(newBsize);
6605  }
6606  newMemsize += newBsize;
6607  // For this number to be somewhat accurate when newBsize is 'low'
6608  // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
6609  // not let it be lower than 100+TBranch::fEntryOffsetLen.
6610  newBaskets += 1+Int_t(totBytes/newBsize);
6611  if (pass == 0) continue;
6612  //Reset the compression level in case the compression factor is small
6613  Double_t comp = 1;
6614  if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
6615  if (comp > 1 && comp < minComp) {
6616  if (pDebug) printf("Disabling compression for branch : %s\n",branch->GetName());
6617  branch->SetCompressionSettings(0);
6618  }
6619  }
6620  // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
6621  memFactor = Double_t(maxMemory)/Double_t(newMemsize);
6622  if (memFactor > 100) memFactor = 100;
6623  Double_t bmin_new = bmin*memFactor;
6624  Double_t bmax_new = bmax*memFactor;
6625  static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
6626 
6627  // Really, really never go lower than 8 bytes (we use this number
6628  // so that the calculation of the number of basket is consistent
6629  // but in fact SetBasketSize will not let the size go below
6630  // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
6631  // (The 2nd part being a slight over estimate of the key length.
6632  static const UInt_t hardmin = 8;
6633  bmin = (bmin_new > hardmax) ? hardmax : ( bmin_new < hardmin ? hardmin : (UInt_t)bmin_new );
6634  bmax = (bmax_new > hardmax) ? bmin : (UInt_t)bmax_new;
6635  }
6636  if (pDebug) {
6637  printf("oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
6638  printf("oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
6639  }
6640 }
6641 
6642 ////////////////////////////////////////////////////////////////////////////////
6643 /// Interface to the Principal Components Analysis class.
6644 ///
6645 /// Create an instance of TPrincipal
6646 ///
6647 /// Fill it with the selected variables
6648 ///
6649 /// - if option "n" is specified, the TPrincipal object is filled with
6650 /// normalized variables.
6651 /// - If option "p" is specified, compute the principal components
6652 /// - If option "p" and "d" print results of analysis
6653 /// - If option "p" and "h" generate standard histograms
6654 /// - If option "p" and "c" generate code of conversion functions
6655 /// - return a pointer to the TPrincipal object. It is the user responsibility
6656 /// - to delete this object.
6657 /// - The option default value is "np"
6658 ///
6659 /// see TTree::Draw for explanation of the other parameters.
6660 ///
6661 /// The created object is named "principal" and a reference to it
6662 /// is added to the list of specials Root objects.
6663 /// you can retrieve a pointer to the created object via:
6664 /// ~~~ {.cpp}
6665 /// TPrincipal *principal =
6666 /// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
6667 /// ~~~
6668 
6669 TPrincipal* TTree::Principal(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
6671  GetPlayer();
6672  if (fPlayer) {
6673  return fPlayer->Principal(varexp, selection, option, nentries, firstentry);
6674  }
6675  return 0;
6676 }
6677 
6678 ////////////////////////////////////////////////////////////////////////////////
6679 /// Print a summary of the tree contents.
6680 ///
6681 /// - If option contains "all" friend trees are also printed.
6682 /// - If option contains "toponly" only the top level branches are printed.
6683 /// - If option contains "clusters" information about the cluster of baskets is printed.
6684 ///
6685 /// Wildcarding can be used to print only a subset of the branches, e.g.,
6686 /// `T.Print("Elec*")` will print all branches with name starting with "Elec".
6687 
6688 void TTree::Print(Option_t* option) const
6690  // We already have been visited while recursively looking
6691  // through the friends tree, let's return.
6692  if (kPrint & fFriendLockStatus) {
6693  return;
6694  }
6695  Int_t s = 0;
6696  Int_t skey = 0;
6697  if (fDirectory) {
6698  TKey* key = fDirectory->GetKey(GetName());
6699  if (key) {
6700  skey = key->GetKeylen();
6701  s = key->GetNbytes();
6702  }
6703  }
6704  Long64_t total = skey;
6705  if (fZipBytes > 0) {
6706  total += fTotBytes;
6707  }
6708  TBufferFile b(TBuffer::kWrite, 10000);
6709  TTree::Class()->WriteBuffer(b, (TTree*) this);
6710  total += b.Length();
6711  Long64_t file = fZipBytes + s;
6712  Float_t cx = 1;
6713  if (fZipBytes) {
6714  cx = (fTotBytes + 0.00001) / fZipBytes;
6715  }
6716  Printf("******************************************************************************");
6717  Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
6718  Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
6719  Printf("* : : Tree compression factor = %6.2f *", cx);
6720  Printf("******************************************************************************");
6721 
6722  if (strncmp(option,"clusterRange",strlen("clusters"))==0) {
6723  Printf("%-16s %-16s %-16s %5s",
6724  "Cluster Range #", "Entry Start", "Last Entry", "Size");
6725  Int_t index= 0;
6726  Long64_t clusterRangeStart = 0;
6727  if (fNClusterRange) {
6728  for( ; index < fNClusterRange; ++index) {
6729  Printf("%-16d %-16lld %-16lld %5lld",
6730  index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
6731  clusterRangeStart = fClusterRangeEnd[index] + 1;
6732  }
6733  }
6734  Printf("%-16d %-16lld %-16lld %5lld",
6735  index, clusterRangeStart, fEntries - 1, fAutoFlush);
6736  return;
6737  }
6738 
6739  Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
6740  Int_t l;
6741  TBranch* br = 0;
6742  TLeaf* leaf = 0;
6743  if (strstr(option, "toponly")) {
6744  Long64_t *count = new Long64_t[nl];
6745  Int_t keep =0;
6746  for (l=0;l<nl;l++) {
6747  leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
6748  br = leaf->GetBranch();
6749  if (strchr(br->GetName(),'.')) {
6750  count[l] = -1;
6751  count[keep] += br->GetZipBytes();
6752  } else {
6753  keep = l;
6754  count[keep] = br->GetZipBytes();
6755  }
6756  }
6757  for (l=0;l<nl;l++) {
6758  if (count[l] < 0) continue;
6759  leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
6760  br = leaf->GetBranch();
6761  printf("branch: %-20s %9lld\n",br->GetName(),count[l]);
6762  }
6763  delete [] count;
6764  } else {
6765  TString reg = "*";
6766  if (strlen(option) && strchr(option,'*')) reg = option;
6767  TRegexp re(reg,kTRUE);
6768  TIter next(const_cast<TTree*>(this)->GetListOfBranches());
6770  while ((br= (TBranch*)next())) {
6771  TString st = br->GetName();
6772  st.ReplaceAll("/","_");
6773  if (st.Index(re) == kNPOS) continue;
6774  br->Print(option);
6775  }
6776  }
6777 
6778  //print TRefTable (if one)
6779  if (fBranchRef) fBranchRef->Print(option);
6780 
6781  //print friends if option "all"
6782  if (!fFriends || !strstr(option,"all")) return;
6783  TIter nextf(fFriends);
6784  TFriendLock lock(const_cast<TTree*>(this),kPrint);
6785  TFriendElement *fr;
6786  while ((fr = (TFriendElement*)nextf())) {
6787  TTree * t = fr->GetTree();
6788  if (t) t->Print(option);
6789  }
6790 }
6791 
6792 ////////////////////////////////////////////////////////////////////////////////
6793 /// print statistics about the TreeCache for this tree, like
6794 /// ~~~ {.cpp}
6795 /// ******TreeCache statistics for file: cms2.root ******
6796 /// Reading 73921562 bytes in 716 transactions
6797 /// Average transaction = 103.242405 Kbytes
6798 /// Number of blocks in current cache: 202, total size : 6001193
6799 /// ~~~
6800 /// if option = "a" the list of blocks in the cache is printed
6801 
6802 void TTree::PrintCacheStats(Option_t* option) const
6804  TFile *f = GetCurrentFile();
6805  if (!f) return;
6806  TTreeCache *tc = (TTreeCache*)f->GetCacheRead(const_cast<TTree*>(this));
6807  if (tc) tc->Print(option);
6808 }
6809 
6810 ////////////////////////////////////////////////////////////////////////////////
6811 /// Process this tree executing the TSelector code in the specified filename.
6812 /// The return value is -1 in case of error and TSelector::GetStatus() in
6813 /// in case of success.
6814 ///
6815 /// The code in filename is loaded (interpreted or compiled, see below),
6816 /// filename must contain a valid class implementation derived from TSelector,
6817 /// where TSelector has the following member functions:
6818 ///
6819 /// - `Begin()`: called every time a loop on the tree starts,
6820 /// a convenient place to create your histograms.
6821 /// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
6822 /// slave servers.
6823 /// - `Process()`: called for each event, in this function you decide what
6824 /// to read and fill your histograms.
6825 /// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
6826 /// called only on the slave servers.
6827 /// - `Terminate()`: called at the end of the loop on the tree,
6828 /// a convenient place to draw/fit your histograms.
6829 ///
6830 /// If filename is of the form file.C, the file will be interpreted.
6831 ///
6832 /// If filename is of the form file.C++, the file file.C will be compiled
6833 /// and dynamically loaded.
6834 ///
6835 /// If filename is of the form file.C+, the file file.C will be compiled
6836 /// and dynamically loaded. At next call, if file.C is older than file.o
6837 /// and file.so, the file.C is not compiled, only file.so is loaded.
6838 ///
6839 /// ## NOTE1
6840 ///
6841 /// It may be more interesting to invoke directly the other Process function
6842 /// accepting a TSelector* as argument.eg
6843 /// ~~~ {.cpp}
6844 /// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
6845 /// selector->CallSomeFunction(..);
6846 /// mytree.Process(selector,..);
6847 /// ~~~
6848 /// ## NOTE2
6849 //
6850 /// One should not call this function twice with the same selector file
6851 /// in the same script. If this is required, proceed as indicated in NOTE1,
6852 /// by getting a pointer to the corresponding TSelector,eg
6853 ///
6854 /// ### workaround 1
6855 /// ~~~ {.cpp}
6856 /// void stubs1() {
6857 /// TSelector *selector = TSelector::GetSelector("h1test.C");
6858 /// TFile *f1 = new TFile("stubs_nood_le1.root");
6859 /// TTree *h1 = (TTree*)f1->Get("h1");
6860 /// h1->Process(selector);
6861 /// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
6862 /// TTree *h2 = (TTree*)f2->Get("h1");
6863 /// h2->Process(selector);
6864 /// }
6865 /// ~~~
6866 /// or use ACLIC to compile the selector
6867 ///
6868 /// ### workaround 2
6869 /// ~~~ {.cpp}
6870 /// void stubs2() {
6871 /// TFile *f1 = new TFile("stubs_nood_le1.root");
6872 /// TTree *h1 = (TTree*)f1->Get("h1");
6873 /// h1->Process("h1test.C+");
6874 /// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
6875 /// TTree *h2 = (TTree*)f2->Get("h1");
6876 /// h2->Process("h1test.C+");
6877 /// }
6878 /// ~~~
6879 
6880 Long64_t TTree::Process(const char* filename, Option_t* option, Long64_t nentries, Long64_t firstentry)
6882  GetPlayer();
6883  if (fPlayer) {
6884  return fPlayer->Process(filename, option, nentries, firstentry);
6885  }
6886  return -1;
6887 }
6888 
6889 ////////////////////////////////////////////////////////////////////////////////
6890 /// Process this tree executing the code in the specified selector.
6891 /// The return value is -1 in case of error and TSelector::GetStatus() in
6892 /// in case of success.
6893 ///
6894 /// The TSelector class has the following member functions:
6895 ///
6896 /// - `Begin()`: called every time a loop on the tree starts,
6897 /// a convenient place to create your histograms.
6898 /// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
6899 /// slave servers.
6900 /// - `Process()`: called for each event, in this function you decide what
6901 /// to read and fill your histograms.
6902 /// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
6903 /// called only on the slave servers.
6904 /// - `Terminate()`: called at the end of the loop on the tree,
6905 /// a convenient place to draw/fit your histograms.
6906 ///
6907 /// If the Tree (Chain) has an associated EventList, the loop is on the nentries
6908 /// of the EventList, starting at firstentry, otherwise the loop is on the
6909 /// specified Tree entries.
6910 
6911 Long64_t TTree::Process(TSelector* selector, Option_t* option, Long64_t nentries, Long64_t firstentry)
6913  GetPlayer();
6914  if (fPlayer) {
6915  return fPlayer->Process(selector, option, nentries, firstentry);
6916  }
6917  return -1;
6918 }
6919 
6920 ////////////////////////////////////////////////////////////////////////////////
6921 /// Make a projection of a tree using selections.
6922 ///
6923 /// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
6924 /// projection of the tree will be filled in histogram hname.
6925 /// Note that the dimension of hname must match with the dimension of varexp.
6926 ///
6927 
6928 Long64_t TTree::Project(const char* hname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
6930  TString var;
6931  var.Form("%s>>%s", varexp, hname);
6932  TString opt("goff");
6933  if (option) {
6934  opt.Form("%sgoff", option);
6935  }
6936  Long64_t nsel = Draw(var, selection, opt, nentries, firstentry);
6937  return nsel;
6938 }
6939 
6940 ////////////////////////////////////////////////////////////////////////////////
6941 /// Loop over entries and return a TSQLResult object containing entries following selection.
6942 
6943 TSQLResult* TTree::Query(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
6945  GetPlayer();
6946  if (fPlayer) {
6947  return fPlayer->Query(varexp, selection, option, nentries, firstentry);
6948  }
6949  return 0;
6950 }
6951 
6952 ////////////////////////////////////////////////////////////////////////////////
6953 /// Create or simply read branches from filename.
6954 ///
6955 /// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
6956 /// is given in the first line of the file with a syntax like
6957 /// ~~~ {.cpp}
6958 /// A/D:Table[2]/F:Ntracks/I:astring/C
6959 /// ~~~
6960 /// otherwise branchDescriptor must be specified with the above syntax.
6961 ///
6962 /// - If the type of the first variable is not specified, it is assumed to be "/F"
6963 /// - If the type of any other variable is not specified, the type of the previous
6964 /// variable is assumed. eg
6965 /// - `x:y:z` (all variables are assumed of type "F"
6966 /// - `x/D:y:z` (all variables are of type "D"
6967 /// - `x:y/D:z` (x is type "F", y and z of type "D"
6968 ///
6969 /// delimiter allows for the use of another delimiter besides whitespace.
6970 /// This provides support for direct import of common data file formats
6971 /// like csv. If delimiter != ' ' and branchDescriptor == "", then the
6972 /// branch description is taken from the first line in the file, but
6973 /// delimiter is used for the branch names tokenization rather than ':'.
6974 /// Note however that if the values in the first line do not use the
6975 /// /[type] syntax, all variables are assumed to be of type "F".
6976 /// If the filename ends with extensions .csv or .CSV and a delimiter is
6977 /// not specified (besides ' '), the delimiter is automatically set to ','.
6978 ///
6979 /// Lines in the input file starting with "#" are ignored. Leading whitespace
6980 /// for each column data is skipped. Empty lines are skipped.
6981 ///
6982 /// A TBranch object is created for each variable in the expression.
6983 /// The total number of rows read from the file is returned.
6984 ///
6985 /// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
6986 ///
6987 /// To fill a TTree with multiple input text files, proceed as indicated above
6988 /// for the first input file and omit the second argument for subsequent calls
6989 /// ~~~ {.cpp}
6990 /// T.ReadFile("file1.dat","branch descriptor");
6991 /// T.ReadFile("file2.dat");
6992 /// ~~~
6993 
6994 Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
6996  std::ifstream in;
6997  in.open(filename);
6998  if (!in.good()) {
6999  Error("ReadFile","Cannot open file: %s",filename);
7000  return 0;
7001  }
7002  const char* ext = strrchr(filename, '.');
7003  if(ext != NULL && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
7004  delimiter = ',';
7005  }
7006  return ReadStream(in, branchDescriptor, delimiter);
7007 }
7008 
7009 ////////////////////////////////////////////////////////////////////////////////
7010 /// Determine which newline this file is using.
7011 /// Return '\\r' for Windows '\\r\\n' as that already terminates.
7012 
7013 char TTree::GetNewlineValue(std::istream &inputStream)
7015  Long_t inPos = inputStream.tellg();
7016  char newline = '\n';
7017  while(1) {
7018  char c = 0;
7019  inputStream.get(c);
7020  if(!inputStream.good()) {
7021  Error("ReadStream","Error reading stream: no newline found.");
7022  return 0;
7023  }
7024  if(c == newline) break;
7025  if(c == '\r') {
7026  newline = '\r';
7027  break;
7028  }
7029  }
7030  inputStream.clear();
7031  inputStream.seekg(inPos);
7032  return newline;
7033 }
7034 
7035 ////////////////////////////////////////////////////////////////////////////////
7036 /// Create or simply read branches from an input stream.
7037 ///
7038 /// See reference information for TTree::ReadFile
7039 
7040 Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
7042  char newline = 0;
7043  std::stringstream ss;
7044  std::istream *inTemp;
7045  Long_t inPos = inputStream.tellg();
7046  if (!inputStream.good()) {
7047  Error("ReadStream","Error reading stream");
7048  return 0;
7049  }
7050  if (inPos == -1) {
7051  ss << std::cin.rdbuf();
7052  newline = GetNewlineValue(ss);
7053  inTemp = &ss;
7054  } else {
7055  newline = GetNewlineValue(inputStream);
7056  inTemp = &inputStream;
7057  }
7058  std::istream& in = *inTemp;
7059  Long64_t nlines = 0;
7060 
7061  TBranch *branch = 0;
7062  Int_t nbranches = fBranches.GetEntries();
7063  if (nbranches == 0) {
7064  char *bdname = new char[4000];
7065  char *bd = new char[100000];
7066  Int_t nch = 0;
7067  if (branchDescriptor) nch = strlen(branchDescriptor);
7068  // branch Descriptor is null, read its definition from the first line in the file
7069  if (!nch) {
7070  do {
7071  in.getline(bd, 100000, newline);
7072  if (!in.good()) {
7073  delete [] bdname;
7074  delete [] bd;
7075  Error("ReadStream","Error reading stream");
7076  return 0;
7077  }
7078  char *cursor = bd;
7079  while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
7080  ++cursor;
7081  }
7082  if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
7083  break;
7084  }
7085  } while (true);
7086  ++nlines;
7087  nch = strlen(bd);
7088  } else {
7089  strlcpy(bd,branchDescriptor,100000);
7090  }
7091 
7092  //parse the branch descriptor and create a branch for each element
7093  //separated by ":"
7094  void *address = &bd[90000];
7095  char *bdcur = bd;
7096  TString desc="", olddesc="F";
7097  char bdelim = ':';
7098  if(delimiter != ' ') {
7099  bdelim = delimiter;
7100  if (strchr(bdcur,bdelim)==0 && strchr(bdcur,':') != 0) {
7101  // revert to the default
7102  bdelim = ':';
7103  }
7104  }
7105  while (bdcur) {
7106  char *colon = strchr(bdcur,bdelim);
7107  if (colon) *colon = 0;
7108  strlcpy(bdname,bdcur,4000);
7109  char *slash = strchr(bdname,'/');
7110  if (slash) {
7111  *slash = 0;
7112  desc = bdcur;
7113  olddesc = slash+1;
7114  } else {
7115  desc.Form("%s/%s",bdname,olddesc.Data());
7116  }
7117  char *bracket = strchr(bdname,'[');
7118  if (bracket) {
7119  *bracket = 0;
7120  }
7121  branch = new TBranch(this,bdname,address,desc.Data(),32000);
7122  if (branch->IsZombie()) {
7123  delete branch;
7124  Warning("ReadStream","Illegal branch definition: %s",bdcur);
7125  } else {
7126  fBranches.Add(branch);
7127  branch->SetAddress(0);
7128  }
7129  if (!colon)break;
7130  bdcur = colon+1;
7131  }
7132  delete [] bdname;
7133  delete [] bd;
7134  }
7135 
7136  nbranches = fBranches.GetEntries();
7137 
7138  if (gDebug > 1) {
7139  Info("ReadStream", "Will use branches:");
7140  for (int i = 0 ; i < nbranches; ++i) {
7141  TBranch* br = (TBranch*) fBranches.At(i);
7142  Info("ReadStream", " %s: %s [%s]", br->GetName(),
7143  br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
7144  }
7145  if (gDebug > 3) {
7146  Info("ReadStream", "Dumping read tokens, format:");
7147  Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
7148  Info("ReadStream", " L: line number");
7149  Info("ReadStream", " B: branch number");
7150  Info("ReadStream", " gfbe: good / fail / bad / eof of token");
7151  Info("ReadStream", " GFBE: good / fail / bad / eof of file");
7152  Info("ReadStream", " T: Token being read");
7153  }
7154  }
7155 
7156  //loop on all lines in the file
7157  Long64_t nGoodLines = 0;
7158  std::string line;
7159  const char sDelimBuf[2] = { delimiter, 0 };
7160  const char* sDelim = sDelimBuf;
7161  if (delimiter == ' ') {
7162  // ' ' really means whitespace
7163  sDelim = "[ \t]";
7164  }
7165  while(in.good()) {
7166  if (newline == '\r' && in.peek() == '\n') {
7167  // Windows, skip '\n':
7168  in.get();
7169  }
7170  std::getline(in, line, newline);
7171  ++nlines;
7172 
7173  TString sLine(line);
7174  sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
7175  if (sLine.IsNull()) {
7176  if (gDebug > 2) {
7177  Info("ReadStream", "Skipping empty line number %lld", nlines);
7178  }
7179  continue; // silently skip empty lines
7180  }
7181  if (sLine[0] == '#') {
7182  if (gDebug > 2) {
7183  Info("ReadStream", "Skipping comment line number %lld: '%s'",
7184  nlines, line.c_str());
7185  }
7186  continue;
7187  }
7188  if (gDebug > 2) {
7189  Info("ReadStream", "Parsing line number %lld: '%s'",
7190  nlines, line.c_str());
7191  }
7192 
7193  // Loop on branches and read the branch values into their buffer
7194  branch = 0;
7195  TString tok; // one column's data
7196  TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7197  std::stringstream sToken; // string stream feeding leafData into leaves
7198  Ssiz_t pos = 0;
7199  Int_t iBranch = 0;
7200  Bool_t goodLine = kTRUE; // whether the row can be filled into the tree
7201  Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7202  while (goodLine && iBranch < nbranches
7203  && sLine.Tokenize(tok, pos, sDelim)) {
7204  tok = tok.Strip(TString::kLeading); // skip leading whitespace
7205  if (tok.IsNull() && delimiter == ' ') {
7206  // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7207  // Thus continue until we have a non-empty token.
7208  continue;
7209  }
7210 
7211  if (!remainingLeafLen) {
7212  // next branch!
7213  branch = (TBranch*)fBranches.At(iBranch);
7214  }
7215  TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7216  if (!remainingLeafLen) {
7217  remainingLeafLen = leaf->GetLen();
7218  if (leaf->GetMaximum() > 0) {
7219  // This is a dynamic leaf length, i.e. most likely a TLeafC's
7220  // string size. This still translates into one token:
7221  remainingLeafLen = 1;
7222  }
7223 
7224  leafData = tok;
7225  } else {
7226  // append token to laf data:
7227  leafData += " ";
7228  leafData += tok;
7229  }
7230  --remainingLeafLen;
7231  if (remainingLeafLen) {
7232  // need more columns for this branch:
7233  continue;
7234  }
7235  ++iBranch;
7236 
7237  // initialize stringstream with token
7238  sToken.clear();
7239  sToken.seekp(0, std::ios_base::beg);
7240  sToken.str(leafData.Data());
7241  sToken.seekg(0, std::ios_base::beg);
7242  leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7243  if (gDebug > 3) {
7244  Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7245  nlines, iBranch,
7246  (int)sToken.good(), (int)sToken.fail(),
7247  (int)sToken.bad(), (int)sToken.eof(),
7248  (int)in.good(), (int)in.fail(),
7249  (int)in.bad(), (int)in.eof(),
7250  sToken.str().c_str());
7251  }
7252 
7253  // Error handling
7254  if (sToken.bad()) {
7255  // How could that happen for a stringstream?
7256  Warning("ReadStream",
7257  "Buffer error while reading data for branch %s on line %lld",
7258  branch->GetName(), nlines);
7259  } else if (!sToken.eof()) {
7260  if (sToken.fail()) {
7261  Warning("ReadStream",
7262  "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7263  tok.Data(), branch->GetName(), nlines);
7264  goodLine = kFALSE;
7265  } else {
7266  std::string remainder;
7267  std::getline(sToken, remainder, newline);
7268  if (!remainder.empty()) {
7269  Warning("ReadStream",
7270  "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7271  remainder.c_str(), branch->GetName(), nlines);
7272  }
7273  }
7274  }
7275  } // tokenizer loop
7276 
7277  if (iBranch < nbranches) {
7278  Warning("ReadStream",
7279  "Read too few columns (%d < %d) in line %lld; ignoring line",
7280  iBranch, nbranches, nlines);
7281  goodLine = kFALSE;
7282  } else if (pos != kNPOS) {
7283  sLine = sLine.Strip(TString::kTrailing);
7284  if (pos < sLine.Length()) {
7285  Warning("ReadStream",
7286  "Ignoring trailing \"%s\" while reading line %lld",
7287  sLine.Data() + pos - 1 /* also print delimiter */,
7288  nlines);
7289  }
7290  }
7291 
7292  //we are now ready to fill the tree
7293  if (goodLine) {
7294  Fill();
7295  ++nGoodLines;
7296  }
7297  }
7298 
7299  return nGoodLines;
7300 }
7301 
7302 ////////////////////////////////////////////////////////////////////////////////
7303 /// Make sure that obj (which is being deleted or will soon be) is no
7304 /// longer referenced by this TTree.
7305 
7308  if (obj == fEventList) {
7309  fEventList = 0;
7310  }
7311  if (obj == fEntryList) {
7312  fEntryList = 0;
7313  }
7314  if (fUserInfo) {
7315  fUserInfo->RecursiveRemove(obj);
7316  }
7317  if (fPlayer == obj) {
7318  fPlayer = 0;
7319  }
7320  if (fTreeIndex == obj) {
7321  fTreeIndex = 0;
7322  }
7323  if (fAliases) {
7324  fAliases->RecursiveRemove(obj);
7325  }
7326  if (fFriends) {
7327  fFriends->RecursiveRemove(obj);
7328  }
7329 }
7330 
7331 ////////////////////////////////////////////////////////////////////////////////
7332 /// Refresh contents of this tree and its branches from the current status on disk.
7333 ///
7334 /// One can call this function in case the tree file is being
7335 /// updated by another process.
7336 
7337 void TTree::Refresh()
7339  if (!fDirectory->GetFile()) {
7340  return;
7341  }
7342  fDirectory->ReadKeys();
7343  fDirectory->Remove(this);
7344  TTree* tree; fDirectory->GetObject(GetName(),tree);
7345  if (!tree) {
7346  return;
7347  }
7348  //copy info from tree header into this Tree
7349  fEntries = 0;
7350  fNClusterRange = 0;
7351  ImportClusterRanges(tree);
7352 
7353  fAutoSave = tree->fAutoSave;
7354  fEntries = tree->fEntries;
7355  fTotBytes = tree->fTotBytes;
7356  fZipBytes = tree->fZipBytes;
7357  fSavedBytes = tree->fSavedBytes;
7358  fTotalBuffers = tree->fTotalBuffers.load();
7359 
7360  //loop on all branches and update them
7361  Int_t nleaves = fLeaves.GetEntriesFast();
7362  for (Int_t i = 0; i < nleaves; i++) {
7363  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7364  TBranch* branch = (TBranch*) leaf->GetBranch();
7365  branch->Refresh(tree->GetBranch(branch->GetName()));
7366  }
7367  fDirectory->Remove(tree);
7368  fDirectory->Append(this);
7369  delete tree;
7370  tree = 0;
7371 }
7372 
7373 ////////////////////////////////////////////////////////////////////////////////
7374 /// Remove a friend from the list of friends.
7375 
7376 void TTree::RemoveFriend(TTree* oldFriend)
7378  // We already have been visited while recursively looking
7379  // through the friends tree, let return
7381  return;
7382  }
7383  if (!fFriends) {
7384  return;
7385  }
7386  TFriendLock lock(this, kRemoveFriend);
7387  TIter nextf(fFriends);
7388  TFriendElement* fe = 0;
7389  while ((fe = (TFriendElement*) nextf())) {
7390  TTree* friend_t = fe->GetTree();
7391  if (friend_t == oldFriend) {
7392  fFriends->Remove(fe);
7393  delete fe;
7394  fe = 0;
7395  }
7396  }
7397 }
7398 
7399 ////////////////////////////////////////////////////////////////////////////////
7400 /// Reset baskets, buffers and entries count in all branches and leaves.
7401 
7402 void TTree::Reset(Option_t* option)
7404  fNotify = 0;
7405  fEntries = 0;
7406  fNClusterRange = 0;
7407  fTotBytes = 0;
7408  fZipBytes = 0;
7409  fFlushedBytes = 0;
7410  fSavedBytes = 0;
7411  fTotalBuffers = 0;
7412  fChainOffset = 0;
7413  fReadEntry = -1;
7414 
7415  delete fTreeIndex;
7416  fTreeIndex = 0;
7417 
7419  for (Int_t i = 0; i < nb; ++i) {
7420  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7421  branch->Reset(option);
7422  }
7423 
7424  if (fBranchRef) {
7425  fBranchRef->Reset();
7426  }
7427 }
7428 
7429 ////////////////////////////////////////////////////////////////////////////////
7430 /// Resets the state of this TTree after a merge (keep the customization but
7431 /// forget the data).
7432 
7435  fEntries = 0;
7436  fNClusterRange = 0;
7437  fTotBytes = 0;
7438  fZipBytes = 0;
7439  fSavedBytes = 0;
7440  fFlushedBytes = 0;
7441  fTotalBuffers = 0;
7442  fChainOffset = 0;
7443  fReadEntry = -1;
7444 
7445  delete fTreeIndex;
7446  fTreeIndex = 0;
7447 
7449  for (Int_t i = 0; i < nb; ++i) {
7450  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7451  branch->ResetAfterMerge(info);
7452  }
7453 
7454  if (fBranchRef) {
7455  fBranchRef->ResetAfterMerge(info);
7456  }
7457 }
7458 
7459 ////////////////////////////////////////////////////////////////////////////////
7460 /// Tell all of our branches to set their addresses to zero.
7461 ///
7462 /// Note: If any of our branches own any objects, they are deleted.
7463 
7466  if (br && br->GetTree()) {
7467  br->ResetAddress();
7468  }
7469 }
7470 
7471 ////////////////////////////////////////////////////////////////////////////////
7472 /// Tell all of our branches to drop their current objects and allocate new ones.
7473 
7476  TObjArray* branches = GetListOfBranches();
7477  Int_t nbranches = branches->GetEntriesFast();
7478  for (Int_t i = 0; i < nbranches; ++i) {
7479  TBranch* branch = (TBranch*) branches->UncheckedAt(i);
7480  branch->ResetAddress();
7481  }
7482 }
7483 
7484 ////////////////////////////////////////////////////////////////////////////////
7485 /// Loop over tree entries and print entries passing selection.
7486 ///
7487 /// - If varexp is 0 (or "") then print only first 8 columns.
7488 /// - If varexp = "*" print all columns.
7489 ///
7490 /// Otherwise a columns selection can be made using "var1:var2:var3".
7491 /// See TTreePlayer::Scan for more information
7492 
7493 Long64_t TTree::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7495  GetPlayer();
7496  if (fPlayer) {
7497  return fPlayer->Scan(varexp, selection, option, nentries, firstentry);
7498  }
7499  return -1;
7500 }
7501 
7502 ////////////////////////////////////////////////////////////////////////////////
7503 /// Set a tree variable alias.
7504 ///
7505 /// Set an alias for an expression/formula based on the tree 'variables'.
7506 ///
7507 /// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
7508 /// TTree::Scan, TTreeViewer) and will be evaluated as the content of
7509 /// 'aliasFormula'.
7510 ///
7511 /// If the content of 'aliasFormula' only contains symbol names, periods and
7512 /// array index specification (for example event.fTracks[3]), then
7513 /// the content of 'aliasName' can be used as the start of symbol.
7514 ///
7515 /// If the alias 'aliasName' already existed, it is replaced by the new
7516 /// value.
7517 ///
7518 /// When being used, the alias can be preceded by an eventual 'Friend Alias'
7519 /// (see TTree::GetFriendAlias)
7520 ///
7521 /// Return true if it was added properly.
7522 ///
7523 /// For example:
7524 /// ~~~ {.cpp}
7525 /// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
7526 /// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
7527 /// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
7528 /// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
7529 /// tree->Draw("y2-y1:x2-x1");
7530 ///
7531 /// tree->SetAlias("theGoodTrack","event.fTracks[3]");
7532 /// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
7533 /// ~~~
7534 
7535 Bool_t TTree::SetAlias(const char* aliasName, const char* aliasFormula)
7537  if (!aliasName || !aliasFormula) {
7538  return kFALSE;
7539  }
7540  if (!aliasName[0] || !aliasFormula[0]) {
7541  return kFALSE;
7542  }
7543  if (!fAliases) {
7544  fAliases = new TList;
7545  } else {
7546  TNamed* oldHolder = (TNamed*) fAliases->FindObject(aliasName);
7547  if (oldHolder) {
7548  oldHolder->SetTitle(aliasFormula);
7549  return kTRUE;
7550  }
7551  }
7552  TNamed* holder = new TNamed(aliasName, aliasFormula);
7553  fAliases->Add(holder);
7554  return kTRUE;
7555 }
7556 
7557 ////////////////////////////////////////////////////////////////////////////////
7558 /// This function may be called at the start of a program to change
7559 /// the default value for fAutoFlush.
7560 ///
7561 /// ### CASE 1 : autof > 0
7562 ///
7563 /// autof is the number of consecutive entries after which TTree::Fill will
7564 /// flush all branch buffers to disk.
7565 ///
7566 /// ### CASE 2 : autof < 0
7567 ///
7568 /// When filling the Tree the branch buffers will be flushed to disk when
7569 /// more than autof bytes have been written to the file. At the first FlushBaskets
7570 /// TTree::Fill will replace fAutoFlush by the current value of fEntries.
7571 ///
7572 /// Calling this function with autof<0 is interesting when it is hard to estimate
7573 /// the size of one entry. This value is also independent of the Tree.
7574 ///
7575 /// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
7576 /// the first AutoFlush will be done when 30 MBytes of data are written to the file.
7577 ///
7578 /// ### CASE 3 : autof = 0
7579 ///
7580 /// The AutoFlush mechanism is disabled.
7581 ///
7582 /// Flushing the buffers at regular intervals optimize the location of
7583 /// consecutive entries on the disk by creating clusters of baskets.
7584 ///
7585 /// A cluster of baskets is a set of baskets that contains all
7586 /// the data for a (consecutive) set of entries and that is stored
7587 /// consecutively on the disk. When reading all the branches, this
7588 /// is the minimum set of baskets that the TTreeCache will read.
7589 
7590 void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
7592  // Implementation note:
7593  //
7594  // A positive value of autoflush determines the size (in number of entries) of
7595  // a cluster of baskets.
7596  //
7597  // If the value of autoflush is changed over time (this happens in
7598  // particular when the TTree results from fast merging many trees),
7599  // we record the values of fAutoFlush in the data members:
7600  // fClusterRangeEnd and fClusterSize.
7601  // In the code we refer to a range of entries where the size of the
7602  // cluster of baskets is the same (i.e the value of AutoFlush was
7603  // constant) is called a ClusterRange.
7604  //
7605  // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
7606  // active (used) values and have fMaxClusterRange allocated entries.
7607  //
7608  // fClusterRangeEnd contains the last entries number of a cluster range.
7609  // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
7610  // fClusterSize contains the size in number of entries of all the cluster
7611  // within the given range.
7612  // The last range (and the only one if fNClusterRange is zero) start at
7613  // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
7614  // size of the cluster in this range is given by the value of fAutoFlush.
7615  //
7616  // For example printing the beginning and end of each the ranges can be done by:
7617  //
7618  // Printf("%-16s %-16s %-16s %5s",
7619  // "Cluster Range #", "Entry Start", "Last Entry", "Size");
7620  // Int_t index= 0;
7621  // Long64_t clusterRangeStart = 0;
7622  // if (fNClusterRange) {
7623  // for( ; index < fNClusterRange; ++index) {
7624  // Printf("%-16d %-16lld %-16lld %5lld",
7625  // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7626  // clusterRangeStart = fClusterRangeEnd[index] + 1;
7627  // }
7628  // }
7629  // Printf("%-16d %-16lld %-16lld %5lld",
7630  // index, prevEntry, fEntries - 1, fAutoFlush);
7631  //
7632 
7633  // Note: We store the entry number corresponding to the end of the cluster
7634  // rather than its start in order to avoid using the array if the cluster
7635  // size never varies (If there is only one value of AutoFlush for the whole TTree).
7636 
7637  if (fAutoFlush > 0 || autof > 0) {
7638  // The mechanism was already enabled, let's record the previous
7639  // cluster if needed.
7640  if (fFlushedBytes) {
7641  if ( (fNClusterRange+1) > fMaxClusterRange ) {
7642  if (fMaxClusterRange) {
7643  Int_t newsize = TMath::Max(10,Int_t(2*fMaxClusterRange));
7645  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7647  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7648  fMaxClusterRange = newsize;
7649  } else {
7650  fMaxClusterRange = 2;
7653  }
7654  }
7657  ++fNClusterRange;
7658  }
7659  }
7660  fAutoFlush = autof;
7661 }
7662 
7663 ////////////////////////////////////////////////////////////////////////////////
7664 /// This function may be called at the start of a program to change
7665 /// the default value for fAutoSave (and for SetAutoSave) is -300000000, ie 300 MBytes
7666 /// When filling the Tree the branch buffers as well as the Tree header
7667 /// will be flushed to disk when the watermark is reached.
7668 /// If fAutoSave is positive the watermark is reached when a multiple of fAutoSave
7669 /// entries have been written.
7670 /// If fAutoSave is negative the watermark is reached when -fAutoSave bytes
7671 /// have been written to the file.
7672 /// In case of a program crash, it will be possible to recover the data in the Tree
7673 /// up to the last AutoSave point.
7674 
7675 void TTree::SetAutoSave(Long64_t autos)
7677  fAutoSave = autos;
7678 }
7679 
7680 ////////////////////////////////////////////////////////////////////////////////
7681 /// Set a branch's basket size.
7682 ///
7683 /// bname is the name of a branch.
7684 ///
7685 /// - if bname="*", apply to all branches.
7686 /// - if bname="xxx*", apply to all branches with name starting with xxx
7687 ///
7688 /// see TRegexp for wildcarding options
7689 /// buffsize = branc basket size
7690 
7691 void TTree::SetBasketSize(const char* bname, Int_t buffsize)
7693  Int_t nleaves = fLeaves.GetEntriesFast();
7694  TRegexp re(bname, kTRUE);
7695  Int_t nb = 0;
7696  for (Int_t i = 0; i < nleaves; i++) {
7697  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7698  TBranch* branch = (TBranch*) leaf->GetBranch();
7699  TString s = branch->GetName();
7700  if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
7701  continue;
7702  }
7703  nb++;
7704  branch->SetBasketSize(buffsize);
7705  }
7706  if (!nb) {
7707  Error("SetBasketSize", "unknown branch -> '%s'", bname);
7708  }
7709 }
7710 
7711 ////////////////////////////////////////////////////////////////////////////////
7712 /// Change branch address, dealing with clone trees properly.
7713 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7714 ///
7715 /// Note: See the comments in TBranchElement::SetAddress() for the
7716 /// meaning of the addr parameter and the object ownership policy.
7717 
7718 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
7720  TBranch* branch = GetBranch(bname);
7721  if (!branch) {
7722  if (ptr) *ptr = 0;
7723  Error("SetBranchAddress", "unknown branch -> %s", bname);
7724  return kMissingBranch;
7725  }
7726  return SetBranchAddressImp(branch,addr,ptr);
7727 }
7728 
7729 ////////////////////////////////////////////////////////////////////////////////
7730 /// Verify the validity of the type of addr before calling SetBranchAddress.
7731 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7732 ///
7733 /// Note: See the comments in TBranchElement::SetAddress() for the
7734 /// meaning of the addr parameter and the object ownership policy.
7735 
7736 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
7738  return SetBranchAddress(bname, addr, 0, ptrClass, datatype, isptr);
7739 }
7740 
7741 ////////////////////////////////////////////////////////////////////////////////
7742 /// Verify the validity of the type of addr before calling SetBranchAddress.
7743 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7744 ///
7745 /// Note: See the comments in TBranchElement::SetAddress() for the
7746 /// meaning of the addr parameter and the object ownership policy.
7747 
7748 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
7750  TBranch* branch = GetBranch(bname);
7751  if (!branch) {
7752  if (ptr) *ptr = 0;
7753  Error("SetBranchAddress", "unknown branch -> %s", bname);
7754  return kMissingBranch;
7755  }
7756 
7757  Int_t res = CheckBranchAddressType(branch, ptrClass, datatype, isptr);
7758  // This will set the value of *ptr to branch.
7759  if (res >= 0) {
7760  // The check succeeded.
7761  SetBranchAddressImp(branch,addr,ptr);
7762  } else {
7763  if (ptr) *ptr = 0;
7764  }
7765  return res;
7766 }
7767 
7768 ////////////////////////////////////////////////////////////////////////////////
7769 /// Change branch address, dealing with clone trees properly.
7770 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7771 ///
7772 /// Note: See the comments in TBranchElement::SetAddress() for the
7773 /// meaning of the addr parameter and the object ownership policy.
7774 
7775 Int_t TTree::SetBranchAddressImp(TBranch *branch, void* addr, TBranch** ptr)
7777  if (ptr) {
7778  *ptr = branch;
7779  }
7780  if (fClones) {
7781  void* oldAddr = branch->GetAddress();
7782  TIter next(fClones);
7783  TTree* clone = 0;
7784  const char *bname = branch->GetName();
7785  while ((clone = (TTree*) next())) {
7786  TBranch* cloneBr = clone->GetBranch(bname);
7787  if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
7788  cloneBr->SetAddress(addr);
7789  }
7790  }
7791  }
7792  branch->SetAddress(addr);
7793  return kVoidPtr;
7794 }
7795 
7796 ////////////////////////////////////////////////////////////////////////////////
7797 /// Set branch status to Process or DoNotProcess.
7798 ///
7799 /// When reading a Tree, by default, all branches are read.
7800 /// One can speed up considerably the analysis phase by activating
7801 /// only the branches that hold variables involved in a query.
7802 ///
7803 /// bname is the name of a branch.
7804 ///
7805 /// - if bname="*", apply to all branches.
7806 /// - if bname="xxx*", apply to all branches with name starting with xxx
7807 ///
7808 /// see TRegexp for wildcarding options
7809 ///
7810 /// - status = 1 branch will be processed
7811 /// - = 0 branch will not be processed
7812 ///
7813 /// Example:
7814 ///
7815 /// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
7816 /// when doing T.GetEntry(i) all branches are read for entry i.
7817 /// to read only the branches c and e, one can do
7818 /// ~~~ {.cpp}
7819 /// T.SetBranchStatus("*",0); //disable all branches
7820 /// T.SetBranchStatus("c",1);
7821 /// T.setBranchStatus("e",1);
7822 /// T.GetEntry(i);
7823 /// ~~~
7824 /// bname is interpreted as a wildcarded TRegexp (see TRegexp::MakeWildcard).
7825 /// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
7826 /// "b", but not any other branch with an "a" followed at some point by a
7827 /// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
7828 /// support '|', and so you cannot select, e.g. track and shower branches
7829 /// with "track|shower".
7830 ///
7831 /// __WARNING! WARNING! WARNING!__
7832 ///
7833 /// SetBranchStatus is matching the branch based on match of the branch
7834 /// 'name' and not on the branch hierarchy! In order to be able to
7835 /// selectively enable a top level object that is 'split' you need to make
7836 /// sure the name of the top level branch is prefixed to the sub-branches'
7837 /// name (by adding a dot ('.') at the end of the Branch creation and use the
7838 /// corresponding bname.
7839 ///
7840 /// I.e If your Tree has been created in split mode with a parent branch "parent."
7841 /// (note the trailing dot).
7842 /// ~~~ {.cpp}
7843 /// T.SetBranchStatus("parent",1);
7844 /// ~~~
7845 /// will not activate the sub-branches of "parent". You should do:
7846 /// ~~~ {.cpp}
7847 /// T.SetBranchStatus("parent*",1);
7848 /// ~~~
7849 /// Without the trailing dot in the branch creation you have no choice but to
7850 /// call SetBranchStatus explicitly for each of the sub branches.
7851 ///
7852 /// An alternative to this function is to read directly and only
7853 /// the interesting branches. Example:
7854 /// ~~~ {.cpp}
7855 /// TBranch *brc = T.GetBranch("c");
7856 /// TBranch *bre = T.GetBranch("e");
7857 /// brc->GetEntry(i);
7858 /// bre->GetEntry(i);
7859 /// ~~~
7860 /// If found is not 0, the number of branch(es) found matching the regular
7861 /// expression is returned in *found AND the error message 'unknown branch'
7862 /// is suppressed.
7863 
7864 void TTree::SetBranchStatus(const char* bname, Bool_t status, UInt_t* found)
7866  // We already have been visited while recursively looking
7867  // through the friends tree, let return
7869  return;
7870  }
7871 
7872  TBranch *branch, *bcount, *bson;
7873  TLeaf *leaf, *leafcount;
7874 
7875  Int_t i,j;
7876  Int_t nleaves = fLeaves.GetEntriesFast();
7877  TRegexp re(bname,kTRUE);
7878  Int_t nb = 0;
7879 
7880  // first pass, loop on all branches
7881  // for leafcount branches activate/deactivate in function of status
7882  for (i=0;i<nleaves;i++) {
7883  leaf = (TLeaf*)fLeaves.UncheckedAt(i);
7884  branch = (TBranch*)leaf->GetBranch();
7885  TString s = branch->GetName();
7886  if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
7887  TString longname;
7888  longname.Form("%s.%s",GetName(),branch->GetName());
7889  if (strcmp(bname,branch->GetName())
7890  && longname != bname
7891  && s.Index(re) == kNPOS) continue;
7892  }
7893  nb++;
7894  if (status) branch->ResetBit(kDoNotProcess);
7895  else branch->SetBit(kDoNotProcess);
7896  leafcount = leaf->GetLeafCount();
7897  if (leafcount) {
7898  bcount = leafcount->GetBranch();
7899  if (status) bcount->ResetBit(kDoNotProcess);
7900  else bcount->SetBit(kDoNotProcess);
7901  }
7902  }
7903  if (nb==0 && strchr(bname,'*')==0) {
7904  branch = GetBranch(bname);
7905  if (branch) {
7906  if (status) branch->ResetBit(kDoNotProcess);
7907  else branch->SetBit(kDoNotProcess);
7908  ++nb;
7909  }
7910  }
7911 
7912  //search in list of friends
7913  UInt_t foundInFriend = 0;
7914  if (fFriends) {
7915  TFriendLock lock(this,kSetBranchStatus);
7916  TIter nextf(fFriends);
7917  TFriendElement *fe;
7918  TString name;
7919  while ((fe = (TFriendElement*)nextf())) {
7920  TTree *t = fe->GetTree();
7921  if (t==0) continue;
7922 
7923  // If the alias is present replace it with the real name.
7924  char *subbranch = (char*)strstr(bname,fe->GetName());
7925  if (subbranch!=bname) subbranch = 0;
7926  if (subbranch) {
7927  subbranch += strlen(fe->GetName());
7928  if ( *subbranch != '.' ) subbranch = 0;
7929  else subbranch ++;
7930  }
7931  if (subbranch) {
7932  name.Form("%s.%s",t->GetName(),subbranch);
7933  } else {
7934  name = bname;
7935  }
7936  t->SetBranchStatus(name,status, &foundInFriend);
7937  }
7938  }
7939  if (!nb && !foundInFriend) {
7940  if (found==0) {
7941  if (status) {
7942  if (strchr(bname,'*') != 0)
7943  Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
7944  else
7945  Error("SetBranchStatus", "unknown branch -> %s", bname);
7946  } else {
7947  if (strchr(bname,'*') != 0)
7948  Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
7949  else
7950  Warning("SetBranchStatus", "unknown branch -> %s", bname);
7951  }
7952  }
7953  return;
7954  }
7955  if (found) *found = nb + foundInFriend;
7956 
7957  // second pass, loop again on all branches
7958  // activate leafcount branches for active branches only
7959  for (i = 0; i < nleaves; i++) {
7960  leaf = (TLeaf*)fLeaves.UncheckedAt(i);
7961  branch = (TBranch*)leaf->GetBranch();
7962  if (!branch->TestBit(kDoNotProcess)) {
7963  leafcount = leaf->GetLeafCount();
7964  if (leafcount) {
7965  bcount = leafcount->GetBranch();
7966  bcount->ResetBit(kDoNotProcess);
7967  }
7968  } else {
7969  //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
7970  Int_t nbranches = branch->GetListOfBranches()->GetEntries();
7971  for (j=0;j<nbranches;j++) {
7972  bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
7973  if (!bson) continue;
7974  if (!bson->TestBit(kDoNotProcess)) {
7975  if (bson->GetNleaves() <= 0) continue;
7976  branch->ResetBit(kDoNotProcess);
7977  break;
7978  }
7979  }
7980  }
7981  }
7982 }
7983 
7984 ////////////////////////////////////////////////////////////////////////////////
7985 /// Set the current branch style. (static function)
7986 ///
7987 /// - style = 0 old Branch
7988 /// - style = 1 new Bronch
7989 
7992  fgBranchStyle = style;
7993 }
7994 
7995 ////////////////////////////////////////////////////////////////////////////////
7996 /// Set maximum size of the file cache .
7997 //
7998 /// - if cachesize = 0 the existing cache (if any) is deleted.
7999 /// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
8000 /// the Tree (default is 30 MBytes).
8001 ///
8002 /// Returns:
8003 /// - 0 size set, cache was created if possible
8004 /// - -1 on error
8005 
8008  // remember that the user has requested an explicit cache setup
8009  fCacheUserSet = kTRUE;
8010 
8011  return SetCacheSizeAux(kFALSE, cacheSize);
8012 }
8013 
8014 ////////////////////////////////////////////////////////////////////////////////
8015 /// Set the size of the file cache and create it if possible.
8016 ///
8017 /// If autocache is true:
8018 /// this may be an autocreated cache, possibly enlarging an existing
8019 /// autocreated cache. The size is calculated. The value passed in cacheSize:
8020 /// - cacheSize = 0 make cache if default cache creation is enabled
8021 /// - cacheSize = -1 make a default sized cache in any case
8022 ///
8023 /// If autocache is false:
8024 /// this is a user requested cache. cacheSize is used to size the cache.
8025 /// This cache should never be automatically adjusted.
8026 ///
8027 /// Returns:
8028 /// - 0 size set, or existing autosized cache almost large enough.
8029 /// (cache was created if possible)
8030 /// - -1 on error
8031 
8032 Int_t TTree::SetCacheSizeAux(Bool_t autocache /* = kTRUE */, Long64_t cacheSize /* = 0 */ )
8034  if (autocache) {
8035  // used as a once only control for automatic cache setup
8037  }
8038 
8039  if (!autocache) {
8040  // negative size means the user requests the default
8041  if (cacheSize < 0) {
8042  cacheSize = GetCacheAutoSize(kTRUE);
8043  }
8044  } else {
8045  if (cacheSize == 0) {
8046  cacheSize = GetCacheAutoSize();
8047  } else if (cacheSize < 0) {
8048  cacheSize = GetCacheAutoSize(kTRUE);
8049  }
8050  }
8051 
8052  TFile* file = GetCurrentFile();
8053  if (!file || GetTree() != this) {
8054  // if there's no file or we are not a plain tree (e.g. if we're a TChain)
8055  // do not create a cache, only record the size if one was given
8056  if (!autocache) {
8057  fCacheSize = cacheSize;
8058  }
8059  if (GetTree() != this) {
8060  return 0;
8061  }
8062  if (!autocache && cacheSize>0) {
8063  Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
8064  }
8065  return 0;
8066  }
8067 
8068  // Check for an existing cache
8069  TTreeCache* pf = GetReadCache(file);
8070  if (pf) {
8071  if (autocache) {
8072  // reset our cache status tracking in case existing cache was added
8073  // by the user without using one of the TTree methods
8074  fCacheSize = pf->GetBufferSize();
8075  fCacheUserSet = !pf->IsAutoCreated();
8076 
8077  if (fCacheUserSet) {
8078  // existing cache was created by the user, don't change it
8079  return 0;
8080  }
8081  } else {
8082  // update the cache to ensure it records the user has explicitly
8083  // requested it
8084  pf->SetAutoCreated(kFALSE);
8085  }
8086 
8087  // if we're using an automatically calculated size and the existing
8088  // cache is already almost large enough don't resize
8089  if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
8090  // already large enough
8091  return 0;
8092  }
8093 
8094  if (cacheSize == fCacheSize) {
8095  return 0;
8096  }
8097 
8098  if (cacheSize == 0) {
8099  // delete existing cache
8100  pf->WaitFinishPrefetch();
8101  file->SetCacheRead(0,this);
8102  delete pf;
8103  pf = 0;
8104  } else {
8105  // resize
8106  Int_t res = pf->SetBufferSize(cacheSize);
8107  if (res < 0) {
8108  return -1;
8109  }
8110  }
8111  } else {
8112  // no existing cache
8113  if (autocache) {
8114  if (fCacheUserSet) {
8115  // value was already set manually.
8116  if (fCacheSize == 0) return 0;
8117  // Expected a cache should exist; perhaps the user moved it
8118  // Do nothing more here.
8119  if (cacheSize) {
8120  Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
8121  }
8122  return -1;
8123  }
8124  }
8125  }
8126 
8127  fCacheSize = cacheSize;
8128  if (cacheSize == 0 || pf) {
8129  return 0;
8130  }
8131 
8133  pf = new TTreeCacheUnzip(this, cacheSize);
8134  else
8135  pf = new TTreeCache(this, cacheSize);
8136 
8137  pf->SetAutoCreated(autocache);
8138 
8139  return 0;
8140 }
8141 
8142 ////////////////////////////////////////////////////////////////////////////////
8143 ///interface to TTreeCache to set the cache entry range
8144 ///
8145 /// Returns:
8146 /// - 0 entry range set
8147 /// - -1 on error
8148 
8151  if (!GetTree()) {
8152  if (LoadTree(0)<0) {
8153  Error("SetCacheEntryRange","Could not load a tree");
8154  return -1;
8155  }
8156  }
8157  if (GetTree()) {
8158  if (GetTree() != this) {
8159  return GetTree()->SetCacheEntryRange(first, last);
8160  }
8161  } else {
8162  Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
8163  return -1;
8164  }
8165 
8166  TFile *f = GetCurrentFile();
8167  if (!f) {
8168  Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
8169  return -1;
8170  }
8171  TTreeCache *tc = GetReadCache(f,kTRUE);
8172  if (!tc) {
8173  Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
8174  return -1;
8175  }
8176  tc->SetEntryRange(first,last);
8177  return 0;
8178 }
8179 
8180 ////////////////////////////////////////////////////////////////////////////////
8181 /// Interface to TTreeCache to set the number of entries for the learning phase
8182 
8186 }
8187 
8188 ////////////////////////////////////////////////////////////////////////////////
8189 /// Enable/Disable circularity for this tree.
8190 ///
8191 /// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8192 /// per branch in memory.
8193 /// Note that when this function is called (maxEntries>0) the Tree
8194 /// must be empty or having only one basket per branch.
8195 /// if maxEntries <= 0 the tree circularity is disabled.
8196 ///
8197 /// #### NOTE 1:
8198 /// Circular Trees are interesting in online real time environments
8199 /// to store the results of the last maxEntries events.
8200 /// #### NOTE 2:
8201 /// Calling SetCircular with maxEntries <= 0 is necessary before
8202 /// merging circular Trees that have been saved on files.
8203 /// #### NOTE 3:
8204 /// SetCircular with maxEntries <= 0 is automatically called
8205 /// by TChain::Merge
8206 /// #### NOTE 4:
8207 /// A circular Tree can still be saved in a file. When read back,
8208 /// it is still a circular Tree and can be filled again.
8209 
8210 void TTree::SetCircular(Long64_t maxEntries)
8212  if (maxEntries <= 0) {
8213  // Disable circularity.
8214  fMaxEntries = 1000000000;
8215  fMaxEntries *= 1000;
8217  //in case the Tree was originally created in gROOT, the branch
8218  //compression level was set to -1. If the Tree is now associated to
8219  //a file, reset the compression level to the file compression level
8220  if (fDirectory) {
8221  TFile* bfile = fDirectory->GetFile();
8222  Int_t compress = 1;
8223  if (bfile) {
8224  compress = bfile->GetCompressionSettings();
8225  }
8227  for (Int_t i = 0; i < nb; i++) {
8228  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8229  branch->SetCompressionSettings(compress);
8230  }
8231  }
8232  } else {
8233  // Enable circularity.
8234  fMaxEntries = maxEntries;
8235  SetBit(kCircular);
8236  }
8237 }
8238 
8239 ////////////////////////////////////////////////////////////////////////////////
8240 /// Set the debug level and the debug range.
8241 ///
8242 /// For entries in the debug range, the functions TBranchElement::Fill
8243 /// and TBranchElement::GetEntry will print the number of bytes filled
8244 /// or read for each branch.
8245 
8246 void TTree::SetDebug(Int_t level, Long64_t min, Long64_t max)
8248  fDebug = level;
8249  fDebugMin = min;
8250  fDebugMax = max;
8251 }
8252 
8253 ////////////////////////////////////////////////////////////////////////////////
8254 /// Update the default value for the branch's fEntryOffsetLen.
8255 /// If updateExisting is true, also update all the existing branches.
8256 /// If newdefault is less than 10, the new default value will be 10.
8257 
8258 void TTree::SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
8260  if (newdefault < 10) {
8261  newdefault = 10;
8262  }
8263  fDefaultEntryOffsetLen = newdefault;
8264  if (updateExisting) {
8265  TIter next( GetListOfBranches() );
8266  TBranch *b;
8267  while ( ( b = (TBranch*)next() ) ) {
8268  b->SetEntryOffsetLen( newdefault, kTRUE );
8269  }
8270  if (fBranchRef) {
8271  fBranchRef->SetEntryOffsetLen( newdefault, kTRUE );
8272  }
8273  }
8274 }
8275 
8276 ////////////////////////////////////////////////////////////////////////////////
8277 /// Change the tree's directory.
8278 ///
8279 /// Remove reference to this tree from current directory and
8280 /// add reference to new directory dir. The dir parameter can
8281 /// be 0 in which case the tree does not belong to any directory.
8282 ///
8283 
8286  if (fDirectory == dir) {
8287  return;
8288  }
8289  if (fDirectory) {
8290  fDirectory->Remove(this);
8291 
8292  // Delete or move the file cache if it points to this Tree
8293  TFile *file = fDirectory->GetFile();
8294  MoveReadCache(file,dir);
8295  }
8296  fDirectory = dir;
8297  if (fDirectory) {
8298  fDirectory->Append(this);
8299  }
8300  TFile* file = 0;
8301  if (fDirectory) {
8302  file = fDirectory->GetFile();
8303  }
8304  if (fBranchRef) {
8305  fBranchRef->SetFile(file);
8306  }
8307  TBranch* b = 0;
8308  TIter next(GetListOfBranches());
8309  while((b = (TBranch*) next())) {
8310  b->SetFile(file);
8311  }
8312 }
8313 
8314 ////////////////////////////////////////////////////////////////////////////////
8315 /// Change number of entries in the tree.
8316 ///
8317 /// If n >= 0, set number of entries in the tree = n.
8318 ///
8319 /// If n < 0, set number of entries in the tree to match the
8320 /// number of entries in each branch. (default for n is -1)
8321 ///
8322 /// This function should be called only when one fills each branch
8323 /// independently via TBranch::Fill without calling TTree::Fill.
8324 /// Calling TTree::SetEntries() make sense only if the number of entries
8325 /// in each branch is identical, a warning is issued otherwise.
8326 /// The function returns the number of entries.
8327 ///
8328 
8331  // case 1 : force number of entries to n
8332  if (n >= 0) {
8333  fEntries = n;
8334  return n;
8335  }
8336 
8337  // case 2; compute the number of entries from the number of entries in the branches
8338  TBranch* b = 0;
8339  Long64_t nMin = 99999999;
8340  Long64_t nMax = 0;
8341  TIter next(GetListOfBranches());
8342  while((b = (TBranch*) next())){
8343  Long64_t n2 = b->GetEntries();
8344  if (n2 < nMin) {
8345  nMin = n2;
8346  }
8347  if (n2 > nMax) {
8348  nMax = n2;
8349  }
8350  }
8351  if (nMin != nMax) {
8352  Warning("SetEntries", "Tree branches have different numbers of entries, with %lld maximum.", nMax);
8353  }
8354  fEntries = nMax;
8355  return fEntries;
8356 }
8357 
8358 ////////////////////////////////////////////////////////////////////////////////
8359 /// Set an EntryList
8360 
8361 void TTree::SetEntryList(TEntryList *enlist, Option_t * /*opt*/)
8363  if (fEntryList) {
8364  //check if the previous entry list is owned by the tree
8365  if (fEntryList->TestBit(kCanDelete)){
8366  delete fEntryList;
8367  }
8368  }
8369  fEventList = 0;
8370  if (!enlist) {
8371  fEntryList = 0;
8372  return;
8373  }
8374  fEntryList = enlist;
8375  fEntryList->SetTree(this);
8376 
8377 }
8378 
8379 ////////////////////////////////////////////////////////////////////////////////
8380 /// This function transfroms the given TEventList into a TEntryList
8381 /// The new TEntryList is owned by the TTree and gets deleted when the tree
8382 /// is deleted. This TEntryList can be returned by GetEntryList() function.
8383 
8384 void TTree::SetEventList(TEventList *evlist)
8386  fEventList = evlist;
8387  if (fEntryList){
8388  if (fEntryList->TestBit(kCanDelete)) {
8389  TEntryList *tmp = fEntryList;
8390  fEntryList = 0; // Avoid problem with RecursiveRemove.
8391  delete tmp;
8392  } else {
8393  fEntryList = 0;
8394  }
8395  }
8396 
8397  if (!evlist) {
8398  fEntryList = 0;
8399  fEventList = 0;
8400  return;
8401  }
8402 
8403  fEventList = evlist;
8404  char enlistname[100];
8405  snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
8406  fEntryList = new TEntryList(enlistname, evlist->GetTitle());
8407  fEntryList->SetDirectory(0); // We own this.
8408  Int_t nsel = evlist->GetN();
8409  fEntryList->SetTree(this);
8410  Long64_t entry;
8411  for (Int_t i=0; i<nsel; i++){
8412  entry = evlist->GetEntry(i);
8413  fEntryList->Enter(entry);
8414  }
8415  fEntryList->SetReapplyCut(evlist->GetReapplyCut());
8416  fEntryList->SetBit(kCanDelete, kTRUE);
8417 }
8418 
8419 ////////////////////////////////////////////////////////////////////////////////
8420 /// Set number of entries to estimate variable limits.
8421 /// If n is -1, the estimate is set to be the current maximum
8422 /// for the tree (i.e. GetEntries() + 1)
8423 /// If n is less than -1, the behavior is undefined.
8424 
8425 void TTree::SetEstimate(Long64_t n /* = 1000000 */)
8427  if (n == 0) {
8428  n = 10000;
8429  } else if (n < 0) {
8430  n = fEntries - n;
8431  }
8432  fEstimate = n;
8433  GetPlayer();
8434  if (fPlayer) {
8435  fPlayer->SetEstimate(n);
8436  }
8437 }
8438 
8439 ////////////////////////////////////////////////////////////////////////////////
8440 /// Set fFileNumber to number.
8441 /// fFileNumber is used by TTree::Fill to set the file name
8442 /// for a new file to be created when the current file exceeds fgTreeMaxSize.
8443 /// (see TTree::ChangeFile)
8444 /// if fFileNumber=10, the new file name will have a suffix "_11",
8445 /// ie, fFileNumber is incremented before setting the file name
8446 
8447 void TTree::SetFileNumber(Int_t number)
8449  if (fFileNumber < 0) {
8450  Warning("SetFileNumber", "file number must be positive. Set to 0");
8451  fFileNumber = 0;
8452  return;
8453  }
8454  fFileNumber = number;
8455 }
8456 
8457 ////////////////////////////////////////////////////////////////////////////////
8458 /// Set all the branches in this TTree to be in decomposed object mode
8459 /// (also known as MakeClass mode).
8460 
8463  fMakeClass = make;
8464 
8466  for (Int_t i = 0; i < nb; ++i) {
8467  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8468  branch->SetMakeClass(make);
8469  }
8470 }
8471 
8472 ////////////////////////////////////////////////////////////////////////////////
8473 /// Set the maximum size in bytes of a Tree file (static function).
8474 /// The default size is 100000000000LL, ie 100 Gigabytes.
8475 ///
8476 /// In TTree::Fill, when the file has a size > fgMaxTreeSize,
8477 /// the function closes the current file and starts writing into
8478 /// a new file with a name of the style "file_1.root" if the original
8479 /// requested file name was "file.root".
8480 
8484 }
8485 
8486 ////////////////////////////////////////////////////////////////////////////////
8487 /// Change the name of this tree.
8488 
8489 void TTree::SetName(const char* name)
8491  if (gPad) {
8492  gPad->Modified();
8493  }
8494  // Trees are named objects in a THashList.
8495  // We must update hashlists if we change the name.
8496  TFile *file = 0;
8497  TTreeCache *pf = 0;
8498  if (fDirectory) {
8499  fDirectory->Remove(this);
8500  if ((file = GetCurrentFile())) {
8501  pf = GetReadCache(file);
8502  file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8503  }
8504  }
8505  // This changes our hash value.
8506  fName = name;
8507  if (fDirectory) {
8508  fDirectory->Append(this);
8509  if (pf) {
8510  file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8511  }
8512  }
8513 }
8514 
8515 ////////////////////////////////////////////////////////////////////////////////
8516 /// Change the name and title of this tree.
8517 
8518 void TTree::SetObject(const char* name, const char* title)
8520  if (gPad) {
8521  gPad->Modified();
8522  }
8523 
8524  // Trees are named objects in a THashList.
8525  // We must update hashlists if we change the name
8526  TFile *file = 0;
8527  TTreeCache *pf = 0;
8528  if (fDirectory) {
8529  fDirectory->Remove(this);
8530  if ((file = GetCurrentFile())) {
8531  pf = GetReadCache(file);
8532  file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8533  }
8534  }
8535  // This changes our hash value.
8536  fName = name;
8537  fTitle = title;
8538  if (fDirectory) {
8539  fDirectory->Append(this);
8540  if (pf) {
8541  file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8542  }
8543  }
8544 }
8545 
8546 ////////////////////////////////////////////////////////////////////////////////
8547 /// Enable or disable parallel unzipping of Tree buffers.
8548 
8549 void TTree::SetParallelUnzip(Bool_t opt, Float_t RelSize)
8553 
8554  if (RelSize > 0) {
8556  }
8557 
8558 }
8559 
8560 ////////////////////////////////////////////////////////////////////////////////
8561 /// Set perf stats
8562 
8565  fPerfStats = perf;
8566 }
8567 
8568 ////////////////////////////////////////////////////////////////////////////////
8569 /// The current TreeIndex is replaced by the new index.
8570 /// Note that this function does not delete the previous index.
8571 /// This gives the possibility to play with more than one index, e.g.,
8572 /// ~~~ {.cpp}
8573 /// TVirtualIndex* oldIndex = tree.GetTreeIndex();
8574 /// tree.SetTreeIndex(newIndex);
8575 /// tree.Draw();
8576 /// tree.SetTreeIndex(oldIndex);
8577 /// tree.Draw(); etc
8578 /// ~~~
8579 
8582  if (fTreeIndex) {
8583  fTreeIndex->SetTree(0);
8584  }
8585  fTreeIndex = index;
8586 }
8587 
8588 ////////////////////////////////////////////////////////////////////////////////
8589 /// Set tree weight.
8590 ///
8591 /// The weight is used by TTree::Draw to automatically weight each
8592 /// selected entry in the resulting histogram.
8593 ///
8594 /// For example the equivalent of:
8595 /// ~~~ {.cpp}
8596 /// T.Draw("x", "w")
8597 /// ~~~
8598 /// is:
8599 /// ~~~ {.cpp}
8600 /// T.SetWeight(w);
8601 /// T.Draw("x");
8602 /// ~~~
8603 /// This function is redefined by TChain::SetWeight. In case of a
8604 /// TChain, an option "global" may be specified to set the same weight
8605 /// for all trees in the TChain instead of the default behaviour
8606 /// using the weights of each tree in the chain (see TChain::SetWeight).
8607 
8610  fWeight = w;
8611 }
8612 
8613 ////////////////////////////////////////////////////////////////////////////////
8614 /// Print values of all active leaves for entry.
8615 ///
8616 /// - if entry==-1, print current entry (default)
8617 /// - if a leaf is an array, a maximum of lenmax elements is printed.
8618 
8619 void TTree::Show(Long64_t entry, Int_t lenmax)
8621  if (entry != -1) {
8622  Int_t ret = LoadTree(entry);
8623  if (ret == -2) {
8624  Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
8625  return;
8626  } else if (ret == -1) {
8627  Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8628  return;
8629  }
8630  ret = GetEntry(entry);
8631  if (ret == -1) {
8632  Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8633  return;
8634  } else if (ret == 0) {
8635  Error("Show()", "Cannot read entry %lld (no data read)", entry);
8636  return;
8637  }
8638  }
8639  printf("======> EVENT:%lld\n", fReadEntry);
8640  TObjArray* leaves = GetListOfLeaves();
8641  Int_t nleaves = leaves->GetEntriesFast();
8642  Int_t ltype;
8643  for (Int_t i = 0; i < nleaves; i++) {
8644  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
8645  TBranch* branch = leaf->GetBranch();
8646  if (branch->TestBit(kDoNotProcess)) {
8647  continue;
8648  }
8649  Int_t len = leaf->GetLen();
8650  if (len <= 0) {
8651  continue;
8652  }
8653  len = TMath::Min(len, lenmax);
8654  if (leaf->IsA() == TLeafElement::Class()) {
8655  leaf->PrintValue(lenmax);
8656  continue;
8657  }
8658  if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
8659  continue;
8660  }
8661  ltype = 10;
8662  if (leaf->IsA() == TLeafF::Class()) {
8663  ltype = 5;
8664  }
8665  if (leaf->IsA() == TLeafD::Class()) {
8666  ltype = 5;
8667  }
8668  if (leaf->IsA() == TLeafC::Class()) {
8669  len = 1;
8670  ltype = 5;
8671  };
8672  printf(" %-15s = ", leaf->GetName());
8673  for (Int_t l = 0; l < len; l++) {
8674  leaf->PrintValue(l);
8675  if (l == (len - 1)) {
8676  printf("\n");
8677  continue;
8678  }
8679  printf(", ");
8680  if ((l % ltype) == 0) {
8681  printf("\n ");
8682  }
8683  }
8684  }
8685 }
8686 
8687 ////////////////////////////////////////////////////////////////////////////////
8688 /// Start the TTreeViewer on this tree.
8689 ///
8690 /// - ww is the width of the canvas in pixels
8691 /// - wh is the height of the canvas in pixels
8692 
8693 void TTree::StartViewer()
8695  GetPlayer();
8696  if (fPlayer) {
8697  fPlayer->StartViewer(600, 400);
8698  }
8699 }
8700 
8701 ////////////////////////////////////////////////////////////////////////////////
8702 /// Stop the cache learning phase
8703 ///
8704 /// Returns:
8705 /// - 0 learning phase stopped or not active
8706 /// - -1 on error
8707 
8710  if (!GetTree()) {
8711  if (LoadTree(0)<0) {
8712  Error("StopCacheLearningPhase","Could not load a tree");
8713  return -1;
8714  }
8715  }
8716  if (GetTree()) {
8717  if (GetTree() != this) {
8718  return GetTree()->StopCacheLearningPhase();
8719  }
8720  } else {
8721  Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
8722  return -1;
8723  }
8724 
8725  TFile *f = GetCurrentFile();
8726  if (!f) {
8727  Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
8728  return -1;
8729  }
8730  TTreeCache *tc = GetReadCache(f,kTRUE);
8731  if (!tc) {
8732  Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
8733  return -1;
8734  }
8735  tc->StopLearningPhase();
8736  return 0;
8737 }
8738 
8739 ////////////////////////////////////////////////////////////////////////////////
8740 /// Set the fTree member for all branches and sub branches.
8741 
8742 static void TBranch__SetTree(TTree *tree, TObjArray &branches)
8744  Int_t nb = branches.GetEntriesFast();
8745  for (Int_t i = 0; i < nb; ++i) {
8746  TBranch* br = (TBranch*) branches.UncheckedAt(i);
8747  br->SetTree(tree);
8748 
8749  Int_t nBaskets = br->GetListOfBaskets()->GetEntries();
8750  Int_t writeBasket = br->GetWriteBasket();
8751  for (Int_t j=writeBasket,n=0;j>=0 && n<nBaskets;--j) {
8752  TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
8753  if (bk) {
8754  tree->IncrementTotalBuffers(bk->GetBufferSize());
8755  ++n;
8756  }
8757  }
8758 
8759  TBranch__SetTree(tree,*br->GetListOfBranches());
8760  }
8761 }
8762 
8763 ////////////////////////////////////////////////////////////////////////////////
8764 /// Set the fTree member for all friend elements.
8765 
8766 void TFriendElement__SetTree(TTree *tree, TList *frlist)
8768  if (frlist) {
8769  TObjLink *lnk = frlist->FirstLink();
8770  while (lnk) {
8771  TFriendElement *elem = (TFriendElement*)lnk->GetObject();
8772  elem->fParentTree = tree;
8773  lnk = lnk->Next();
8774  }
8775  }
8776 }
8777 
8778 ////////////////////////////////////////////////////////////////////////////////
8779 /// Stream a class object.
8780 
8781 void TTree::Streamer(TBuffer& b)
8782 {
8783  if (b.IsReading()) {
8784  UInt_t R__s, R__c;
8785  if (fDirectory) {
8786  fDirectory->Remove(this);
8787  //delete the file cache if it points to this Tree
8788  TFile *file = fDirectory->GetFile();
8789  MoveReadCache(file,0);
8790  }
8791  fDirectory = 0;
8794  Version_t R__v = b.ReadVersion(&R__s, &R__c);
8795  if (R__v > 4) {
8796  b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
8797 
8798  fBranches.SetOwner(kTRUE); // True needed only for R__v < 19 and most R__v == 19
8799 
8800  if (fBranchRef) fBranchRef->SetTree(this);
8803 
8804  if (fTreeIndex) {
8805  fTreeIndex->SetTree(this);
8806  }
8807  if (fIndex.fN) {
8808  Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
8809  fIndex.Set(0);
8810  fIndexValues.Set(0);
8811  }
8812  if (fEstimate <= 10000) {
8813  fEstimate = 1000000;
8814  }
8815  if (GetCacheAutoSize() != 0) {
8816  // a cache will be automatically created.
8817  // No need for TTreePlayer::Process to enable the cache
8818  fCacheSize = 0;
8819  } else if (fAutoFlush < 0) {
8820  // If there is no autoflush set, let's keep the cache completely
8821  // disable by default for now.
8823  } else if (fAutoFlush != 0) {
8824  // Estimate the cluster size.
8825  // This will allow TTree::Process to enable the cache.
8826  if (fZipBytes != 0) {
8828  } else if (fTotBytes != 0) {
8830  } else {
8831  fCacheSize = 30000000;
8832  }
8833  if (fCacheSize >= (INT_MAX / 4)) {
8834  fCacheSize = INT_MAX / 4;
8835  } else if (fCacheSize == 0) {
8836  fCacheSize = 30000000;
8837  }
8838  } else {
8839  fCacheSize = 0;
8840  }
8842  return;
8843  }
8844  //====process old versions before automatic schema evolution
8845  Stat_t djunk;
8846  Int_t ijunk;
8847  TNamed::Streamer(b);
8848  TAttLine::Streamer(b);
8849  TAttFill::Streamer(b);
8850  TAttMarker::Streamer(b);
8851  b >> fScanField;
8852  b >> ijunk; fMaxEntryLoop = (Long64_t)ijunk;
8853  b >> ijunk; fMaxVirtualSize = (Long64_t)ijunk;
8854  b >> djunk; fEntries = (Long64_t)djunk;
8855  b >> djunk; fTotBytes = (Long64_t)djunk;
8856  b >> djunk; fZipBytes = (Long64_t)djunk;
8857  b >> ijunk; fAutoSave = (Long64_t)ijunk;
8858  b >> ijunk; fEstimate = (Long64_t)ijunk;
8859  if (fEstimate <= 10000) fEstimate = 1000000;
8860  fBranches.Streamer(b);
8861  if (fBranchRef) fBranchRef->SetTree(this);
8863  fLeaves.Streamer(b);
8865  if (R__v > 1) fIndexValues.Streamer(b);
8866  if (R__v > 2) fIndex.Streamer(b);
8867  if (R__v > 3) {
8868  TList OldInfoList;
8869  OldInfoList.Streamer(b);
8870  OldInfoList.Delete();
8871  }
8872  fNClusterRange = 0;
8873  fDefaultEntryOffsetLen = 1000;
8875  b.CheckByteCount(R__s, R__c, TTree::IsA());
8876  //====end of old versions
8877  } else {
8878  if (fBranchRef) {
8879  fBranchRef->Clear();
8880  }
8881  TRefTable *table = TRefTable::GetRefTable();
8882  if (table) TRefTable::SetRefTable(0);
8883 
8884  b.WriteClassBuffer(TTree::Class(), this);
8885 
8886  if (table) TRefTable::SetRefTable(table);
8887  }
8888 }
8889 
8890 ////////////////////////////////////////////////////////////////////////////////
8891 /// Unbinned fit of one or more variable(s) from a tree.
8892 ///
8893 /// funcname is a TF1 function.
8894 ///
8895 /// See TTree::Draw for explanations of the other parameters.
8896 ///
8897 /// Fit the variable varexp using the function funcname using the
8898 /// selection cuts given by selection.
8899 ///
8900 /// The list of fit options is given in parameter option.
8901 ///
8902 /// - option = "Q" Quiet mode (minimum printing)
8903 /// - option = "V" Verbose mode (default is between Q and V)
8904 /// - option = "E" Perform better Errors estimation using Minos technique
8905 /// - option = "M" More. Improve fit results
8906 ///
8907 /// You can specify boundary limits for some or all parameters via
8908 /// ~~~ {.cpp}
8909 /// func->SetParLimits(p_number, parmin, parmax);
8910 /// ~~~
8911 /// if parmin>=parmax, the parameter is fixed
8912 ///
8913 /// Note that you are not forced to fix the limits for all parameters.
8914 /// For example, if you fit a function with 6 parameters, you can do:
8915 /// ~~~ {.cpp}
8916 /// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
8917 /// func->SetParLimits(4,-10,-4);
8918 /// func->SetParLimits(5, 1,1);
8919 /// ~~~
8920 /// With this setup:
8921 ///
8922 /// - Parameters 0->3 can vary freely
8923 /// - Parameter 4 has boundaries [-10,-4] with initial value -8
8924 /// - Parameter 5 is fixed to 100.
8925 ///
8926 /// For the fit to be meaningful, the function must be self-normalized.
8927 ///
8928 /// i.e. It must have the same integral regardless of the parameter
8929 /// settings. Otherwise the fit will effectively just maximize the
8930 /// area.
8931 ///
8932 /// It is mandatory to have a normalization variable
8933 /// which is fixed for the fit. e.g.
8934 /// ~~~ {.cpp}
8935 /// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
8936 /// f1->SetParameters(1, 3.1, 0.01);
8937 /// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
8938 /// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
8939 /// ~~~
8940 /// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
8941 ///
8942 /// Return status:
8943 ///
8944 /// - The function return the status of the fit in the following form
8945 /// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
8946 /// - The fitResult is 0 is the fit is OK.
8947 /// - The fitResult is negative in case of an error not connected with the fit.
8948 /// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
8949 /// - If the number of selected entries is null the function returns -1
8950 
8951 Int_t TTree::UnbinnedFit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
8953  GetPlayer();
8954  if (fPlayer) {
8955  return fPlayer->UnbinnedFit(funcname, varexp, selection, option, nentries, firstentry);
8956  }
8957  return -1;
8958 }
8959 
8960 ////////////////////////////////////////////////////////////////////////////////
8961 /// Replace current attributes by current style.
8962 
8965  if (gStyle->IsReading()) {
8974  } else {
8983  }
8984 }
8985 
8986 ////////////////////////////////////////////////////////////////////////////////
8987 /// Write this object to the current directory. For more see TObject::Write
8988 /// Write calls TTree::FlushBaskets before writing the tree.
8989 
8990 Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
8992  FlushBaskets();
8993  return TObject::Write(name, option, bufsize);
8994 }
8995 
8996 ////////////////////////////////////////////////////////////////////////////////
8997 /// Write this object to the current directory. For more see TObject::Write
8998 /// If option & kFlushBasket, call FlushBasket before writing the tree.
8999 
9000 Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize)
9002  return ((const TTree*)this)->Write(name, option, bufsize);
9003 }
9004 
9005 ////////////////////////////////////////////////////////////////////////////////
9006 /// \class TTreeFriendLeafIter
9007 ///
9008 /// Iterator on all the leaves in a TTree and its friend
9009 
9011 
9012 ////////////////////////////////////////////////////////////////////////////////
9013 /// Create a new iterator. By default the iteration direction
9014 /// is kIterForward. To go backward use kIterBackward.
9015 
9017 : fTree(const_cast<TTree*>(tree))
9018 , fLeafIter(0)
9019 , fTreeIter(0)
9020 , fDirection(dir)
9021 {
9022 }
9023 
9024 ////////////////////////////////////////////////////////////////////////////////
9025 /// Copy constructor. Does NOT copy the 'cursor' location!
9026 
9028 : TIterator(iter)
9029 , fTree(iter.fTree)
9030 , fLeafIter(0)
9031 , fTreeIter(0)
9032 , fDirection(iter.fDirection)
9033 {
9034 }
9035 
9036 ////////////////////////////////////////////////////////////////////////////////
9037 /// Overridden assignment operator. Does NOT copy the 'cursor' location!
9038 
9041  if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
9042  const TTreeFriendLeafIter &rhs1 = (const TTreeFriendLeafIter &)rhs;
9043  fDirection = rhs1.fDirection;
9044  }
9045  return *this;
9046 }
9047 
9048 ////////////////////////////////////////////////////////////////////////////////
9049 /// Overridden assignment operator. Does NOT copy the 'cursor' location!
9050 
9053  if (this != &rhs) {
9054  fDirection = rhs.fDirection;
9055  }
9056  return *this;
9057 }
9058 
9059 ////////////////////////////////////////////////////////////////////////////////
9060 /// Go the next friend element
9061 
9064  if (!fTree) return 0;
9065 
9066  TObject * next;
9067  TTree * nextTree;
9068 
9069  if (!fLeafIter) {
9070  TObjArray *list = fTree->GetListOfLeaves();
9071  if (!list) return 0; // Can happen with an empty chain.
9072  fLeafIter = list->MakeIterator(fDirection);
9073  if (!fLeafIter) return 0;
9074  }
9075 
9076  next = fLeafIter->Next();
9077  if (!next) {
9078  if (!fTreeIter) {
9079  TCollection * list = fTree->GetListOfFriends();
9080  if (!list) return next;
9081  fTreeIter = list->MakeIterator(fDirection);
9082  if (!fTreeIter) return 0;
9083  }
9084  TFriendElement * nextFriend = (TFriendElement*) fTreeIter->Next();
9085  ///nextTree = (TTree*)fTreeIter->Next();
9086  if (nextFriend) {
9087  nextTree = const_cast<TTree*>(nextFriend->GetTree());
9088  if (!nextTree) return Next();
9089  SafeDelete(fLeafIter);
9090  fLeafIter = nextTree->GetListOfLeaves()->MakeIterator(fDirection);
9091  if (!fLeafIter) return 0;
9092  next = fLeafIter->Next();
9093  }
9094  }
9095  return next;
9096 }
9097 
9098 ////////////////////////////////////////////////////////////////////////////////
9099 /// Returns the object option stored in the list.
9100 
9103  if (fLeafIter) return fLeafIter->GetOption();
9104  return "";
9105 }
A zero length substring is legal.
Definition: TString.h:83
TString fTitle
Definition: TNamed.h:37
TTree * fParentTree
! pointer to the parent TTree
void Add(TObject *obj, const char *name=0, Int_t check=-1)
Add object with name to browser.
Definition: TBrowser.cxx:261
virtual Int_t GetLen() const
Return the number of effective elements of this leaf.
Definition: TLeaf.cxx:278
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:47
virtual void UpdateAddress()
Definition: TBranch.h:219
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
virtual TBranch * FindBranch(const char *name)
Return the branch that correspond to the path &#39;branchname&#39;, which can include the name of the tree or...
Definition: TTree.cxx:4557
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:830
virtual Bool_t GetReapplyCut() const
Definition: TEventList.h:59
Double_t fWeight
Tree weight (see TTree::SetWeight)
Definition: TTree.h:106
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
Return the line style.
Definition: TAttLine.h:40
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition: TAttFill.h:36
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:37
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition: TAttLine.h:49
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:865
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:5830
A TFolder object is a collection of objects and folders.
Definition: TFolder.h:32
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch after a Merge operation (drop data but keep customizations) TRefTable is cleared...
Definition: TBranchRef.cxx:198
virtual TList * GetListOfClones()
Definition: TTree.h:415
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3449
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:2551
An array of TObjects.
Definition: TObjArray.h:39
static TDataType * GetDataType(EDataType type)
Given a EDataType type, get the TDataType* that represents it.
Definition: TDataType.cxx:440
Long64_t fDebugMin
! First entry number to debug
Definition: TTree.h:128
Principal Components Analysis (PCA)
Definition: TPrincipal.h:28
virtual Long64_t GetAutoSave() const
Definition: TTree.h:378
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:191
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:405
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition: TBranch.cxx:2663
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2229
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:2068
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:6532
virtual const char * GetFriendAlias(TTree *) const
If the &#39;tree&#39; is a friend, this method returns its alias name.
Definition: TTree.cxx:5553
Bool_t MemoryFull(Int_t nbytes)
Check if adding nbytes to memory we are still below MaxVirtualsize.
Definition: TTree.cxx:6339
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:1471
virtual Int_t MakeCode(const char *filename=0)
Generate a skeleton function for this tree.
Definition: TTree.cxx:6142
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:1478
virtual Int_t MakeReader(const char *classname, Option_t *option)=0
virtual const char * GetName() const
Return name of this collection.
This namespace contains pre-defined functions to be used in conjuction with TExecutor::Map and TExecu...
Definition: StringConv.hxx:21
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition: TTree.cxx:8709
Bool_t IsReading() const
Definition: TBuffer.h:83
virtual void SetBranchStatus(const char *bname, Bool_t status=1, UInt_t *found=0)
Set branch status to Process or DoNotProcess.
Definition: TTree.cxx:7865
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:488
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:158
virtual void IncrementTotalBuffers(Int_t nbytes)
Definition: TTree.h:471
short Version_t
Definition: RtypesCore.h:61
virtual void Delete(Option_t *option="")
Delete this tree from memory or/and disk.
Definition: TTree.cxx:3562
virtual const char * GetMinorName() const =0
Int_t GetType() const
Definition: TDataType.h:70
A Branch for the case of an object.
Definition: TBranchObject.h:28
Ssiz_t Length() const
Definition: TString.h:390
TObjArray * GetListOfBaskets()
Definition: TBranch.h:177
TLine * line
static Int_t fgBranchStyle
Old/New branch style.
Definition: TTree.h:156
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:5946
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:298
float Float_t
Definition: RtypesCore.h:53
virtual Int_t GetExpectedType(TClass *&clptr, EDataType &type)
Fill expectedClass and expectedType with information on the data type of the object/values contained ...
Definition: TBranch.cxx:1381
static Long64_t GetMaxTreeSize()
Static function which returns the tree file size limit in bytes.
Definition: TTree.cxx:5777
virtual void SetParallelUnzip(Bool_t opt=kTRUE, Float_t RelSize=-1)
Enable or disable parallel unzipping of Tree buffers.
Definition: TTree.cxx:8550
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:236
return c
A cache when reading files over the network.
const char Option_t
Definition: RtypesCore.h:62
virtual Bool_t Notify()
Function called when loading a new class library.
Definition: TTree.cxx:6508
TTree()
Default constructor and I/O constructor.
Definition: TTree.cxx:649
void GetObject(const char *namecycle, T *&ptr)
Definition: TDirectory.h:147
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:329
virtual Long64_t GetReadEntry() const
Definition: TTree.h:435
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:33
const char * Size
Definition: TXMLSetup.cxx:56
TBuffer * fTransientBuffer
! Pointer to the current transient buffer.
Definition: TTree.h:149
virtual void Flush()
Synchronize a file&#39;s in-memory and on-disk states.
Definition: TFile.cxx:1086
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=0, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition: TFile.cxx:2197
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:4785
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
R__EXTERN TStyle * gStyle
Definition: TStyle.h:418
TList * fFriends
pointer to list of friend elements
Definition: TTree.h:142
void SetHistLineWidth(Width_t width=1)
Definition: TStyle.h:373
TPrincipal * Principal(const char *varexp="", const char *selection="", Option_t *option="np", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Interface to the Principal Components Analysis class.
Definition: TTree.cxx:6670
virtual Int_t Fill()
Fill all branches.
Definition: TTree.cxx:4374
virtual TEntryList * GetEntryList()
Returns the entry list, set to this tree.
Definition: TTree.cxx:5376
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:131
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual TList * GetList() const
Definition: TDirectory.h:157
virtual void DropBaskets(Option_t *option="")
Loop on all branch baskets.
Definition: TBranch.cxx:641
Long64_t GetCacheAutoSize(Bool_t withDefault=kFALSE) const
Used for automatic sizing of the cache.
Definition: TTree.cxx:4991
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5571
static void SetBranchStyle(Int_t style=1)
Set the current branch style.
Definition: TTree.cxx:7991
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:5702
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:5085
TTree * fTree
Definition: TTree.h:189
static Int_t SetParallelUnzip(TTreeCacheUnzip::EParUnzipMode option=TTreeCacheUnzip::kEnable)
Static function that (de)activates multithreading unzipping.
static char DataTypeToChar(EDataType datatype)
Definition: TTree.cxx:426
Double_t Atof() const
Return floating-point value contained in string.
Definition: TString.cxx:2031
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:899
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:50
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:5612
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:1636
virtual void Print(Option_t *option="") const
Print TBranch parameters.
Definition: TBranch.cxx:1746
virtual EDataType GetType() const =0
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
Regular expression class.
Definition: TRegexp.h:35
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition: TTree.h:133
constexpr Float_t kNEntriesResortInv
Definition: TTree.cxx:415
Bool_t IsPersistent() const
Definition: TDataMember.h:89
Int_t fMakeClass
! not zero when processing code generated by MakeClass
Definition: TTree.h:130
#define R__ASSERT(e)
Definition: TError.h:98
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition: TTree.cxx:3546
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
#define gROOT
Definition: TROOT.h:364
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3559
virtual Int_t WriteTObject(const TObject *obj, const char *name=0, Option_t *="", Int_t=0)
See TDirectoryFile::WriteTObject for details.
void ForceWriteInfo(TFile *file, Bool_t force=kFALSE)
Recursively mark streamer infos for writing to a file.
virtual TPrincipal * Principal(const char *varexp="", const char *selection="", Option_t *option="np", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual void SetAutoSave(Long64_t autos=-300000000)
This function may be called at the start of a program to change the default value for fAutoSave (and ...
Definition: TTree.cxx:7676
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:5210
virtual Int_t ReadKeys(Bool_t=kTRUE)
Definition: TDirectory.h:182
Bool_t IsZombie() const
Definition: TObject.h:127
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 &#39;friendname.
Definition: TTree.cxx:5496
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:6270
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
virtual void SetTargetClass(const char *name)
Set the name of the class of the in-memory object into which the data will loaded.
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1089
static TBranch * R__FindBranchHelper(TObjArray *list, const char *branchname)
Search in the array for a branch matching the branch name, with the branch possibly expressed as a &#39;f...
Definition: TTree.cxx:4509
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:6803
TArc * a
Definition: textangle.C:12
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:2511
constexpr std::array< decltype(std::declval< F >)(std::declval< int >))), N > make(F f)
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition: TAttFill.h:44
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:497
virtual Long64_t GetZipBytes() const
Definition: TTree.h:470
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:1160
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:5387
Int_t fScanField
Number of runs before prompting in Scan.
Definition: TTree.h:108
virtual Long64_t GetEND() const
Definition: TFile.h:200
virtual Int_t FlushBaskets() const
Write to disk all the basket that have not yet been individually written.
Definition: TTree.cxx:4799
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:3003
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:3534
const char * Class
Definition: TXMLSetup.cxx:64
virtual TVirtualIndex * GetTreeIndex() const
Definition: TTree.h:444
virtual void KeepCircular()
Keep a maximum of fMaxEntries in memory.
Definition: TTree.cxx:5910
TArrayD fIndexValues
Sorted index values.
Definition: TTree.h:139
Style_t GetHistFillStyle() const
Definition: TStyle.h:235
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:5052
constexpr Int_t kNEntriesResort
Definition: TTree.cxx:414
virtual Long64_t GetEntries(const char *)=0
Long64_t fMaxEntryLoop
Maximum number of entries to process.
Definition: TTree.h:114
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition: TTree.cxx:5816
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition: TTree.h:553
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:6944
Streamer around an arbitrary STL like container, which implements basic container functionality...
void ToHumanReadableSize(value_type bytes, Bool_t si, Double_t *coeff, const char **units)
Return the size expressed in &#39;human readeable&#39; format.
Definition: StringConv.hxx:38
virtual Int_t AddBranch(TBranch *b, Bool_t subgbranches=kFALSE)
Add a branch to the list of branches to be stored in the cache this function is called by TBranch::Ge...
Definition: TTreeCache.cxx:332
virtual Int_t DeleteGlobal(void *obj)=0
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:311
virtual void SetupAddresses()
If the branch address is not set, we set all addresses starting with the top level parent branch...
Definition: TBranch.cxx:2653
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:591
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:996
void Reset()
Definition: TCollection.h:161
void BypassStreamer(Bool_t bypass=kTRUE)
When the kBypassStreamer bit is set, the automatically generated Streamer can call directly TClass::W...
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:739
virtual void Reset(Option_t *option="")
Definition: TBranchRef.cxx:187
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:7338
if object in a list can be deleted
Definition: TObject.h:63
virtual void SetFileNumber(Int_t number=0)
Set fFileNumber to number.
Definition: TTree.cxx:8448
virtual Double_t GetMinimum(const char *columname)
Return minimum of column with name columname.
Definition: TTree.cxx:5787
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:3634
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:3871
virtual void SetTree(TTree *tree)
Definition: TBranch.h:217
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:383
virtual Int_t GetN() const
Definition: TEventList.h:58
virtual void StartViewer()
Start the TTreeViewer on this tree.
Definition: TTree.cxx:8694
virtual TList * GetListOfFriends() const
Definition: TTree.h:418
virtual Long64_t Merge(TCollection *list, Option_t *option="")
Merge the trees in the TList into this tree.
Definition: TTree.cxx:6396
Marker Attributes class.
Definition: TAttMarker.h:24
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:6689
static TVirtualTreePlayer * TreePlayer(TTree *obj)
Static function returning a pointer to a Tree player.
virtual void SetBranchFolder()
virtual TKey * GetKey(const char *, Short_t=9999) const
Definition: TDirectory.h:156
TFileCacheRead * GetCacheRead(TObject *tree=0) const
Return a pointer to the current read cache.
Definition: TFile.cxx:1202
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:953
virtual Int_t GetEntryWithIndex(Int_t major, Int_t minor=0)
Read entry corresponding to major and minor number.
Definition: TTree.cxx:5449
TList * fAliases
List of aliases for expressions based on the tree branches.
Definition: TTree.h:136
EFromHumanReadableSize FromHumanReadableSize(std::string_view str, T &value)
Convert strings like the following into byte counts 5MB, 5 MB, 5M, 3.7GB, 123b, 456kB, 3.7GiB, 5MiB with some amount of forgiveness baked into the parsing.
Definition: StringConv.hxx:86
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:499
virtual TObjArray * GetListOfBranches()
Definition: TTree.h:416
Helper class to iterate over cluster of baskets.
Definition: TTree.h:255
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition: TTree.h:145
Fill Area Attributes class.
Definition: TAttFill.h:24
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in &#39;fromtree&#39; to this tree, including the value of fAuto...
Definition: TTree.cxx:5871
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:7591
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2335
virtual Bool_t HasPointers() const =0
Int_t GetCompressionLevel() const
Definition: TFile.h:366
virtual const char * GetTreeName() const
virtual Long64_t CopyEntries(TTree *tree, Long64_t nentries=-1, Option_t *option="")
Copy nentries from given tree to this tree.
Definition: TTree.cxx:3365
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:7719
void SetHistFillColor(Color_t color=1)
Definition: TStyle.h:369
Int_t fNfill
! Local for EntryLoop
Definition: TTree.h:126
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:8519
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:551
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition: TTree.cxx:5967
Bool_t fCacheUserSet
! true if the cache setting was explicitly given by user
Definition: TTree.h:151
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition: TTree.cxx:8581
Int_t fMaxClusterRange
! Memory allocated for the cluster range.
Definition: TTree.h:112
static Int_t GetBranchStyle()
Static function returning the current branch style.
Definition: TTree.cxx:4979
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4702
virtual Int_t BuildIndex(const char *majorname, const char *minorname="0")
Build a Tree Index (default is TTreeIndex).
Definition: TTree.cxx:2536
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:8952
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:2313
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:1884
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition: TClass.cxx:2525
virtual void Show(Long64_t entry=-1, Int_t lenmax=20)
Print values of all active leaves for entry.
Definition: TTree.cxx:8620
virtual Int_t GetBufferSize() const
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition: TBranch.cxx:907
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor) const =0
TBranchRef * fBranchRef
Branch supporting the TRefTable (if any)
Definition: TTree.h:147
virtual Int_t MakeClass(const char *classname=0, Option_t *option="")
Generate a skeleton analysis class for this tree.
Definition: TTree.cxx:6109
virtual Long64_t GetN() const =0
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:5041
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition: TAttMarker.h:43
const Int_t kDoNotProcess
Definition: TBranch.h:52
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition: TTree.h:148
Data member is a pointer to an array of basic types.
Definition: TLeaf.h:59
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
Timer interval in milliseconds.
Definition: TTree.h:107
Long64_t GetEntries() const
Definition: TBranch.h:183
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition: TTree.cxx:1184
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:1654
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:7494
Long64_t fFlushedBytes
Number of auto-flushed bytes.
Definition: TTree.h:105
TObjArray * GetListOfBranches()
Definition: TBranch.h:178
UInt_t fNEntriesSinceSorting
! Number of entries processed since the last re-sorting of branches
Definition: TTree.h:153
Specialization of TTreeCache for parallel Unzipping.
TBasket * GetBasket(Int_t basket)
Return pointer to basket basketnumber in this Branch.
Definition: TBranch.cxx:1095
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:65
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
Int_t GetNevBuf() const
Definition: TBasket.h:79
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:925
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:5748
void Set(Int_t n)
Set size of this array to n ints.
Definition: TArrayI.cxx:105
virtual void RemoveFriend(TTree *)
Remove a friend from the list of friends.
Definition: TTree.cxx:7377
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:5855
virtual void SetCacheLearnEntries(Int_t n=10)
Interface to TTreeCache to set the number of entries for the learning phase.
Definition: TTree.cxx:8184
A branch containing and managing a TRefTable for TRef autoloading.
Definition: TBranchRef.h:33
Long64_t fZipBytes
Total number of bytes in all branches after compression.
Definition: TTree.h:103
virtual TIterator * MakeIterator(Bool_t dir=kIterForward) const =0
Long64_t fDebugMax
! Last entry number to debug
Definition: TTree.h:129
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:1390
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:8385
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition: TBuffer.cxx:201
void UseCurrentStyle()
Replace current attributes by current style.
Definition: TTree.cxx:8964
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:1984
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:4868
Bool_t fCacheDoAutoInit
! true if cache auto creation or resize check is needed
Definition: TTree.h:150
virtual TFile * GetFile() const
Definition: TDirectory.h:155
Int_t GetRecordHeader(char *buf, Long64_t first, Int_t maxbytes, Int_t &nbytes, Int_t &objlen, Int_t &keylen)
Read the logical record header starting at a certain postion.
Definition: TFile.cxx:1239
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:737
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:91
TObjArray fLeaves
Direct pointers to individual branch leaves.
Definition: TTree.h:135
Long64_t * fClusterRangeEnd
[fNClusterRange] Last entry of a cluster range.
Definition: TTree.h:119
virtual Long64_t GetTotBytes() const
Definition: TTree.h:442
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition: TAttLine.h:46
Bool_t IsReading() const
Definition: TStyle.h:290
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1940
Int_t GetBufferSize() const
Definition: TBasket.h:75
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:41
Int_t fNClusterRange
Number of Cluster range in addition to the one defined by &#39;AutoFlush&#39;.
Definition: TTree.h:111
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:222
Bool_t HasRuleWithSourceClass(const TString &source) const
Return True if we have any rule whose source class is &#39;source&#39;.
virtual char * GetAddress() const
Definition: TBranch.h:147
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition: TTree.h:138
void SetParentClass(TClass *clparent)
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition: TAttMarker.h:38
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:9102
Color_t GetHistFillColor() const
Definition: TStyle.h:233
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:9001
TVirtualStreamerInfo * FindConversionStreamerInfo(const char *onfile_classname, UInt_t checksum) const
Return a Conversion StreamerInfo from the class &#39;classname&#39; for the layout represented by &#39;checksum&#39; ...
Definition: TClass.cxx:6730
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition: TTree.cxx:8426
Width_t GetHistLineWidth() const
Definition: TStyle.h:237
virtual void SetOffset(Int_t offset=0)
Definition: TBranch.h:215
virtual Long64_t Process(const char *filename, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual void UpdateFormulaLeaves()=0
virtual Int_t DropBranch(TBranch *b, Bool_t subbranches=kFALSE)
Remove a branch to the list of branches to be stored in the cache this function is called by TBranch:...
Definition: TTreeCache.cxx:484
void SetHistFillStyle(Style_t styl=0)
Definition: TStyle.h:371
TObjArray * GetElements() const
void SetCompressionSettings(Int_t settings=1)
Set compression settings.
Definition: TBranch.cxx:2191
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
Long64_t fChainOffset
! Offset of 1st entry of this Tree in a TChain
Definition: TTree.h:122
virtual Long64_t GetCacheSize() const
Definition: TTree.h:383
~TFriendLock()
Restore the state of tree the same as before we set the lock.
Definition: TTree.cxx:507
Long64_t * fClusterSize
[fNClusterRange] Number of entries in each cluster for a given range.
Definition: TTree.h:120
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:4356
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:3581
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition: TAttFill.h:42
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:46
void TFriendElement__SetTree(TTree *tree, TList *frlist)
Set the fTree member for all friend elements.
Definition: TTree.cxx:8767
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition: TTree.h:143
virtual Int_t GetTreeNumber() const
Definition: TTree.h:445
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TObjArray.cxx:630
TDirectory * GetDirectory() const
Definition: TTree.h:391
TVirtualStreamerInfo * GetConversionStreamerInfo(const char *onfile_classname, Int_t version) const
Return a Conversion StreamerInfo from the class &#39;classname&#39; for version number &#39;version&#39; to this clas...
Definition: TClass.cxx:6633
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx:496
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:188
virtual Int_t ReadTObject(TObject *, const char *)
Definition: TDirectory.h:183
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:675
Long64_t fReadEntry
! Number of the entry being processed
Definition: TTree.h:123
virtual ~TTree()
Destructor.
Definition: TTree.cxx:828
virtual Color_t GetFillColor() const
Return the fill area color.
Definition: TAttFill.h:35
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:4827
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5059
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1551
TList * fUserInfo
pointer to a list of user objects associated to this Tree
Definition: TTree.h:144
TObjArray fBranches
List of Branches.
Definition: TTree.h:134
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2322
unsigned int UInt_t
Definition: RtypesCore.h:42
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:159
TMarker * m
Definition: textangle.C:8
void InitializeSortedBranches()
Initializes the vector of top-level branches and sorts it by branch size.
Definition: TTree.cxx:5331
static void SetMaxTreeSize(Long64_t maxsize=1900000000)
Set the maximum size in bytes of a Tree file (static function).
Definition: TTree.cxx:8482
virtual Long64_t GetEntry(Int_t index)
Return the number of the entry #index of this TEntryList in the TTree or TChain See also Next()...
Definition: TEntryList.cxx:655
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition: TFile.cxx:1394
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:153
Manages buffers for branches of a Tree.
Definition: TBasket.h:38
virtual const char * GetMajorName() const =0
virtual TBranchRef * GetBranchRef() const
Definition: TTree.h:380
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:4629
The TRealData class manages the effective list of all data members for a given class.
Definition: TRealData.h:34
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all leaves of entry and return total number of bytes read.
Definition: TBranch.cxx:1217
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5432
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:358
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
TArrayI fIndex
Index of sorted values.
Definition: TTree.h:140
TSubString Strip(EStripType s=kTrailing, char c= ' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1070
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition: TAttMarker.h:45
static void SetLearnEntries(Int_t n=10)
Static function to set the number of entries to be used in learning mode The default value for n is 1...
Bool_t fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition: TTree.h:152
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:7465
Bool_t fDirection
iteration direction
Definition: TTree.h:590
virtual Color_t GetLineColor() const
Return the line color.
Definition: TAttLine.h:39
TEventList * fEventList
! Pointer to event selection list (if one)
Definition: TTree.h:137
TString fName
Definition: TNamed.h:36
virtual TBranch * Bronch(const char *name, const char *classname, void *addobj, Int_t bufsize=32000, Int_t splitlevel=99)
Create a new TTree BranchElement.
Definition: TTree.cxx:2214
if object destructor must call RecursiveRemove()
Definition: TObject.h:64
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition: TAttMarker.h:46
Long64_t fMaxEntries
Maximum number of entries in case of circular buffers.
Definition: TTree.h:113
TTree * GetTree() const
Definition: TBranch.h:184
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:1099
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2241
virtual void KeepCircular(Long64_t maxEntries)
keep a maximum of fMaxEntries in memory
Definition: TBranch.cxx:1691
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:7014
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 &#39;bname&#39; from the Tree cache.
Definition: TTree.cxx:1022
Int_t GetCompressionSettings() const
Definition: TFile.h:372
Long64_t fAutoSave
Autosave tree when fAutoSave entries written or -fAutoSave (compressed) bytes produced.
Definition: TTree.h:116
virtual void SaveSelf(Bool_t=kFALSE)
Definition: TDirectory.h:189
virtual void SetBasketSize(Int_t buffsize)
Set the basket size The function makes sure that the basket size is greater than fEntryOffsetlen.
Definition: TBranch.cxx:2115
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:2739
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:8247
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:6881
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&#39;s memory.
Definition: TClass.cxx:5545
virtual Int_t GetBasketSize() const
Definition: TBranch.h:152
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:7041
virtual void DropBuffers(Int_t nbytes)
Drop branch buffers to accommodate nbytes below MaxVirtualsize.
Definition: TTree.cxx:4306
virtual Int_t Fill()
Fill the branch basket with the referenced objects parent numbers.
Definition: TBranchRef.cxx:103
virtual void SetMakeClass(Int_t make)
Set all the branches in this TTree to be in decomposed object mode (also known as MakeClass mode)...
Definition: TTree.cxx:8462
virtual void SetWeight(Double_t w=1, Option_t *option="")
Set tree weight.
Definition: TTree.cxx:8609
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition: TTree.cxx:598
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor) const =0
virtual Int_t GetSize() const
Definition: TCollection.h:95
virtual void SetDirectory(TDirectory *dir)
Change the tree&#39;s directory.
Definition: TTree.cxx:8285
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:6059
virtual void SetEstimate(Long64_t n)=0
virtual Long64_t GetAutoFlush() const
Definition: TTree.h:377
Long64_t fMaxVirtualSize
Maximum total size of buffers kept in memory.
Definition: TTree.h:115
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
#define ClassImp(name)
Definition: Rtypes.h:279
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:8362
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator. Does NOT copy the &#39;cursor&#39; location!
Definition: TTree.cxx:9040
virtual void ResetAddress()
Reset the address of the branch.
Definition: TBranch.cxx:2037
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:416
double Double_t
Definition: RtypesCore.h:55
virtual void Clear(Option_t *option="")
Clear entries in the TRefTable.
Definition: TBranchRef.cxx:95
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
Definition: TRefTable.cxx:287
virtual TClass * GetValueClass() const =0
void SetHistLineStyle(Style_t styl=0)
Definition: TStyle.h:372
Long64_t fTotBytes
Total number of bytes in all branches before compression.
Definition: TTree.h:102
virtual void WaitFinishPrefetch()
virtual Int_t GetLenType() const
Definition: TLeaf.h:75
TClass * GetClass() const
Definition: TClonesArray.h:57
Describe directory structure in memory.
Definition: TDirectory.h:44
virtual void SetPerfStats(TVirtualPerfStats *perf)
Set perf stats.
Definition: TTree.cxx:8564
std::vector< std::pair< Long64_t, TBranch * > > fSortedBranches
! Branches sorted by average task time
Definition: TTree.h:154
static void TBranch__SetTree(TTree *tree, TObjArray &branches)
Set the fTree member for all branches and sub branches.
Definition: TTree.cxx:8743
void SortBranchesByTime()
Sorts top-level branches by the last average task time recorded per branch.
Definition: TTree.cxx:5355
virtual Long64_t GetEntriesFast() const
Definition: TTree.h:394
R__EXTERN TEnv * gEnv
Definition: TEnv.h:174
unsigned long long ULong64_t
Definition: RtypesCore.h:70
TNamed()
Definition: TNamed.h:40
Long64_t fAutoFlush
Auto-flush tree when fAutoFlush entries written or -fAutoFlush (compressed) bytes produced...
Definition: TTree.h:117
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition: TTree.cxx:7475
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:366
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
Initial Length of fEntryOffset table in the basket buffers.
Definition: TTree.h:110
const std::type_info * GetTypeInfo() const
Definition: TClass.h:451
virtual TTree * GetTree() const
Definition: TTree.h:443
void Browse(TBrowser *b)
Browse this collection (called by TBrowser).
Int_t GetNleaves() const
Definition: TBranch.h:181
Color_t GetHistLineColor() const
Definition: TStyle.h:234
TObjArray * GetListOfLeaves()
Definition: TBranch.h:179
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:494
Long64_t fEstimate
Number of entries to estimate histogram limits.
Definition: TTree.h:118
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:190
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition: TTree.h:186
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:2882
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:8007
Int_t fDebug
! Debug level
Definition: TTree.h:127
EOnIndexError
Definition: TTree.cxx:3262
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:8033
double Stat_t
Definition: RtypesCore.h:73
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition: TAttLine.h:48
virtual Int_t GetOffset() const
Definition: TLeaf.h:79
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2811
virtual void SetBasketSize(const char *bname, Int_t buffsize=16000)
Set a branch&#39;s basket size.
Definition: TTree.cxx:7692
virtual TFile * GetFile()
Return pointer to TFile containing this friend TTree.
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition: TTree.cxx:2138
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data)...
Definition: TTree.cxx:7434
virtual Bool_t SetAlias(const char *aliasName, const char *aliasFormula)
Set a tree variable alias.
Definition: TTree.cxx:7536
Int_t fFileNumber
! current file number (if file extensions)
Definition: TTree.h:131
Mother of all ROOT objects.
Definition: TObject.h:44
virtual Long64_t ReadFile(const char *filename, const char *branchDescriptor="", char delimiter= ' ')
Create or simply read branches from filename.
Definition: TTree.cxx:6995
Int_t fUpdate
Update frequency for EntryLoop.
Definition: TTree.h:109
A Branch handling STL collection of pointers (vectors, lists, queues, sets and multisets) while stori...
Definition: TBranchSTL.h:22
static void * ReAlloc(void *vp, size_t size)
Reallocate (i.e.
Definition: TStorage.cxx:178
virtual Int_t Branch(TCollection *list, Int_t bufsize=32000, Int_t splitlevel=99, const char *name="")
Create one branch for each element in the collection.
Definition: TTree.cxx:1651
TDirectory * fOutputDirectory
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:557
virtual void SetEntryOffsetLen(Int_t len, Bool_t updateSubBranches=kFALSE)
Update the default value for the branch&#39;s fEntryOffsetLen if and only if it was already non zero (and...
Definition: TBranch.cxx:2207
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:2249
Long64_t fEntries
Number of entries.
Definition: TTree.h:101
Int_t BufferSize() const
Definition: TBuffer.h:94
TList * fClones
! List of cloned trees which share our addresses
Definition: TTree.h:146
Int_t GetMaxBaskets() const
Definition: TBranch.h:180
virtual void Refresh(TBranch *b)
Refresh this branch using new information in b This function is called by TTree::Refresh.
Definition: TBranch.cxx:1894
virtual Int_t MakeSelector(const char *selector=0, Option_t *option="")
Generate skeleton selector class for this tree.
Definition: TTree.cxx:6324
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TObjArray.cxx:479
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:917
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition: TAttMarker.h:36
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:435
virtual Int_t DropBuffers()
Drop buffers of this basket if it is not the current basket.
Definition: TBasket.cxx:187
ROOT::ESTLType IsSTLContainer()
Return which type (if any) of STL container the data member is.
Definition: TBaseClass.cxx:101
Abstract base class defining the interface for the plugins that implement Draw, Scan, Process, MakeProxy, etc.
A Branch for the case of an array of clone objects.
Definition: TBranchClones.h:31
virtual void * GetValuePointer() const
Definition: TLeaf.h:80
virtual void Add(TObject *obj)
Definition: TList.h:81
const Ssiz_t kNPOS
Definition: Rtypes.h:115
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition: TROOT.cxx:545
TClusterIterator(TTree *tree, Long64_t firstEntry)
Regular constructor.
Definition: TTree.cxx:524
Int_t Length() const
Definition: TBuffer.h:96
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition: TList.cxx:635
Definition: file.py:1
Int_t GetClassVersion()
virtual TObject ** GetObjectRef(const TObject *obj) const =0
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:1943
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:171
Iterator on all the leaves in a TTree and its friend.
Definition: TTree.h:584
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:2222
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:7307
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
virtual Int_t LoadBaskets()
Baskets associated to this branch are forced to be in memory.
Definition: TBranch.cxx:1717
#define NULL
Definition: Rtypes.h:82
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1841
#define snprintf
Definition: civetweb.c:822
#define gPad
Definition: TVirtualPad.h:289
virtual void SetCircular(Long64_t maxEntries)
Enable/Disable circularity for this tree.
Definition: TTree.cxx:8211
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:7403
ROOT::ESTLType GetCollectionType() const
Return the &#39;type&#39; of the STL the TClass is representing.
Definition: TClass.cxx:2800
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
Definition: tree.py:1
std::atomic< Long64_t > fTotalBuffers
! Total number of bytes in branch buffers
Definition: TTree.h:124
TObject * fNotify
! Object to be notified when loading a Tree
Definition: TTree.h:132
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition: TTree.cxx:8150
void Add(TObject *obj)
Definition: TObjArray.h:75
virtual Long64_t GetEntries() const
Definition: TTree.h:392
A TTree object has a header with a name and a title.
Definition: TTree.h:98
#define gDirectory
Definition: TDirectory.h:221
TVirtualIndex * fTreeIndex
Pointer to the tree Index (if any)
Definition: TTree.h:141
TFriendLock & operator=(const TFriendLock &)
Assignment operator.
Definition: TTree.cxx:494
Int_t SetBranchAddressImp(TBranch *branch, void *addr, TBranch **ptr)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:7776
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:158
virtual void SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting=kFALSE)
Update the default value for the branch&#39;s fEntryOffsetLen.
Definition: TTree.cxx:8259
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4598
Int_t GetMakeClass() const
Definition: TTree.h:423
TObject * Next()
Go the next friend element.
Definition: TTree.cxx:9063
Definition: first.py:1
virtual void DropBaskets()
Remove some baskets from memory.
Definition: TTree.cxx:4293
Int_t FlushBaskets()
Flush to disk all the baskets of this branch and any of subbranches.
Definition: TBranch.cxx:1008
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:5596
static Long64_t fgMaxTreeSize
Maximum size of a file containing a Tree.
Definition: TTree.h:157
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
virtual void WriteHeader()
Write File Header.
Definition: TFile.cxx:2416
virtual Long64_t GetEntryNumberFriend(const TTree *)=0
virtual TFile * GetFile(Int_t mode=0)
Return pointer to the file where branch buffers reside, returns 0 in case branch buffers reside in th...
Definition: TBranch.cxx:1400
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition: TTree.cxx:8330
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:517
virtual void Compress()
Remove empty slots from array.
Definition: TObjArray.cxx:309
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:2626
virtual Int_t Occurence(const TObject *obj) const
Return occurence number of object in the list of objects of this folder.
Definition: TFolder.cxx:436
static TTree * MergeTrees(TList *list, Option_t *option="")
Static function merging the trees in the TList into a new tree.
Definition: TTree.cxx:6353
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:4964
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition: TAttMarker.h:37
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
Return the line width.
Definition: TAttLine.h:41
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:460
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:155
void SetHistLineColor(Color_t color=1)
Definition: TStyle.h:370
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:5412
virtual Int_t AddBranchToCache(const char *bname, Bool_t subbranches=kFALSE)
Add branch with name bname to the Tree cache.
Definition: TTree.cxx:939
Int_t fPacketSize
! Number of entries in one packet for parallel root
Definition: TTree.h:125
void Set(Int_t n)
Set size of this array to n doubles.
Definition: TArrayD.cxx:105
const Int_t n
Definition: legend1.C:16
TString & String()
Definition: TString.h:122
virtual Long64_t Project(const char *hname, const char *varexp, const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Make a projection of a tree using selections.
Definition: TTree.cxx:6929
Line Attributes class.
Definition: TAttLine.h:24
Int_t GetWriteBasket() const
Definition: TBranch.h:171
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Definition: TMath.h:931
char name[80]
Definition: TGX11.cxx:109
TFriendLock(const TFriendLock &)
Copy constructor.
Definition: TTree.cxx:484
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:467
Int_t GetReadBasket() const
Definition: TBranch.h:169
virtual void SetName(const char *name)
Change the name of this tree.
Definition: TTree.cxx:8490
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:567
void MoveReadCache(TFile *src, TDirectory *dir)
Move a cache from a file to the current file in dir.
Definition: TTree.cxx:6486
virtual void CopyAddresses(TTree *, Bool_t undo=kFALSE)
Set branch addresses of passed tree equal to ours.
Definition: TTree.cxx:3158
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:417
static void ResetCount()
Static function resetting fgCount.
Definition: TBranch.cxx:2060
Long64_t fSavedBytes
Number of autosaved bytes.
Definition: TTree.h:104
Long64_t fCacheSize
! Maximum size of file buffers
Definition: TTree.h:121
virtual void Print(Option_t *option="") const
Print the TRefTable branch.
Definition: TBranchRef.cxx:159
virtual Long64_t AutoSave(Option_t *option="")
AutoSave tree header every fAutoSave bytes.
Definition: TTree.cxx:1336
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:911