Logo ROOT   6.12/06
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 "ROOT/TIOFeatures.hxx"
340 #include "TArrayC.h"
341 #include "TBufferFile.h"
342 #include "TBaseClass.h"
343 #include "TBasket.h"
344 #include "TBranchClones.h"
345 #include "TBranchElement.h"
346 #include "TBranchObject.h"
347 #include "TBranchRef.h"
348 #include "TBrowser.h"
349 #include "TClass.h"
350 #include "TClassEdit.h"
351 #include "TClonesArray.h"
352 #include "TCut.h"
353 #include "TDataMember.h"
354 #include "TDataType.h"
355 #include "TDirectory.h"
356 #include "TError.h"
357 #include "TEntryList.h"
358 #include "TEnv.h"
359 #include "TEventList.h"
360 #include "TFile.h"
361 #include "TFolder.h"
362 #include "TFriendElement.h"
363 #include "TInterpreter.h"
364 #include "TLeaf.h"
365 #include "TLeafB.h"
366 #include "TLeafC.h"
367 #include "TLeafD.h"
368 #include "TLeafElement.h"
369 #include "TLeafF.h"
370 #include "TLeafI.h"
371 #include "TLeafL.h"
372 #include "TLeafObject.h"
373 #include "TLeafS.h"
374 #include "TList.h"
375 #include "TMath.h"
376 #include "TROOT.h"
377 #include "TRealData.h"
378 #include "TRegexp.h"
379 #include "TStreamerElement.h"
380 #include "TStreamerInfo.h"
381 #include "TStyle.h"
382 #include "TSystem.h"
383 #include "TTreeCloner.h"
384 #include "TTreeCache.h"
385 #include "TTreeCacheUnzip.h"
386 #include "TVirtualCollectionProxy.h"
388 #include "TVirtualFitter.h"
389 #include "TVirtualIndex.h"
390 #include "TVirtualPerfStats.h"
391 #include "TVirtualPad.h"
392 #include "TBranchSTL.h"
393 #include "TSchemaRuleSet.h"
394 #include "TFileMergeInfo.h"
395 #include "ROOT/StringConv.hxx"
396 #include "TVirtualMutex.h"
397 
398 #include "TBranchIMTHelper.h"
399 
400 #include <chrono>
401 #include <cstddef>
402 #include <iostream>
403 #include <fstream>
404 #include <sstream>
405 #include <string>
406 #include <stdio.h>
407 #include <limits.h>
408 #include <algorithm>
409 
410 #ifdef R__USE_IMT
411 #include "ROOT/TThreadExecutor.hxx"
412 #include <thread>
413 #include <string>
414 #include <sstream>
415 #endif
416 
417 constexpr Int_t kNEntriesResort = 100;
420 Int_t TTree::fgBranchStyle = 1; // Use new TBranch style with TBranchElement.
421 Long64_t TTree::fgMaxTreeSize = 100000000000LL;
422 
423 ClassImp(TTree);
424 
425 ////////////////////////////////////////////////////////////////////////////////
426 ////////////////////////////////////////////////////////////////////////////////
427 ////////////////////////////////////////////////////////////////////////////////
428 
429 static char DataTypeToChar(EDataType datatype)
430 {
431  // Return the leaflist 'char' for a given datatype.
432 
433  switch(datatype) {
434  case kChar_t: return 'B';
435  case kUChar_t: return 'b';
436  case kBool_t: return 'O';
437  case kShort_t: return 'S';
438  case kUShort_t: return 's';
439  case kCounter:
440  case kInt_t: return 'I';
441  case kUInt_t: return 'i';
442  case kDouble_t:
443  case kDouble32_t: return 'D';
444  case kFloat_t:
445  case kFloat16_t: return 'F';
446  case kLong_t: return 0; // unsupported
447  case kULong_t: return 0; // unsupported?
448  case kchar: return 0; // unsupported
449  case kLong64_t: return 'L';
450  case kULong64_t: return 'l';
451 
452  case kCharStar: return 'C';
453  case kBits: return 0; //unsupported
454 
455  case kOther_t:
456  case kNoType_t:
457  default:
458  return 0;
459  }
460  return 0;
461 }
462 
463 ////////////////////////////////////////////////////////////////////////////////
464 /// \class TTree::TFriendLock
465 /// Helper class to prevent infinite recursion in the usage of TTree Friends.
466 
467 ////////////////////////////////////////////////////////////////////////////////
468 /// Record in tree that it has been used while recursively looks through the friends.
469 
471 : fTree(tree)
472 {
473  // We could also add some code to acquire an actual
474  // lock to prevent multi-thread issues
475  fMethodBit = methodbit;
476  if (fTree) {
477  fPrevious = fTree->fFriendLockStatus & fMethodBit;
478  fTree->fFriendLockStatus |= fMethodBit;
479  } else {
480  fPrevious = 0;
481  }
482 }
483 
484 ////////////////////////////////////////////////////////////////////////////////
485 /// Copy constructor.
486 
488  fTree(tfl.fTree),
489  fMethodBit(tfl.fMethodBit),
490  fPrevious(tfl.fPrevious)
491 {
492 }
493 
494 ////////////////////////////////////////////////////////////////////////////////
495 /// Assignment operator.
496 
498 {
499  if(this!=&tfl) {
500  fTree=tfl.fTree;
502  fPrevious=tfl.fPrevious;
503  }
504  return *this;
505 }
506 
507 ////////////////////////////////////////////////////////////////////////////////
508 /// Restore the state of tree the same as before we set the lock.
509 
511 {
512  if (fTree) {
513  if (!fPrevious) {
514  fTree->fFriendLockStatus &= ~(fMethodBit & kBitMask);
515  }
516  }
517 }
518 
519 ////////////////////////////////////////////////////////////////////////////////
520 /// \class TTree::TClusterIterator
521 /// Helper class to iterate over cluster of baskets.
522 
523 ////////////////////////////////////////////////////////////////////////////////
524 /// Regular constructor.
525 /// TTree is not set as const, since we might modify if it is a TChain.
526 
527 TTree::TClusterIterator::TClusterIterator(TTree *tree, Long64_t firstEntry) : fTree(tree), fClusterRange(0), fStartEntry(0), fNextEntry(0)
528 {
529  if ( fTree->GetAutoFlush() <= 0 ) {
530  // Case of old files before November 9 2009
531  fStartEntry = firstEntry;
532  } else if (fTree->fNClusterRange) {
533  // Find the correct cluster range.
534  //
535  // Since fClusterRangeEnd contains the inclusive upper end of the range, we need to search for the
536  // range that was containing the previous entry and add 1 (because BinarySearch consider the values
537  // to be the inclusive start of the bucket).
538  fClusterRange = TMath::BinarySearch(fTree->fNClusterRange, fTree->fClusterRangeEnd, firstEntry - 1) + 1;
539 
540  Long64_t entryInRange;
541  Long64_t pedestal;
542  if (fClusterRange == 0) {
543  pedestal = 0;
544  entryInRange = firstEntry;
545  } else {
546  pedestal = fTree->fClusterRangeEnd[fClusterRange-1] + 1;
547  entryInRange = firstEntry - pedestal;
548  }
549  Long64_t autoflush;
550  if (fClusterRange == fTree->fNClusterRange) {
551  autoflush = fTree->fAutoFlush;
552  } else {
553  autoflush = fTree->fClusterSize[fClusterRange];
554  }
555  if (autoflush == 0) {
556  autoflush = GetEstimatedClusterSize();
557  }
558  fStartEntry = pedestal + entryInRange - entryInRange%autoflush;
559  } else {
560  fStartEntry = firstEntry - firstEntry%fTree->GetAutoFlush();
561  }
562  fNextEntry = fStartEntry; // Position correctly for the first call to Next()
563 }
564 
565 ////////////////////////////////////////////////////////////////////////////////
566 /// In the case where the cluster size was not fixed (old files and
567 /// case where autoflush was explicitly set to zero, we need estimate
568 /// a cluster size in relation to the size of the cache.
569 
571 {
572  Long64_t zipBytes = fTree->GetZipBytes();
573  if (zipBytes == 0) {
574  return fTree->GetEntries() - 1;
575  } else {
576  Long64_t clusterEstimate = 1;
577  Long64_t cacheSize = fTree->GetCacheSize();
578  if (cacheSize == 0) {
579  // Humm ... let's double check on the file.
580  TFile *file = fTree->GetCurrentFile();
581  if (file) {
582  TFileCacheRead *cache = file->GetCacheRead(fTree);
583  if (cache) {
584  cacheSize = cache->GetBufferSize();
585  }
586  }
587  }
588  if (cacheSize > 0) {
589  clusterEstimate = fTree->GetEntries() * cacheSize / zipBytes;
590  if (clusterEstimate == 0)
591  clusterEstimate = 1;
592  }
593  return clusterEstimate;
594  }
595 }
596 
597 ////////////////////////////////////////////////////////////////////////////////
598 /// Move on to the next cluster and return the starting entry
599 /// of this next cluster
600 
602 {
603  fStartEntry = fNextEntry;
604  if ( fTree->GetAutoFlush() <= 0 ) {
605  // Case of old files before November 9 2009
606  Long64_t clusterEstimate = GetEstimatedClusterSize();
607  fNextEntry = fStartEntry + clusterEstimate;
608  } else {
609  if (fClusterRange == fTree->fNClusterRange) {
610  // We are looking at a range which size
611  // is defined by AutoFlush itself and goes to the GetEntries.
612  fNextEntry += fTree->GetAutoFlush();
613  } else {
614  if (fStartEntry > fTree->fClusterRangeEnd[fClusterRange]) {
615  ++fClusterRange;
616  }
617  if (fClusterRange == fTree->fNClusterRange) {
618  // We are looking at the last range which size
619  // is defined by AutoFlush itself and goes to the GetEntries.
620  fNextEntry += fTree->GetAutoFlush();
621  } else {
622  Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
623  if (clusterSize == 0) {
624  clusterSize = GetEstimatedClusterSize();
625  }
626  fNextEntry += clusterSize;
627  if (fNextEntry > fTree->fClusterRangeEnd[fClusterRange]) {
628  // The last cluster of the range was a partial cluster,
629  // so the next cluster starts at the beginning of the
630  // next range.
631  fNextEntry = fTree->fClusterRangeEnd[fClusterRange] + 1;
632  }
633  }
634  }
635  }
636  if (fNextEntry > fTree->GetEntries()) {
637  fNextEntry = fTree->GetEntries();
638  }
639  return fStartEntry;
640 }
641 
642 ////////////////////////////////////////////////////////////////////////////////
643 /// Move on to the previous cluster and return the starting entry
644 /// of this previous cluster
645 
647 {
648  fNextEntry = fStartEntry;
649  if (fTree->GetAutoFlush() <= 0) {
650  // Case of old files before November 9 2009
651  Long64_t clusterEstimate = GetEstimatedClusterSize();
652  fStartEntry = fNextEntry - clusterEstimate;
653  } else {
654  if (fClusterRange == 0 || fTree->fNClusterRange == 0) {
655  // We are looking at a range which size
656  // is defined by AutoFlush itself.
657  fStartEntry -= fTree->GetAutoFlush();
658  } else {
659  if (fNextEntry <= fTree->fClusterRangeEnd[fClusterRange]) {
660  --fClusterRange;
661  }
662  if (fClusterRange == 0) {
663  // We are looking at the first range.
664  fStartEntry = 0;
665  } else {
666  Long64_t clusterSize = fTree->fClusterSize[fClusterRange];
667  if (clusterSize == 0) {
668  clusterSize = GetEstimatedClusterSize();
669  }
670  fStartEntry -= clusterSize;
671  }
672  }
673  }
674  if (fStartEntry < 0) {
675  fStartEntry = 0;
676  }
677  return fStartEntry;
678 }
679 
680 ////////////////////////////////////////////////////////////////////////////////
681 ////////////////////////////////////////////////////////////////////////////////
682 ////////////////////////////////////////////////////////////////////////////////
683 
684 ////////////////////////////////////////////////////////////////////////////////
685 /// Default constructor and I/O constructor.
686 ///
687 /// Note: We do *not* insert ourself into the current directory.
688 ///
689 
690 TTree::TTree()
692 , TAttLine()
693 , TAttFill()
694 , TAttMarker()
695 , fEntries(0)
696 , fTotBytes(0)
697 , fZipBytes(0)
698 , fSavedBytes(0)
699 , fFlushedBytes(0)
700 , fWeight(1)
701 , fTimerInterval(0)
702 , fScanField(25)
703 , fUpdate(0)
705 , fNClusterRange(0)
706 , fMaxClusterRange(0)
707 , fMaxEntries(0)
708 , fMaxEntryLoop(0)
709 , fMaxVirtualSize(0)
710 , fAutoSave( -300000000)
711 , fAutoFlush(-30000000)
712 , fEstimate(1000000)
713 , fClusterRangeEnd(0)
714 , fClusterSize(0)
715 , fCacheSize(0)
716 , fChainOffset(0)
717 , fReadEntry(-1)
718 , fTotalBuffers(0)
719 , fPacketSize(100)
720 , fNfill(0)
721 , fDebug(0)
722 , fDebugMin(0)
723 , fDebugMax(9999999)
724 , fMakeClass(0)
725 , fFileNumber(0)
726 , fNotify(0)
727 , fDirectory(0)
728 , fBranches()
729 , fLeaves()
730 , fAliases(0)
731 , fEventList(0)
732 , fEntryList(0)
733 , fIndexValues()
734 , fIndex()
735 , fTreeIndex(0)
736 , fFriends(0)
737 , fPerfStats(0)
738 , fUserInfo(0)
739 , fPlayer(0)
740 , fClones(0)
741 , fBranchRef(0)
743 , fTransientBuffer(0)
749 {
750  fMaxEntries = 1000000000;
751  fMaxEntries *= 1000;
752 
753  fMaxEntryLoop = 1000000000;
754  fMaxEntryLoop *= 1000;
755 
757 }
758 
759 ////////////////////////////////////////////////////////////////////////////////
760 /// Normal tree constructor.
761 ///
762 /// The tree is created in the current directory.
763 /// Use the various functions Branch below to add branches to this tree.
764 ///
765 /// If the first character of title is a "/", the function assumes a folder name.
766 /// In this case, it creates automatically branches following the folder hierarchy.
767 /// splitlevel may be used in this case to control the split level.
768 
769 TTree::TTree(const char* name, const char* title, Int_t splitlevel /* = 99 */,
770  TDirectory* dir /* = gDirectory*/)
771 : TNamed(name, title)
772 , TAttLine()
773 , TAttFill()
774 , TAttMarker()
775 , fEntries(0)
776 , fTotBytes(0)
777 , fZipBytes(0)
778 , fSavedBytes(0)
779 , fFlushedBytes(0)
780 , fWeight(1)
781 , fTimerInterval(0)
782 , fScanField(25)
783 , fUpdate(0)
785 , fNClusterRange(0)
786 , fMaxClusterRange(0)
787 , fMaxEntries(0)
788 , fMaxEntryLoop(0)
789 , fMaxVirtualSize(0)
790 , fAutoSave( -300000000)
791 , fAutoFlush(-30000000)
792 , fEstimate(1000000)
793 , fClusterRangeEnd(0)
794 , fClusterSize(0)
795 , fCacheSize(0)
796 , fChainOffset(0)
797 , fReadEntry(-1)
798 , fTotalBuffers(0)
799 , fPacketSize(100)
800 , fNfill(0)
801 , fDebug(0)
802 , fDebugMin(0)
803 , fDebugMax(9999999)
804 , fMakeClass(0)
805 , fFileNumber(0)
806 , fNotify(0)
807 , fDirectory(dir)
808 , fBranches()
809 , fLeaves()
810 , fAliases(0)
811 , fEventList(0)
812 , fEntryList(0)
813 , fIndexValues()
814 , fIndex()
815 , fTreeIndex(0)
816 , fFriends(0)
817 , fPerfStats(0)
818 , fUserInfo(0)
819 , fPlayer(0)
820 , fClones(0)
821 , fBranchRef(0)
823 , fTransientBuffer(0)
829 {
830  // TAttLine state.
834 
835  // TAttFill state.
838 
839  // TAttMarkerState.
843 
844  fMaxEntries = 1000000000;
845  fMaxEntries *= 1000;
846 
847  fMaxEntryLoop = 1000000000;
848  fMaxEntryLoop *= 1000;
849 
850  // Insert ourself into the current directory.
851  // FIXME: This is very annoying behaviour, we should
852  // be able to choose to not do this like we
853  // can with a histogram.
854  if (fDirectory) fDirectory->Append(this);
855 
857 
858  // If title starts with "/" and is a valid folder name, a superbranch
859  // is created.
860  // FIXME: Why?
861  if (strlen(title) > 2) {
862  if (title[0] == '/') {
863  Branch(title+1,32000,splitlevel);
864  }
865  }
866 }
867 
868 ////////////////////////////////////////////////////////////////////////////////
869 /// Destructor.
870 
872 {
873  if (fDirectory) {
874  // We are in a directory, which may possibly be a file.
875  if (fDirectory->GetList()) {
876  // Remove us from the directory listing.
877  fDirectory->Remove(this);
878  }
879  //delete the file cache if it points to this Tree
881  MoveReadCache(file,0);
882  }
883  // We don't own the leaves in fLeaves, the branches do.
884  fLeaves.Clear();
885  // I'm ready to destroy any objects allocated by
886  // SetAddress() by my branches. If I have clones,
887  // tell them to zero their pointers to this shared
888  // memory.
889  if (fClones && fClones->GetEntries()) {
890  // I have clones.
891  // I am about to delete the objects created by
892  // SetAddress() which we are sharing, so tell
893  // the clones to release their pointers to them.
894  for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
895  TTree* clone = (TTree*) lnk->GetObject();
896  // clone->ResetBranchAddresses();
897 
898  // Reset only the branch we have set the address of.
899  CopyAddresses(clone,kTRUE);
900  }
901  }
902  // Get rid of our branches, note that this will also release
903  // any memory allocated by TBranchElement::SetAddress().
904  fBranches.Delete();
905  // FIXME: We must consider what to do with the reset of these if we are a clone.
906  delete fPlayer;
907  fPlayer = 0;
908  if (fFriends) {
909  fFriends->Delete();
910  delete fFriends;
911  fFriends = 0;
912  }
913  if (fAliases) {
914  fAliases->Delete();
915  delete fAliases;
916  fAliases = 0;
917  }
918  if (fUserInfo) {
919  fUserInfo->Delete();
920  delete fUserInfo;
921  fUserInfo = 0;
922  }
923  if (fClones) {
924  // Clone trees should no longer be removed from fClones when they are deleted.
925  {
927  gROOT->GetListOfCleanups()->Remove(fClones);
928  }
929  // Note: fClones does not own its content.
930  delete fClones;
931  fClones = 0;
932  }
933  if (fEntryList) {
935  // Delete the entry list if it is marked to be deleted and it is not also
936  // owned by a directory. (Otherwise we would need to make sure that a
937  // TDirectoryFile that has a TTree in it does a 'slow' TList::Delete.
938  delete fEntryList;
939  fEntryList=0;
940  }
941  }
942  delete fTreeIndex;
943  fTreeIndex = 0;
944  delete fBranchRef;
945  fBranchRef = 0;
946  delete [] fClusterRangeEnd;
947  fClusterRangeEnd = 0;
948  delete [] fClusterSize;
949  fClusterSize = 0;
950  // Must be done after the destruction of friends.
951  // Note: We do *not* own our directory.
952  fDirectory = 0;
953 
954  if (fTransientBuffer) {
955  delete fTransientBuffer;
956  fTransientBuffer = 0;
957  }
958 }
959 
960 ////////////////////////////////////////////////////////////////////////////////
961 /// Returns the transient buffer currently used by this TTree for reading/writing baskets.
962 
964 {
965  if (fTransientBuffer) {
966  if (fTransientBuffer->BufferSize() < size) {
967  fTransientBuffer->Expand(size);
968  }
969  return fTransientBuffer;
970  }
972  return fTransientBuffer;
973 }
974 
975 ////////////////////////////////////////////////////////////////////////////////
976 /// Add branch with name bname to the Tree cache.
977 /// If bname="*" all branches are added to the cache.
978 /// if subbranches is true all the branches of the subbranches are
979 /// also put to the cache.
980 ///
981 /// Returns:
982 /// - 0 branch added or already included
983 /// - -1 on error
984 
985 Int_t TTree::AddBranchToCache(const char*bname, Bool_t subbranches)
986 {
987  if (!GetTree()) {
988  if (LoadTree(0)<0) {
989  Error("AddBranchToCache","Could not load a tree");
990  return -1;
991  }
992  }
993  if (GetTree()) {
994  if (GetTree() != this) {
995  return GetTree()->AddBranchToCache(bname, subbranches);
996  }
997  } else {
998  Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
999  return -1;
1000  }
1001 
1002  TFile *f = GetCurrentFile();
1003  if (!f) {
1004  Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1005  return -1;
1006  }
1007  TTreeCache *tc = GetReadCache(f,kTRUE);
1008  if (!tc) {
1009  Error("AddBranchToCache", "No cache is available, branch not added");
1010  return -1;
1011  }
1012  return tc->AddBranch(bname,subbranches);
1013 }
1014 
1015 ////////////////////////////////////////////////////////////////////////////////
1016 /// Add branch b to the Tree cache.
1017 /// if subbranches is true all the branches of the subbranches are
1018 /// also put to the cache.
1019 ///
1020 /// Returns:
1021 /// - 0 branch added or already included
1022 /// - -1 on error
1023 
1026  if (!GetTree()) {
1027  if (LoadTree(0)<0) {
1028  Error("AddBranchToCache","Could not load a tree");
1029  return -1;
1030  }
1031  }
1032  if (GetTree()) {
1033  if (GetTree() != this) {
1034  Int_t res = GetTree()->AddBranchToCache(b, subbranches);
1035  if (res<0) {
1036  Error("AddBranchToCache", "Error adding branch");
1037  }
1038  return res;
1039  }
1040  } else {
1041  Error("AddBranchToCache", "No tree is available. Branch was not added to the cache");
1042  return -1;
1043  }
1044 
1045  TFile *f = GetCurrentFile();
1046  if (!f) {
1047  Error("AddBranchToCache", "No file is available. Branch was not added to the cache");
1048  return -1;
1049  }
1050  TTreeCache *tc = GetReadCache(f,kTRUE);
1051  if (!tc) {
1052  Error("AddBranchToCache", "No cache is available, branch not added");
1053  return -1;
1054  }
1055  return tc->AddBranch(b,subbranches);
1056 }
1057 
1058 ////////////////////////////////////////////////////////////////////////////////
1059 /// Remove the branch with name 'bname' from the Tree cache.
1060 /// If bname="*" all branches are removed from the cache.
1061 /// if subbranches is true all the branches of the subbranches are
1062 /// also removed from the cache.
1063 ///
1064 /// Returns:
1065 /// - 0 branch dropped or not in cache
1066 /// - -1 on error
1067 
1068 Int_t TTree::DropBranchFromCache(const char*bname, Bool_t subbranches)
1070  if (!GetTree()) {
1071  if (LoadTree(0)<0) {
1072  Error("DropBranchFromCache","Could not load a tree");
1073  return -1;
1074  }
1075  }
1076  if (GetTree()) {
1077  if (GetTree() != this) {
1078  return GetTree()->DropBranchFromCache(bname, subbranches);
1079  }
1080  } else {
1081  Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1082  return -1;
1083  }
1084 
1085  TFile *f = GetCurrentFile();
1086  if (!f) {
1087  Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1088  return -1;
1089  }
1090  TTreeCache *tc = GetReadCache(f,kTRUE);
1091  if (!tc) {
1092  Error("DropBranchFromCache", "No cache is available, branch not dropped");
1093  return -1;
1094  }
1095  return tc->DropBranch(bname,subbranches);
1096 }
1097 
1098 ////////////////////////////////////////////////////////////////////////////////
1099 /// Remove the branch b from the Tree cache.
1100 /// if subbranches is true all the branches of the subbranches are
1101 /// also removed from the cache.
1102 ///
1103 /// Returns:
1104 /// - 0 branch dropped or not in cache
1105 /// - -1 on error
1106 
1109  if (!GetTree()) {
1110  if (LoadTree(0)<0) {
1111  Error("DropBranchFromCache","Could not load a tree");
1112  return -1;
1113  }
1114  }
1115  if (GetTree()) {
1116  if (GetTree() != this) {
1117  Int_t res = GetTree()->DropBranchFromCache(b, subbranches);
1118  if (res<0) {
1119  Error("DropBranchFromCache", "Error dropping branch");
1120  }
1121  return res;
1122  }
1123  } else {
1124  Error("DropBranchFromCache", "No tree is available. Branch was not dropped from the cache");
1125  return -1;
1126  }
1127 
1128  TFile *f = GetCurrentFile();
1129  if (!f) {
1130  Error("DropBranchFromCache", "No file is available. Branch was not dropped from the cache");
1131  return -1;
1132  }
1133  TTreeCache *tc = GetReadCache(f,kTRUE);
1134  if (!tc) {
1135  Error("DropBranchFromCache", "No cache is available, branch not dropped");
1136  return -1;
1137  }
1138  return tc->DropBranch(b,subbranches);
1139 }
1140 
1141 ////////////////////////////////////////////////////////////////////////////////
1142 /// Add a cloned tree to our list of trees to be notified whenever we change
1143 /// our branch addresses or when we are deleted.
1144 
1145 void TTree::AddClone(TTree* clone)
1147  if (!fClones) {
1148  fClones = new TList();
1149  fClones->SetOwner(false);
1150  // So that the clones are automatically removed from the list when
1151  // they are deleted.
1152  {
1154  gROOT->GetListOfCleanups()->Add(fClones);
1155  }
1156  }
1157  if (!fClones->FindObject(clone)) {
1158  fClones->Add(clone);
1159  }
1160 }
1161 
1162 ////////////////////////////////////////////////////////////////////////////////
1163 /// Add a TFriendElement to the list of friends.
1164 ///
1165 /// This function:
1166 /// - opens a file if filename is specified
1167 /// - reads a Tree with name treename from the file (current directory)
1168 /// - adds the Tree to the list of friends
1169 /// see other AddFriend functions
1170 ///
1171 /// A TFriendElement TF describes a TTree object TF in a file.
1172 /// When a TFriendElement TF is added to the the list of friends of an
1173 /// existing TTree T, any variable from TF can be referenced in a query
1174 /// to T.
1175 ///
1176 /// A tree keeps a list of friends. In the context of a tree (or a chain),
1177 /// friendship means unrestricted access to the friends data. In this way
1178 /// it is much like adding another branch to the tree without taking the risk
1179 /// of damaging it. To add a friend to the list, you can use the TTree::AddFriend
1180 /// method. The tree in the diagram below has two friends (friend_tree1 and
1181 /// friend_tree2) and now has access to the variables a,b,c,i,j,k,l and m.
1182 ///
1183 /// \image html ttree_friend1.png
1184 ///
1185 /// The AddFriend method has two parameters, the first is the tree name and the
1186 /// second is the name of the ROOT file where the friend tree is saved.
1187 /// AddFriend automatically opens the friend file. If no file name is given,
1188 /// the tree called ft1 is assumed to be in the same file as the original tree.
1189 ///
1190 /// tree.AddFriend("ft1","friendfile1.root");
1191 /// If the friend tree has the same name as the original tree, you can give it
1192 /// an alias in the context of the friendship:
1193 ///
1194 /// tree.AddFriend("tree1 = tree","friendfile1.root");
1195 /// Once the tree has friends, we can use TTree::Draw as if the friend's
1196 /// variables were in the original tree. To specify which tree to use in
1197 /// the Draw method, use the syntax:
1198 /// ~~~ {.cpp}
1199 /// <treeName>.<branchname>.<varname>
1200 /// ~~~
1201 /// If the variablename is enough to uniquely identify the variable, you can
1202 /// leave out the tree and/or branch name.
1203 /// For example, these commands generate a 3-d scatter plot of variable "var"
1204 /// in the TTree tree versus variable v1 in TTree ft1 versus variable v2 in
1205 /// TTree ft2.
1206 /// ~~~ {.cpp}
1207 /// tree.AddFriend("ft1","friendfile1.root");
1208 /// tree.AddFriend("ft2","friendfile2.root");
1209 /// tree.Draw("var:ft1.v1:ft2.v2");
1210 /// ~~~
1211 /// \image html ttree_friend2.png
1212 ///
1213 /// The picture illustrates the access of the tree and its friends with a
1214 /// Draw command.
1215 /// When AddFriend is called, the ROOT file is automatically opened and the
1216 /// friend tree (ft1) is read into memory. The new friend (ft1) is added to
1217 /// the list of friends of tree.
1218 /// The number of entries in the friend must be equal or greater to the number
1219 /// of entries of the original tree. If the friend tree has fewer entries a
1220 /// warning is given and the missing entries are not included in the histogram.
1221 /// To retrieve the list of friends from a tree use TTree::GetListOfFriends.
1222 /// When the tree is written to file (TTree::Write), the friends list is saved
1223 /// with it. And when the tree is retrieved, the trees on the friends list are
1224 /// also retrieved and the friendship restored.
1225 /// When a tree is deleted, the elements of the friend list are also deleted.
1226 /// It is possible to declare a friend tree that has the same internal
1227 /// structure (same branches and leaves) as the original tree, and compare the
1228 /// same values by specifying the tree.
1229 /// ~~~ {.cpp}
1230 /// tree.Draw("var:ft1.var:ft2.var")
1231 /// ~~~
1232 
1233 TFriendElement* TTree::AddFriend(const char* treename, const char* filename)
1235  if (!fFriends) {
1236  fFriends = new TList();
1237  }
1238  TFriendElement* fe = new TFriendElement(this, treename, filename);
1239 
1240  fFriends->Add(fe);
1241  TTree* t = fe->GetTree();
1242  if (t) {
1243  if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1244  Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent Tree: %lld", treename, filename, t->GetEntries(), fEntries);
1245  }
1246  } else {
1247  Warning("AddFriend", "Cannot add FriendElement %s in file %s", treename, filename);
1248  }
1249  return fe;
1250 }
1251 
1252 ////////////////////////////////////////////////////////////////////////////////
1253 /// Add a TFriendElement to the list of friends.
1254 ///
1255 /// The TFile is managed by the user (e.g. the user must delete the file).
1256 /// For complete description see AddFriend(const char *, const char *).
1257 /// This function:
1258 /// - reads a Tree with name treename from the file
1259 /// - adds the Tree to the list of friends
1260 
1261 TFriendElement* TTree::AddFriend(const char* treename, TFile* file)
1263  if (!fFriends) {
1264  fFriends = new TList();
1265  }
1266  TFriendElement *fe = new TFriendElement(this, treename, file);
1267  R__ASSERT(fe);
1268  fFriends->Add(fe);
1269  TTree *t = fe->GetTree();
1270  if (t) {
1271  if (!t->GetTreeIndex() && (t->GetEntries() < fEntries)) {
1272  Warning("AddFriend", "FriendElement %s in file %s has less entries %lld than its parent tree: %lld", treename, file->GetName(), t->GetEntries(), fEntries);
1273  }
1274  } else {
1275  Warning("AddFriend", "unknown tree '%s' in file '%s'", treename, file->GetName());
1276  }
1277  return fe;
1278 }
1279 
1280 ////////////////////////////////////////////////////////////////////////////////
1281 /// Add a TFriendElement to the list of friends.
1282 ///
1283 /// The TTree is managed by the user (e.g., the user must delete the file).
1284 /// For a complete description see AddFriend(const char *, const char *).
1285 
1286 TFriendElement* TTree::AddFriend(TTree* tree, const char* alias, Bool_t warn)
1288  if (!tree) {
1289  return 0;
1290  }
1291  if (!fFriends) {
1292  fFriends = new TList();
1293  }
1294  TFriendElement* fe = new TFriendElement(this, tree, alias);
1295  R__ASSERT(fe); // this assert is for historical reasons. Don't remove it unless you understand all the consequences.
1296  fFriends->Add(fe);
1297  TTree* t = fe->GetTree();
1298  if (warn && (t->GetEntries() < fEntries)) {
1299  Warning("AddFriend", "FriendElement '%s' in file '%s' has less entries %lld than its parent tree: %lld",
1300  tree->GetName(), fe->GetFile() ? fe->GetFile()->GetName() : "(memory resident)", t->GetEntries(), fEntries);
1301  }
1302  return fe;
1303 }
1304 
1305 ////////////////////////////////////////////////////////////////////////////////
1306 /// AutoSave tree header every fAutoSave bytes.
1307 ///
1308 /// When large Trees are produced, it is safe to activate the AutoSave
1309 /// procedure. Some branches may have buffers holding many entries.
1310 /// If fAutoSave is negative, AutoSave is automatically called by
1311 /// TTree::Fill when the number of bytes generated since the previous
1312 /// AutoSave is greater than -fAutoSave bytes.
1313 /// If fAutoSave is positive, AutoSave is automatically called by
1314 /// TTree::Fill every N entries.
1315 /// This function may also be invoked by the user.
1316 /// Each AutoSave generates a new key on the file.
1317 /// Once the key with the tree header has been written, the previous cycle
1318 /// (if any) is deleted.
1319 ///
1320 /// Note that calling TTree::AutoSave too frequently (or similarly calling
1321 /// TTree::SetAutoSave with a small value) is an expensive operation.
1322 /// You should make tests for your own application to find a compromise
1323 /// between speed and the quantity of information you may loose in case of
1324 /// a job crash.
1325 ///
1326 /// In case your program crashes before closing the file holding this tree,
1327 /// the file will be automatically recovered when you will connect the file
1328 /// in UPDATE mode.
1329 /// The Tree will be recovered at the status corresponding to the last AutoSave.
1330 ///
1331 /// if option contains "SaveSelf", gDirectory->SaveSelf() is called.
1332 /// This allows another process to analyze the Tree while the Tree is being filled.
1333 ///
1334 /// if option contains "FlushBaskets", TTree::FlushBaskets is called and all
1335 /// the current basket are closed-out and written to disk individually.
1336 ///
1337 /// By default the previous header is deleted after having written the new header.
1338 /// if option contains "Overwrite", the previous Tree header is deleted
1339 /// before written the new header. This option is slightly faster, but
1340 /// the default option is safer in case of a problem (disk quota exceeded)
1341 /// when writing the new header.
1342 ///
1343 /// The function returns the number of bytes written to the file.
1344 /// if the number of bytes is null, an error has occurred while writing
1345 /// the header to the file.
1346 ///
1347 /// ## How to write a Tree in one process and view it from another process
1348 ///
1349 /// The following two scripts illustrate how to do this.
1350 /// The script treew.C is executed by process1, treer.C by process2
1351 ///
1352 /// script treew.C:
1353 /// ~~~ {.cpp}
1354 /// void treew() {
1355 /// TFile f("test.root","recreate");
1356 /// TNtuple *ntuple = new TNtuple("ntuple","Demo","px:py:pz:random:i");
1357 /// Float_t px, py, pz;
1358 /// for ( Int_t i=0; i<10000000; i++) {
1359 /// gRandom->Rannor(px,py);
1360 /// pz = px*px + py*py;
1361 /// Float_t random = gRandom->Rndm(1);
1362 /// ntuple->Fill(px,py,pz,random,i);
1363 /// if (i%1000 == 1) ntuple->AutoSave("SaveSelf");
1364 /// }
1365 /// }
1366 /// ~~~
1367 /// script treer.C:
1368 /// ~~~ {.cpp}
1369 /// void treer() {
1370 /// TFile f("test.root");
1371 /// TTree *ntuple = (TTree*)f.Get("ntuple");
1372 /// TCanvas c1;
1373 /// Int_t first = 0;
1374 /// while(1) {
1375 /// if (first == 0) ntuple->Draw("px>>hpx", "","",10000000,first);
1376 /// else ntuple->Draw("px>>+hpx","","",10000000,first);
1377 /// first = (Int_t)ntuple->GetEntries();
1378 /// c1.Update();
1379 /// gSystem->Sleep(1000); //sleep 1 second
1380 /// ntuple->Refresh();
1381 /// }
1382 /// }
1383 /// ~~~
1384 
1387  if (!fDirectory || fDirectory == gROOT || !fDirectory->IsWritable()) return 0;
1388  if (gDebug > 0) {
1389  Info("AutoSave", "Tree:%s after %lld bytes written\n",GetName(),GetTotBytes());
1390  }
1391  TString opt = option;
1392  opt.ToLower();
1393 
1394  if (opt.Contains("flushbaskets")) {
1395  if (gDebug > 0) Info("AutoSave", "calling FlushBaskets \n");
1396  FlushBaskets();
1397  }
1398 
1400 
1402  Long64_t nbytes;
1403  if (opt.Contains("overwrite")) {
1404  nbytes = fDirectory->WriteTObject(this,"","overwrite");
1405  } else {
1406  nbytes = fDirectory->WriteTObject(this); //nbytes will be 0 if Write failed (disk space exceeded)
1407  if (nbytes && key) {
1408  key->Delete();
1409  delete key;
1410  }
1411  }
1412  // save StreamerInfo
1413  TFile *file = fDirectory->GetFile();
1414  if (file) file->WriteStreamerInfo();
1415 
1416  if (opt.Contains("saveself")) {
1417  fDirectory->SaveSelf();
1418  //the following line is required in case GetUserInfo contains a user class
1419  //for which the StreamerInfo must be written. One could probably be a bit faster (Rene)
1420  if (file) file->WriteHeader();
1421  }
1422 
1423  return nbytes;
1424 }
1425 
1426 namespace {
1427  // This error message is repeated several times in the code. We write it once.
1428  const char* writeStlWithoutProxyMsg = "The class requested (%s) for the branch \"%s\""
1429  " is an instance of an stl collection and does not have a compiled CollectionProxy."
1430  " Please generate the dictionary for this collection (%s) to avoid to write corrupted data.";
1431 }
1432 
1433 ////////////////////////////////////////////////////////////////////////////////
1434 /// Same as TTree::Branch() with added check that addobj matches className.
1435 ///
1436 /// See TTree::Branch() for other details.
1437 ///
1438 
1439 TBranch* TTree::BranchImp(const char* branchname, const char* classname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1441  TClass* claim = TClass::GetClass(classname);
1442  if (!ptrClass) {
1443  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1444  Error("Branch", writeStlWithoutProxyMsg,
1445  claim->GetName(), branchname, claim->GetName());
1446  return 0;
1447  }
1448  return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1449  }
1450  TClass* actualClass = 0;
1451  void** addr = (void**) addobj;
1452  if (addr) {
1453  actualClass = ptrClass->GetActualClass(*addr);
1454  }
1455  if (ptrClass && claim) {
1456  if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1457  // Note we currently do not warn in case of splicing or over-expectation).
1458  if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1459  // The type is the same according to the C++ type_info, we must be in the case of
1460  // a template of Double32_t. This is actually a correct case.
1461  } else {
1462  Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the pointer passed (%s)",
1463  claim->GetName(), branchname, ptrClass->GetName());
1464  }
1465  } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1466  if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1467  // The type is the same according to the C++ type_info, we must be in the case of
1468  // a template of Double32_t. This is actually a correct case.
1469  } else {
1470  Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1471  actualClass->GetName(), branchname, claim->GetName());
1472  }
1473  }
1474  }
1475  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1476  Error("Branch", writeStlWithoutProxyMsg,
1477  claim->GetName(), branchname, claim->GetName());
1478  return 0;
1479  }
1480  return Branch(branchname, classname, (void*) addobj, bufsize, splitlevel);
1481 }
1482 
1483 ////////////////////////////////////////////////////////////////////////////////
1484 /// Same as TTree::Branch but automatic detection of the class name.
1485 /// See TTree::Branch for other details.
1486 
1487 TBranch* TTree::BranchImp(const char* branchname, TClass* ptrClass, void* addobj, Int_t bufsize, Int_t splitlevel)
1489  if (!ptrClass) {
1490  Error("Branch", "The pointer specified for %s is not of a class known to ROOT", branchname);
1491  return 0;
1492  }
1493  TClass* actualClass = 0;
1494  void** addr = (void**) addobj;
1495  if (addr && *addr) {
1496  actualClass = ptrClass->GetActualClass(*addr);
1497  if (!actualClass) {
1498  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",
1499  branchname, ptrClass->GetName());
1500  actualClass = ptrClass;
1501  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1502  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());
1503  return 0;
1504  }
1505  } else {
1506  actualClass = ptrClass;
1507  }
1508  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1509  Error("Branch", writeStlWithoutProxyMsg,
1510  actualClass->GetName(), branchname, actualClass->GetName());
1511  return 0;
1512  }
1513  return Branch(branchname, actualClass->GetName(), (void*) addobj, bufsize, splitlevel);
1514 }
1515 
1516 ////////////////////////////////////////////////////////////////////////////////
1517 /// Same as TTree::Branch but automatic detection of the class name.
1518 /// See TTree::Branch for other details.
1519 
1520 TBranch* TTree::BranchImpRef(const char* branchname, const char *classname, TClass* ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
1522  TClass* claim = TClass::GetClass(classname);
1523  if (!ptrClass) {
1524  if (claim && claim->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(claim->GetCollectionProxy())) {
1525  Error("Branch", writeStlWithoutProxyMsg,
1526  claim->GetName(), branchname, claim->GetName());
1527  return 0;
1528  } else if (claim == 0) {
1529  Error("Branch", "The pointer specified for %s is not of a class known to ROOT and %s is not a known class", branchname, classname);
1530  return 0;
1531  }
1532  ptrClass = claim;
1533  }
1534  TClass* actualClass = 0;
1535  if (!addobj) {
1536  Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1537  return 0;
1538  }
1539  actualClass = ptrClass->GetActualClass(addobj);
1540  if (ptrClass && claim) {
1541  if (!(claim->InheritsFrom(ptrClass) || ptrClass->InheritsFrom(claim))) {
1542  // Note we currently do not warn in case of splicing or over-expectation).
1543  if (claim->IsLoaded() && ptrClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), ptrClass->GetTypeInfo()->name() ) == 0) {
1544  // The type is the same according to the C++ type_info, we must be in the case of
1545  // a template of Double32_t. This is actually a correct case.
1546  } else {
1547  Error("Branch", "The class requested (%s) for \"%s\" is different from the type of the object passed (%s)",
1548  claim->GetName(), branchname, ptrClass->GetName());
1549  }
1550  } else if (actualClass && (claim != actualClass) && !actualClass->InheritsFrom(claim)) {
1551  if (claim->IsLoaded() && actualClass->IsLoaded() && strcmp( claim->GetTypeInfo()->name(), actualClass->GetTypeInfo()->name() ) == 0) {
1552  // The type is the same according to the C++ type_info, we must be in the case of
1553  // a template of Double32_t. This is actually a correct case.
1554  } else {
1555  Error("Branch", "The actual class (%s) of the object provided for the definition of the branch \"%s\" does not inherit from %s",
1556  actualClass->GetName(), branchname, claim->GetName());
1557  }
1558  }
1559  }
1560  if (!actualClass) {
1561  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",
1562  branchname, ptrClass->GetName());
1563  actualClass = ptrClass;
1564  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1565  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());
1566  return 0;
1567  }
1568  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1569  Error("Branch", writeStlWithoutProxyMsg,
1570  actualClass->GetName(), branchname, actualClass->GetName());
1571  return 0;
1572  }
1573  return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1574 }
1575 
1576 ////////////////////////////////////////////////////////////////////////////////
1577 /// Same as TTree::Branch but automatic detection of the class name.
1578 /// See TTree::Branch for other details.
1579 
1580 TBranch* TTree::BranchImpRef(const char* branchname, TClass* ptrClass, EDataType datatype, void* addobj, Int_t bufsize, Int_t splitlevel)
1582  if (!ptrClass) {
1583  if (datatype == kOther_t || datatype == kNoType_t) {
1584  Error("Branch", "The pointer specified for %s is not of a class or type known to ROOT", branchname);
1585  } else {
1586  TString varname; varname.Form("%s/%c",branchname,DataTypeToChar(datatype));
1587  return Branch(branchname,addobj,varname.Data(),bufsize);
1588  }
1589  return 0;
1590  }
1591  TClass* actualClass = 0;
1592  if (!addobj) {
1593  Error("Branch", "Reference interface requires a valid object (for branch: %s)!", branchname);
1594  return 0;
1595  }
1596  actualClass = ptrClass->GetActualClass(addobj);
1597  if (!actualClass) {
1598  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",
1599  branchname, ptrClass->GetName());
1600  actualClass = ptrClass;
1601  } else if ((ptrClass != actualClass) && !actualClass->InheritsFrom(ptrClass)) {
1602  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());
1603  return 0;
1604  }
1605  if (actualClass && actualClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(actualClass->GetCollectionProxy())) {
1606  Error("Branch", writeStlWithoutProxyMsg,
1607  actualClass->GetName(), branchname, actualClass->GetName());
1608  return 0;
1609  }
1610  return BronchExec(branchname, actualClass->GetName(), (void*) addobj, kFALSE, bufsize, splitlevel);
1611 }
1612 
1613 ////////////////////////////////////////////////////////////////////////////////
1614 /// Deprecated function. Use next function instead.
1615 
1616 Int_t TTree::Branch(TList* li, Int_t bufsize /* = 32000 */ , Int_t splitlevel /* = 99 */)
1618  return Branch((TCollection*) li, bufsize, splitlevel);
1619 }
1620 
1621 ////////////////////////////////////////////////////////////////////////////////
1622 /// Create one branch for each element in the collection.
1623 ///
1624 /// Each entry in the collection becomes a top level branch if the
1625 /// corresponding class is not a collection. If it is a collection, the entry
1626 /// in the collection becomes in turn top level branches, etc.
1627 /// The splitlevel is decreased by 1 every time a new collection is found.
1628 /// For example if list is a TObjArray*
1629 /// - if splitlevel = 1, one top level branch is created for each element
1630 /// of the TObjArray.
1631 /// - if splitlevel = 2, one top level branch is created for each array element.
1632 /// if, in turn, one of the array elements is a TCollection, one top level
1633 /// branch will be created for each element of this collection.
1634 ///
1635 /// In case a collection element is a TClonesArray, the special Tree constructor
1636 /// for TClonesArray is called.
1637 /// The collection itself cannot be a TClonesArray.
1638 ///
1639 /// The function returns the total number of branches created.
1640 ///
1641 /// If name is given, all branch names will be prefixed with name_.
1642 ///
1643 /// IMPORTANT NOTE1: This function should not be called with splitlevel < 1.
1644 ///
1645 /// IMPORTANT NOTE2: The branches created by this function will have names
1646 /// corresponding to the collection or object names. It is important
1647 /// to give names to collections to avoid misleading branch names or
1648 /// identical branch names. By default collections have a name equal to
1649 /// the corresponding class name, e.g. the default name for a TList is "TList".
1650 ///
1651 /// And in general in any cases two or more master branches contain subbranches
1652 /// with identical names, one must add a "." (dot) character at the end
1653 /// of the master branch name. This will force the name of the subbranch
1654 /// to be master.subbranch instead of simply subbranch.
1655 /// This situation happens when the top level object (say event)
1656 /// has two or more members referencing the same class.
1657 /// For example, if a Tree has two branches B1 and B2 corresponding
1658 /// to objects of the same class MyClass, one can do:
1659 /// ~~~ {.cpp}
1660 /// tree.Branch("B1.","MyClass",&b1,8000,1);
1661 /// tree.Branch("B2.","MyClass",&b2,8000,1);
1662 /// ~~~
1663 /// if MyClass has 3 members a,b,c, the two instructions above will generate
1664 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1665 ///
1666 /// Example:
1667 /// ~~~ {.cpp}
1668 /// {
1669 /// TTree T("T","test list");
1670 /// TList *list = new TList();
1671 ///
1672 /// TObjArray *a1 = new TObjArray();
1673 /// a1->SetName("a1");
1674 /// list->Add(a1);
1675 /// TH1F *ha1a = new TH1F("ha1a","ha1",100,0,1);
1676 /// TH1F *ha1b = new TH1F("ha1b","ha1",100,0,1);
1677 /// a1->Add(ha1a);
1678 /// a1->Add(ha1b);
1679 /// TObjArray *b1 = new TObjArray();
1680 /// b1->SetName("b1");
1681 /// list->Add(b1);
1682 /// TH1F *hb1a = new TH1F("hb1a","hb1",100,0,1);
1683 /// TH1F *hb1b = new TH1F("hb1b","hb1",100,0,1);
1684 /// b1->Add(hb1a);
1685 /// b1->Add(hb1b);
1686 ///
1687 /// TObjArray *a2 = new TObjArray();
1688 /// a2->SetName("a2");
1689 /// list->Add(a2);
1690 /// TH1S *ha2a = new TH1S("ha2a","ha2",100,0,1);
1691 /// TH1S *ha2b = new TH1S("ha2b","ha2",100,0,1);
1692 /// a2->Add(ha2a);
1693 /// a2->Add(ha2b);
1694 ///
1695 /// T.Branch(list,16000,2);
1696 /// T.Print();
1697 /// }
1698 /// ~~~
1699 
1700 Int_t TTree::Branch(TCollection* li, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */, const char* name /* = "" */)
1702 
1703  if (!li) {
1704  return 0;
1705  }
1706  TObject* obj = 0;
1707  Int_t nbranches = GetListOfBranches()->GetEntries();
1708  if (li->InheritsFrom(TClonesArray::Class())) {
1709  Error("Branch", "Cannot call this constructor for a TClonesArray");
1710  return 0;
1711  }
1712  Int_t nch = strlen(name);
1713  TString branchname;
1714  TIter next(li);
1715  while ((obj = next())) {
1716  if ((splitlevel > 1) && obj->InheritsFrom(TCollection::Class()) && !obj->InheritsFrom(TClonesArray::Class())) {
1717  TCollection* col = (TCollection*) obj;
1718  if (nch) {
1719  branchname.Form("%s_%s_", name, col->GetName());
1720  } else {
1721  branchname.Form("%s_", col->GetName());
1722  }
1723  Branch(col, bufsize, splitlevel - 1, branchname);
1724  } else {
1725  if (nch && (name[nch-1] == '_')) {
1726  branchname.Form("%s%s", name, obj->GetName());
1727  } else {
1728  if (nch) {
1729  branchname.Form("%s_%s", name, obj->GetName());
1730  } else {
1731  branchname.Form("%s", obj->GetName());
1732  }
1733  }
1734  if (splitlevel > 99) {
1735  branchname += ".";
1736  }
1737  Bronch(branchname, obj->ClassName(), li->GetObjectRef(obj), bufsize, splitlevel - 1);
1738  }
1739  }
1740  return GetListOfBranches()->GetEntries() - nbranches;
1741 }
1742 
1743 ////////////////////////////////////////////////////////////////////////////////
1744 /// Create one branch for each element in the folder.
1745 /// Returns the total number of branches created.
1746 
1747 Int_t TTree::Branch(const char* foldername, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1749  TObject* ob = gROOT->FindObjectAny(foldername);
1750  if (!ob) {
1751  return 0;
1752  }
1753  if (ob->IsA() != TFolder::Class()) {
1754  return 0;
1755  }
1756  Int_t nbranches = GetListOfBranches()->GetEntries();
1757  TFolder* folder = (TFolder*) ob;
1758  TIter next(folder->GetListOfFolders());
1759  TObject* obj = 0;
1760  char* curname = new char[1000];
1761  char occur[20];
1762  while ((obj = next())) {
1763  snprintf(curname,1000, "%s/%s", foldername, obj->GetName());
1764  if (obj->IsA() == TFolder::Class()) {
1765  Branch(curname, bufsize, splitlevel - 1);
1766  } else {
1767  void* add = (void*) folder->GetListOfFolders()->GetObjectRef(obj);
1768  for (Int_t i = 0; i < 1000; ++i) {
1769  if (curname[i] == 0) {
1770  break;
1771  }
1772  if (curname[i] == '/') {
1773  curname[i] = '.';
1774  }
1775  }
1776  Int_t noccur = folder->Occurence(obj);
1777  if (noccur > 0) {
1778  snprintf(occur,20, "_%d", noccur);
1779  strlcat(curname, occur,1000);
1780  }
1781  TBranchElement* br = (TBranchElement*) Bronch(curname, obj->ClassName(), add, bufsize, splitlevel - 1);
1782  if (br) br->SetBranchFolder();
1783  }
1784  }
1785  delete[] curname;
1786  return GetListOfBranches()->GetEntries() - nbranches;
1787 }
1788 
1789 ////////////////////////////////////////////////////////////////////////////////
1790 /// Create a new TTree Branch.
1791 ///
1792 /// This Branch constructor is provided to support non-objects in
1793 /// a Tree. The variables described in leaflist may be simple
1794 /// variables or structures. // See the two following
1795 /// constructors for writing objects in a Tree.
1796 ///
1797 /// By default the branch buffers are stored in the same file as the Tree.
1798 /// use TBranch::SetFile to specify a different file
1799 ///
1800 /// * address is the address of the first item of a structure.
1801 /// * leaflist is the concatenation of all the variable names and types
1802 /// separated by a colon character :
1803 /// The variable name and the variable type are separated by a slash (/).
1804 /// The variable type may be 0,1 or 2 characters. If no type is given,
1805 /// the type of the variable is assumed to be the same as the previous
1806 /// variable. If the first variable does not have a type, it is assumed
1807 /// of type F by default. The list of currently supported types is given below:
1808 /// - `C` : a character string terminated by the 0 character
1809 /// - `B` : an 8 bit signed integer (`Char_t`)
1810 /// - `b` : an 8 bit unsigned integer (`UChar_t`)
1811 /// - `S` : a 16 bit signed integer (`Short_t`)
1812 /// - `s` : a 16 bit unsigned integer (`UShort_t`)
1813 /// - `I` : a 32 bit signed integer (`Int_t`)
1814 /// - `i` : a 32 bit unsigned integer (`UInt_t`)
1815 /// - `F` : a 32 bit floating point (`Float_t`)
1816 /// - `D` : a 64 bit floating point (`Double_t`)
1817 /// - `L` : a 64 bit signed integer (`Long64_t`)
1818 /// - `l` : a 64 bit unsigned integer (`ULong64_t`)
1819 /// - `O` : [the letter `o`, not a zero] a boolean (`Bool_t`)
1820 ///
1821 /// Arrays of values are supported with the following syntax:
1822 /// - If leaf name has the form var[nelem], where nelem is alphanumeric, then
1823 /// if nelem is a leaf name, it is used as the variable size of the array,
1824 /// otherwise return 0.
1825 /// - If leaf name has the form var[nelem], where nelem is a non-negative integer, then
1826 /// it is used as the fixed size of the array.
1827 /// - If leaf name has the form of a multi-dimensional array (e.g. var[nelem][nelem2])
1828 /// where nelem and nelem2 are non-negative integer) then
1829 /// it is used as a 2 dimensional array of fixed size.
1830 ///
1831 /// Any of other form is not supported.
1832 ///
1833 /// Note that the TTree will assume that all the item are contiguous in memory.
1834 /// On some platform, this is not always true of the member of a struct or a class,
1835 /// due to padding and alignment. Sorting your data member in order of decreasing
1836 /// sizeof usually leads to their being contiguous in memory.
1837 ///
1838 /// * bufsize is the buffer size in bytes for this branch
1839 /// The default value is 32000 bytes and should be ok for most cases.
1840 /// You can specify a larger value (e.g. 256000) if your Tree is not split
1841 /// and each entry is large (Megabytes)
1842 /// A small value for bufsize is optimum if you intend to access
1843 /// the entries in the Tree randomly and your Tree is in split mode.
1844 
1845 TBranch* TTree::Branch(const char* name, void* address, const char* leaflist, Int_t bufsize /* = 32000 */)
1847  TBranch* branch = new TBranch(this, name, address, leaflist, bufsize);
1848  if (branch->IsZombie()) {
1849  delete branch;
1850  branch = 0;
1851  return 0;
1852  }
1853  fBranches.Add(branch);
1854  return branch;
1855 }
1856 
1857 ////////////////////////////////////////////////////////////////////////////////
1858 /// Create a new branch with the object of class classname at address addobj.
1859 ///
1860 /// WARNING:
1861 ///
1862 /// Starting with Root version 3.01, the Branch function uses the new style
1863 /// branches (TBranchElement). To get the old behaviour, you can:
1864 /// - call BranchOld or
1865 /// - call TTree::SetBranchStyle(0)
1866 ///
1867 /// Note that with the new style, classname does not need to derive from TObject.
1868 /// It must derived from TObject if the branch style has been set to 0 (old)
1869 ///
1870 /// Note: See the comments in TBranchElement::SetAddress() for a more
1871 /// detailed discussion of the meaning of the addobj parameter in
1872 /// the case of new-style branches.
1873 ///
1874 /// Use splitlevel < 0 instead of splitlevel=0 when the class
1875 /// has a custom Streamer
1876 ///
1877 /// Note: if the split level is set to the default (99), TTree::Branch will
1878 /// not issue a warning if the class can not be split.
1879 
1880 TBranch* TTree::Branch(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
1882  if (fgBranchStyle == 1) {
1883  return Bronch(name, classname, addobj, bufsize, splitlevel);
1884  } else {
1885  if (splitlevel < 0) {
1886  splitlevel = 0;
1887  }
1888  return BranchOld(name, classname, addobj, bufsize, splitlevel);
1889  }
1890 }
1891 
1892 ////////////////////////////////////////////////////////////////////////////////
1893 /// Create a new TTree BranchObject.
1894 ///
1895 /// Build a TBranchObject for an object of class classname.
1896 /// addobj is the address of a pointer to an object of class classname.
1897 /// IMPORTANT: classname must derive from TObject.
1898 /// The class dictionary must be available (ClassDef in class header).
1899 ///
1900 /// This option requires access to the library where the corresponding class
1901 /// is defined. Accessing one single data member in the object implies
1902 /// reading the full object.
1903 /// See the next Branch constructor for a more efficient storage
1904 /// in case the entry consists of arrays of identical objects.
1905 ///
1906 /// By default the branch buffers are stored in the same file as the Tree.
1907 /// use TBranch::SetFile to specify a different file
1908 ///
1909 /// IMPORTANT NOTE about branch names:
1910 ///
1911 /// In case two or more master branches contain subbranches with
1912 /// identical names, one must add a "." (dot) character at the end
1913 /// of the master branch name. This will force the name of the subbranch
1914 /// to be master.subbranch instead of simply subbranch.
1915 /// This situation happens when the top level object (say event)
1916 /// has two or more members referencing the same class.
1917 /// For example, if a Tree has two branches B1 and B2 corresponding
1918 /// to objects of the same class MyClass, one can do:
1919 /// ~~~ {.cpp}
1920 /// tree.Branch("B1.","MyClass",&b1,8000,1);
1921 /// tree.Branch("B2.","MyClass",&b2,8000,1);
1922 /// ~~~
1923 /// if MyClass has 3 members a,b,c, the two instructions above will generate
1924 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
1925 ///
1926 /// bufsize is the buffer size in bytes for this branch
1927 /// The default value is 32000 bytes and should be ok for most cases.
1928 /// You can specify a larger value (e.g. 256000) if your Tree is not split
1929 /// and each entry is large (Megabytes)
1930 /// A small value for bufsize is optimum if you intend to access
1931 /// the entries in the Tree randomly and your Tree is in split mode.
1932 
1933 TBranch* TTree::BranchOld(const char* name, const char* classname, void* addobj, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 1 */)
1935  TClass* cl = TClass::GetClass(classname);
1936  if (!cl) {
1937  Error("BranchOld", "Cannot find class: '%s'", classname);
1938  return 0;
1939  }
1940  if (!cl->IsTObject()) {
1941  if (fgBranchStyle == 0) {
1942  Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1943  "\tfgBranchStyle is set to zero requesting by default to use BranchOld.\n"
1944  "\tIf this is intentional use Bronch instead of Branch or BranchOld.", classname);
1945  } else {
1946  Fatal("BranchOld", "The requested class ('%s') does not inherit from TObject.\n"
1947  "\tYou can not use BranchOld to store objects of this type.",classname);
1948  }
1949  return 0;
1950  }
1951  TBranch* branch = new TBranchObject(this, name, classname, addobj, bufsize, splitlevel);
1952  fBranches.Add(branch);
1953  if (!splitlevel) {
1954  return branch;
1955  }
1956  // We are going to fully split the class now.
1957  TObjArray* blist = branch->GetListOfBranches();
1958  const char* rdname = 0;
1959  const char* dname = 0;
1960  TString branchname;
1961  char** apointer = (char**) addobj;
1962  TObject* obj = (TObject*) *apointer;
1963  Bool_t delobj = kFALSE;
1964  if (!obj) {
1965  obj = (TObject*) cl->New();
1966  delobj = kTRUE;
1967  }
1968  // Build the StreamerInfo if first time for the class.
1969  BuildStreamerInfo(cl, obj);
1970  // Loop on all public data members of the class and its base classes.
1971  Int_t lenName = strlen(name);
1972  Int_t isDot = 0;
1973  if (name[lenName-1] == '.') {
1974  isDot = 1;
1975  }
1976  TBranch* branch1 = 0;
1977  TRealData* rd = 0;
1978  TRealData* rdi = 0;
1979  TIter nexti(cl->GetListOfRealData());
1980  TIter next(cl->GetListOfRealData());
1981  // Note: This loop results in a full split because the
1982  // real data list includes all data members of
1983  // data members.
1984  while ((rd = (TRealData*) next())) {
1985  if (rd->TestBit(TRealData::kTransient)) continue;
1986 
1987  // Loop over all data members creating branches for each one.
1988  TDataMember* dm = rd->GetDataMember();
1989  if (!dm->IsPersistent()) {
1990  // Do not process members with an "!" as the first character in the comment field.
1991  continue;
1992  }
1993  if (rd->IsObject()) {
1994  // We skip data members of class type.
1995  // But we do build their real data, their
1996  // streamer info, and write their streamer
1997  // info to the current directory's file.
1998  // Oh yes, and we also do this for all of
1999  // their base classes.
2000  TClass* clm = TClass::GetClass(dm->GetFullTypeName());
2001  if (clm) {
2002  BuildStreamerInfo(clm, (char*) obj + rd->GetThisOffset());
2003  }
2004  continue;
2005  }
2006  rdname = rd->GetName();
2007  dname = dm->GetName();
2008  if (cl->CanIgnoreTObjectStreamer()) {
2009  // Skip the TObject base class data members.
2010  // FIXME: This prevents a user from ever
2011  // using these names themself!
2012  if (!strcmp(dname, "fBits")) {
2013  continue;
2014  }
2015  if (!strcmp(dname, "fUniqueID")) {
2016  continue;
2017  }
2018  }
2019  TDataType* dtype = dm->GetDataType();
2020  Int_t code = 0;
2021  if (dtype) {
2022  code = dm->GetDataType()->GetType();
2023  }
2024  // Encode branch name. Use real data member name
2025  branchname = rdname;
2026  if (isDot) {
2027  if (dm->IsaPointer()) {
2028  // FIXME: This is wrong! The asterisk is not usually in the front!
2029  branchname.Form("%s%s", name, &rdname[1]);
2030  } else {
2031  branchname.Form("%s%s", name, &rdname[0]);
2032  }
2033  }
2034  // FIXME: Change this to a string stream.
2035  TString leaflist;
2036  Int_t offset = rd->GetThisOffset();
2037  char* pointer = ((char*) obj) + offset;
2038  if (dm->IsaPointer()) {
2039  // We have a pointer to an object or a pointer to an array of basic types.
2040  TClass* clobj = 0;
2041  if (!dm->IsBasic()) {
2042  clobj = TClass::GetClass(dm->GetTypeName());
2043  }
2044  if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
2045  // We have a pointer to a clones array.
2046  char* cpointer = (char*) pointer;
2047  char** ppointer = (char**) cpointer;
2048  TClonesArray* li = (TClonesArray*) *ppointer;
2049  if (splitlevel != 2) {
2050  if (isDot) {
2051  branch1 = new TBranchClones(branch,branchname, pointer, bufsize);
2052  } else {
2053  // FIXME: This is wrong! The asterisk is not usually in the front!
2054  branch1 = new TBranchClones(branch,&branchname.Data()[1], pointer, bufsize);
2055  }
2056  blist->Add(branch1);
2057  } else {
2058  if (isDot) {
2059  branch1 = new TBranchObject(branch, branchname, li->ClassName(), pointer, bufsize);
2060  } else {
2061  // FIXME: This is wrong! The asterisk is not usually in the front!
2062  branch1 = new TBranchObject(branch, &branchname.Data()[1], li->ClassName(), pointer, bufsize);
2063  }
2064  blist->Add(branch1);
2065  }
2066  } else if (clobj) {
2067  // We have a pointer to an object.
2068  //
2069  // It must be a TObject object.
2070  if (!clobj->IsTObject()) {
2071  continue;
2072  }
2073  branch1 = new TBranchObject(branch, dname, clobj->GetName(), pointer, bufsize, 0);
2074  if (isDot) {
2075  branch1->SetName(branchname);
2076  } else {
2077  // FIXME: This is wrong! The asterisk is not usually in the front!
2078  // Do not use the first character (*).
2079  branch1->SetName(&branchname.Data()[1]);
2080  }
2081  blist->Add(branch1);
2082  } else {
2083  // We have a pointer to an array of basic types.
2084  //
2085  // Check the comments in the text of the code for an index specification.
2086  const char* index = dm->GetArrayIndex();
2087  if (index[0]) {
2088  // We are a pointer to a varying length array of basic types.
2089  //check that index is a valid data member name
2090  //if member is part of an object (e.g. fA and index=fN)
2091  //index must be changed from fN to fA.fN
2092  TString aindex (rd->GetName());
2093  Ssiz_t rdot = aindex.Last('.');
2094  if (rdot>=0) {
2095  aindex.Remove(rdot+1);
2096  aindex.Append(index);
2097  }
2098  nexti.Reset();
2099  while ((rdi = (TRealData*) nexti())) {
2100  if (rdi->TestBit(TRealData::kTransient)) continue;
2101 
2102  if (!strcmp(rdi->GetName(), index)) {
2103  break;
2104  }
2105  if (!strcmp(rdi->GetName(), aindex)) {
2106  index = rdi->GetName();
2107  break;
2108  }
2109  }
2110 
2111  char vcode = DataTypeToChar((EDataType)code);
2112  // Note that we differentiate between strings and
2113  // char array by the fact that there is NO specified
2114  // size for a string (see next if (code == 1)
2115 
2116  if (vcode) {
2117  leaflist.Form("%s[%s]/%c", &rdname[0], index, vcode);
2118  } else {
2119  Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2120  leaflist = "";
2121  }
2122  } else {
2123  // We are possibly a character string.
2124  if (code == 1) {
2125  // We are a character string.
2126  leaflist.Form("%s/%s", dname, "C");
2127  } else {
2128  // Invalid array specification.
2129  // FIXME: We need an error message here.
2130  continue;
2131  }
2132  }
2133  // There are '*' in both the branchname and leaflist, remove them.
2134  TString bname( branchname );
2135  bname.ReplaceAll("*","");
2136  leaflist.ReplaceAll("*","");
2137  // Add the branch to the tree and indicate that the address
2138  // is that of a pointer to be dereferenced before using.
2139  branch1 = new TBranch(branch, bname, *((void**) pointer), leaflist, bufsize);
2140  TLeaf* leaf = (TLeaf*) branch1->GetListOfLeaves()->At(0);
2142  leaf->SetAddress((void**) pointer);
2143  blist->Add(branch1);
2144  }
2145  } else if (dm->IsBasic()) {
2146  // We have a basic type.
2147 
2148  char vcode = DataTypeToChar((EDataType)code);
2149  if (vcode) {
2150  leaflist.Form("%s/%c", rdname, vcode);
2151  } else {
2152  Error("BranchOld", "Cannot create branch for rdname: %s code: %d", branchname.Data(), code);
2153  leaflist = "";
2154  }
2155  branch1 = new TBranch(branch, branchname, pointer, leaflist, bufsize);
2156  branch1->SetTitle(rdname);
2157  blist->Add(branch1);
2158  } else {
2159  // We have a class type.
2160  // Note: This cannot happen due to the rd->IsObject() test above.
2161  // FIXME: Put an error message here just in case.
2162  }
2163  if (branch1) {
2164  branch1->SetOffset(offset);
2165  } else {
2166  Warning("BranchOld", "Cannot process member: '%s'", rdname);
2167  }
2168  }
2169  if (delobj) {
2170  delete obj;
2171  obj = 0;
2172  }
2173  return branch;
2174 }
2175 
2176 ////////////////////////////////////////////////////////////////////////////////
2177 /// Build the optional branch supporting the TRefTable.
2178 /// This branch will keep all the information to find the branches
2179 /// containing referenced objects.
2180 ///
2181 /// At each Tree::Fill, the branch numbers containing the
2182 /// referenced objects are saved to the TBranchRef basket.
2183 /// When the Tree header is saved (via TTree::Write), the branch
2184 /// is saved keeping the information with the pointers to the branches
2185 /// having referenced objects.
2186 
2189  if (!fBranchRef) {
2190  fBranchRef = new TBranchRef(this);
2191  }
2192  return fBranchRef;
2193 }
2194 
2195 ////////////////////////////////////////////////////////////////////////////////
2196 /// Create a new TTree BranchElement.
2197 ///
2198 /// ## WARNING about this new function
2199 ///
2200 /// This function is designed to replace the internal
2201 /// implementation of the old TTree::Branch (whose implementation
2202 /// has been moved to BranchOld).
2203 ///
2204 /// NOTE: The 'Bronch' method supports only one possible calls
2205 /// signature (where the object type has to be specified
2206 /// explicitly and the address must be the address of a pointer).
2207 /// For more flexibility use 'Branch'. Use Bronch only in (rare)
2208 /// cases (likely to be legacy cases) where both the new and old
2209 /// implementation of Branch needs to be used at the same time.
2210 ///
2211 /// This function is far more powerful than the old Branch
2212 /// function. It supports the full C++, including STL and has
2213 /// the same behaviour in split or non-split mode. classname does
2214 /// not have to derive from TObject. The function is based on
2215 /// the new TStreamerInfo.
2216 ///
2217 /// Build a TBranchElement for an object of class classname.
2218 ///
2219 /// addr is the address of a pointer to an object of class
2220 /// classname. The class dictionary must be available (ClassDef
2221 /// in class header).
2222 ///
2223 /// Note: See the comments in TBranchElement::SetAddress() for a more
2224 /// detailed discussion of the meaning of the addr parameter.
2225 ///
2226 /// This option requires access to the library where the
2227 /// corresponding class is defined. Accessing one single data
2228 /// member in the object implies reading the full object.
2229 ///
2230 /// By default the branch buffers are stored in the same file as the Tree.
2231 /// use TBranch::SetFile to specify a different file
2232 ///
2233 /// IMPORTANT NOTE about branch names:
2234 ///
2235 /// In case two or more master branches contain subbranches with
2236 /// identical names, one must add a "." (dot) character at the end
2237 /// of the master branch name. This will force the name of the subbranch
2238 /// to be master.subbranch instead of simply subbranch.
2239 /// This situation happens when the top level object (say event)
2240 /// has two or more members referencing the same class.
2241 /// For example, if a Tree has two branches B1 and B2 corresponding
2242 /// to objects of the same class MyClass, one can do:
2243 /// ~~~ {.cpp}
2244 /// tree.Branch("B1.","MyClass",&b1,8000,1);
2245 /// tree.Branch("B2.","MyClass",&b2,8000,1);
2246 /// ~~~
2247 /// if MyClass has 3 members a,b,c, the two instructions above will generate
2248 /// subbranches called B1.a, B1.b ,B1.c, B2.a, B2.b, B2.c
2249 ///
2250 /// bufsize is the buffer size in bytes for this branch
2251 /// The default value is 32000 bytes and should be ok for most cases.
2252 /// You can specify a larger value (e.g. 256000) if your Tree is not split
2253 /// and each entry is large (Megabytes)
2254 /// A small value for bufsize is optimum if you intend to access
2255 /// the entries in the Tree randomly and your Tree is in split mode.
2256 ///
2257 /// Use splitlevel < 0 instead of splitlevel=0 when the class
2258 /// has a custom Streamer
2259 ///
2260 /// Note: if the split level is set to the default (99), TTree::Branch will
2261 /// not issue a warning if the class can not be split.
2262 
2263 TBranch* TTree::Bronch(const char* name, const char* classname, void* addr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2265  return BronchExec(name, classname, addr, kTRUE, bufsize, splitlevel);
2266 }
2267 
2268 ////////////////////////////////////////////////////////////////////////////////
2269 /// Helper function implementing TTree::Bronch and TTree::Branch(const char *name, T &obj);
2270 
2271 TBranch* TTree::BronchExec(const char* name, const char* classname, void* addr, Bool_t isptrptr, Int_t bufsize /* = 32000 */, Int_t splitlevel /* = 99 */)
2273  TClass* cl = TClass::GetClass(classname);
2274  if (!cl) {
2275  Error("Bronch", "Cannot find class:%s", classname);
2276  return 0;
2277  }
2278 
2279  //if splitlevel <= 0 and class has a custom Streamer, we must create
2280  //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
2281  //with the custom Streamer. The penalty is that one cannot process
2282  //this Tree without the class library containing the class.
2283 
2284  char* objptr = 0;
2285  if (!isptrptr) {
2286  objptr = (char*)addr;
2287  } else if (addr) {
2288  objptr = *((char**) addr);
2289  }
2290 
2291  if (cl == TClonesArray::Class()) {
2292  TClonesArray* clones = (TClonesArray*) objptr;
2293  if (!clones) {
2294  Error("Bronch", "Pointer to TClonesArray is null");
2295  return 0;
2296  }
2297  if (!clones->GetClass()) {
2298  Error("Bronch", "TClonesArray with no class defined in branch: %s", name);
2299  return 0;
2300  }
2301  if (!clones->GetClass()->HasDataMemberInfo()) {
2302  Error("Bronch", "TClonesArray with no dictionary defined in branch: %s", name);
2303  return 0;
2304  }
2305  bool hasCustomStreamer = clones->GetClass()->TestBit(TClass::kHasCustomStreamerMember);
2306  if (splitlevel > 0) {
2307  if (hasCustomStreamer)
2308  Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", clones->GetClass()->GetName());
2309  } else {
2310  if (hasCustomStreamer) clones->BypassStreamer(kFALSE);
2311  TBranchObject *branch = new TBranchObject(this,name,classname,addr,bufsize,0,/*compress=*/ -1,isptrptr);
2312  fBranches.Add(branch);
2313  return branch;
2314  }
2315  }
2316 
2317  if (cl->GetCollectionProxy()) {
2318  TVirtualCollectionProxy* collProxy = cl->GetCollectionProxy();
2319  //if (!collProxy) {
2320  // Error("Bronch", "%s is missing its CollectionProxy (for branch %s)", classname, name);
2321  //}
2322  TClass* inklass = collProxy->GetValueClass();
2323  if (!inklass && (collProxy->GetType() == 0)) {
2324  Error("Bronch", "%s with no class defined in branch: %s", classname, name);
2325  return 0;
2326  }
2327  if ((splitlevel > 0) && inklass && (inklass->GetCollectionProxy() == 0)) {
2328  ROOT::ESTLType stl = cl->GetCollectionType();
2329  if ((stl != ROOT::kSTLmap) && (stl != ROOT::kSTLmultimap)) {
2330  if (!inklass->HasDataMemberInfo()) {
2331  Error("Bronch", "Container with no dictionary defined in branch: %s", name);
2332  return 0;
2333  }
2334  if (inklass->TestBit(TClass::kHasCustomStreamerMember)) {
2335  Warning("Bronch", "Using split mode on a class: %s with a custom Streamer", inklass->GetName());
2336  }
2337  }
2338  }
2339  //-------------------------------------------------------------------------
2340  // If the splitting switch is enabled, the split level is big enough and
2341  // the collection contains pointers we can split it
2342  //////////////////////////////////////////////////////////////////////////
2343 
2344  TBranch *branch;
2345  if( splitlevel > kSplitCollectionOfPointers && collProxy->HasPointers() )
2346  branch = new TBranchSTL( this, name, collProxy, bufsize, splitlevel );
2347  else
2348  branch = new TBranchElement(this, name, collProxy, bufsize, splitlevel);
2349  fBranches.Add(branch);
2350  if (isptrptr) {
2351  branch->SetAddress(addr);
2352  } else {
2353  branch->SetObject(addr);
2354  }
2355  return branch;
2356  }
2357 
2358  Bool_t hasCustomStreamer = kFALSE;
2359  if (!cl->HasDataMemberInfo() && !cl->GetCollectionProxy()) {
2360  Error("Bronch", "Cannot find dictionary for class: %s", classname);
2361  return 0;
2362  }
2363 
2365  // Not an STL container and the linkdef file had a "-" after the class name.
2366  hasCustomStreamer = kTRUE;
2367  }
2368 
2369  if (splitlevel < 0 || ((splitlevel == 0) && hasCustomStreamer && cl->IsTObject())) {
2370  TBranchObject* branch = new TBranchObject(this, name, classname, addr, bufsize, 0, /*compress=*/ -1, isptrptr);
2371  fBranches.Add(branch);
2372  return branch;
2373  }
2374 
2375  if (cl == TClonesArray::Class()) {
2376  // Special case of TClonesArray.
2377  // No dummy object is created.
2378  // The streamer info is not rebuilt unoptimized.
2379  // No dummy top-level branch is created.
2380  // No splitting is attempted.
2381  TBranchElement* branch = new TBranchElement(this, name, (TClonesArray*) objptr, bufsize, splitlevel%kSplitCollectionOfPointers);
2382  fBranches.Add(branch);
2383  if (isptrptr) {
2384  branch->SetAddress(addr);
2385  } else {
2386  branch->SetObject(addr);
2387  }
2388  return branch;
2389  }
2390 
2391  //
2392  // If we are not given an object to use as an i/o buffer
2393  // then create a temporary one which we will delete just
2394  // before returning.
2395  //
2396 
2397  Bool_t delobj = kFALSE;
2398 
2399  if (!objptr) {
2400  objptr = (char*) cl->New();
2401  delobj = kTRUE;
2402  }
2403 
2404  //
2405  // Avoid splitting unsplittable classes.
2406  //
2407 
2408  if ((splitlevel > 0) && !cl->CanSplit()) {
2409  if (splitlevel != 99) {
2410  Warning("Bronch", "%s cannot be split, resetting splitlevel to 0", cl->GetName());
2411  }
2412  splitlevel = 0;
2413  }
2414 
2415  //
2416  // Make sure the streamer info is built and fetch it.
2417  //
2418  // If we are splitting, then make sure the streamer info
2419  // is built unoptimized (data members are not combined).
2420  //
2421 
2422  TStreamerInfo* sinfo = BuildStreamerInfo(cl, objptr, splitlevel==0);
2423  if (!sinfo) {
2424  Error("Bronch", "Cannot build the StreamerInfo for class: %s", cl->GetName());
2425  return 0;
2426  }
2427 
2428  //
2429  // Do we have a final dot in our name?
2430  //
2431 
2432  // Note: The branch constructor which takes a folder as input
2433  // creates top-level branch names with dots in them to
2434  // indicate the folder hierarchy.
2435  char* dot = (char*) strchr(name, '.');
2436  Int_t nch = strlen(name);
2437  Bool_t dotlast = kFALSE;
2438  if (nch && (name[nch-1] == '.')) {
2439  dotlast = kTRUE;
2440  }
2441 
2442  //
2443  // Create a dummy top level branch object.
2444  //
2445 
2446  Int_t id = -1;
2447  if (splitlevel > 0) {
2448  id = -2;
2449  }
2450  TBranchElement* branch = new TBranchElement(this, name, sinfo, id, objptr, bufsize, splitlevel);
2451  fBranches.Add(branch);
2452 
2453  //
2454  // Do splitting, if requested.
2455  //
2456 
2457  if (splitlevel%kSplitCollectionOfPointers > 0) {
2458  // Loop on all public data members of the class and its base classes and create branches for each one.
2459  TObjArray* blist = branch->GetListOfBranches();
2460  TIter next(sinfo->GetElements());
2461  TStreamerElement* element = 0;
2462  TString bname;
2463  for (id = 0; (element = (TStreamerElement*) next()); ++id) {
2464  if (element->IsA() == TStreamerArtificial::Class()) {
2465  continue;
2466  }
2467  if (element->TestBit(TStreamerElement::kRepeat)) {
2468  continue;
2469  }
2470  if (element->TestBit(TStreamerElement::kCache) && !element->TestBit(TStreamerElement::kWrite)) {
2471  continue;
2472  }
2473  char* pointer = (char*) (objptr + element->GetOffset());
2474  // FIXME: This is not good enough, an STL container can be
2475  // a base, and the test will fail.
2476  // See TBranchElement::InitializeOffsets() for the
2477  // correct test.
2478  Bool_t isBase = (element->IsA() == TStreamerBase::Class());
2479  if (isBase) {
2480  TClass* clbase = element->GetClassPointer();
2481  if ((clbase == TObject::Class()) && cl->CanIgnoreTObjectStreamer()) {
2482  // Note: TStreamerInfo::Compile() leaves this element
2483  // out of the optimized info, although it does
2484  // exists in the non-compiled and non-optimized info.
2485  // FIXME: The test that TStreamerInfo::Compile() uses
2486  // is element->GetType() < 0, so that is what
2487  // we should do as well.
2488  continue;
2489  }
2490  if (clbase->GetListOfRealData()->GetSize() == 0) {
2491  // Do not create a branch for empty bases.
2492  continue;
2493  }
2494  }
2495  if (dot) {
2496  if (dotlast) {
2497  bname.Form("%s%s", name, element->GetFullName());
2498  } else {
2499  // FIXME: We are in the case where we have a top-level
2500  // branch name that was created by the branch
2501  // constructor which takes a folder as input.
2502  // The internal dots in the name are in place of
2503  // of the original slashes and represent the
2504  // folder hierarchy.
2505  if (isBase) {
2506  // FIXME: This is very strange, this is the only case where
2507  // we create a branch for a base class that does
2508  // not have the base class name in the branch name.
2509  // FIXME: This is also quite bad since classes with two
2510  // or more base classes end up with sub-branches
2511  // that have the same name.
2512  bname = name;
2513  } else {
2514  bname.Form("%s.%s", name, element->GetFullName());
2515  }
2516  }
2517  } else {
2518  // Note: For a base class element, this results in the branchname
2519  // being the name of the base class.
2520  bname.Form("%s", element->GetFullName());
2521  }
2522 
2523  if( splitlevel > kSplitCollectionOfPointers && element->GetClass() &&
2524  element->GetClass()->GetCollectionProxy() &&
2525  element->GetClass()->GetCollectionProxy()->HasPointers() )
2526  {
2527  TBranchSTL* brSTL = new TBranchSTL( branch, bname, element->GetClass()->GetCollectionProxy(), bufsize, splitlevel-1, sinfo, id );
2528  blist->Add(brSTL);
2529  }
2530  else
2531  {
2532  TBranchElement* bre = new TBranchElement(branch, bname, sinfo, id, pointer, bufsize, splitlevel - 1);
2533  bre->SetParentClass(cl);
2534  blist->Add(bre);
2535  }
2536  }
2537  }
2538 
2539  //
2540  // Setup our offsets into the user's i/o buffer.
2541  //
2542 
2543  if (isptrptr) {
2544  branch->SetAddress(addr);
2545  } else {
2546  branch->SetObject(addr);
2547  }
2548 
2549  if (delobj) {
2550  cl->Destructor(objptr);
2551  objptr = 0;
2552  }
2553 
2554  return branch;
2555 }
2556 
2557 ////////////////////////////////////////////////////////////////////////////////
2558 /// Browse content of the TTree.
2559 
2560 void TTree::Browse(TBrowser* b)
2562  fBranches.Browse(b);
2563  if (fUserInfo) {
2564  if (strcmp("TList",fUserInfo->GetName())==0) {
2565  fUserInfo->SetName("UserInfo");
2566  b->Add(fUserInfo);
2567  fUserInfo->SetName("TList");
2568  } else {
2569  b->Add(fUserInfo);
2570  }
2571  }
2572 }
2573 
2574 ////////////////////////////////////////////////////////////////////////////////
2575 /// Build a Tree Index (default is TTreeIndex).
2576 /// See a description of the parameters and functionality in
2577 /// TTreeIndex::TTreeIndex().
2578 ///
2579 /// The return value is the number of entries in the Index (< 0 indicates failure).
2580 ///
2581 /// A TTreeIndex object pointed by fTreeIndex is created.
2582 /// This object will be automatically deleted by the TTree destructor.
2583 /// See also comments in TTree::SetTreeIndex().
2584 
2585 Int_t TTree::BuildIndex(const char* majorname, const char* minorname /* = "0" */)
2587  fTreeIndex = GetPlayer()->BuildIndex(this, majorname, minorname);
2588  if (fTreeIndex->IsZombie()) {
2589  delete fTreeIndex;
2590  fTreeIndex = 0;
2591  return 0;
2592  }
2593  return fTreeIndex->GetN();
2594 }
2595 
2596 ////////////////////////////////////////////////////////////////////////////////
2597 /// Build StreamerInfo for class cl.
2598 /// pointer is an optional argument that may contain a pointer to an object of cl.
2599 
2600 TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, Bool_t canOptimize /* = kTRUE */ )
2602  if (!cl) {
2603  return 0;
2604  }
2605  cl->BuildRealData(pointer);
2607 
2608  // Create StreamerInfo for all base classes.
2609  TBaseClass* base = 0;
2610  TIter nextb(cl->GetListOfBases());
2611  while((base = (TBaseClass*) nextb())) {
2612  if (base->IsSTLContainer()) {
2613  continue;
2614  }
2615  TClass* clm = TClass::GetClass(base->GetName());
2616  BuildStreamerInfo(clm, pointer, canOptimize);
2617  }
2618  if (sinfo && fDirectory) {
2619  sinfo->ForceWriteInfo(fDirectory->GetFile());
2620  }
2621  return sinfo;
2622 }
2623 
2624 ////////////////////////////////////////////////////////////////////////////////
2625 /// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
2626 /// Create a new file. If the original file is named "myfile.root",
2627 /// subsequent files are named "myfile_1.root", "myfile_2.root", etc.
2628 ///
2629 /// Returns a pointer to the new file.
2630 ///
2631 /// Currently, the automatic change of file is restricted
2632 /// to the case where the tree is in the top level directory.
2633 /// The file should not contain sub-directories.
2634 ///
2635 /// Before switching to a new file, the tree header is written
2636 /// to the current file, then the current file is closed.
2637 ///
2638 /// To process the multiple files created by ChangeFile, one must use
2639 /// a TChain.
2640 ///
2641 /// The new file name has a suffix "_N" where N is equal to fFileNumber+1.
2642 /// By default a Root session starts with fFileNumber=0. One can set
2643 /// fFileNumber to a different value via TTree::SetFileNumber.
2644 /// In case a file named "_N" already exists, the function will try
2645 /// a file named "__N", then "___N", etc.
2646 ///
2647 /// fgMaxTreeSize can be set via the static function TTree::SetMaxTreeSize.
2648 /// The default value of fgMaxTreeSize is 100 Gigabytes.
2649 ///
2650 /// If the current file contains other objects like TH1 and TTree,
2651 /// these objects are automatically moved to the new file.
2652 ///
2653 /// IMPORTANT NOTE:
2654 ///
2655 /// Be careful when writing the final Tree header to the file!
2656 ///
2657 /// Don't do:
2658 /// ~~~ {.cpp}
2659 /// TFile *file = new TFile("myfile.root","recreate");
2660 /// TTree *T = new TTree("T","title");
2661 /// T->Fill(); //loop
2662 /// file->Write();
2663 /// file->Close();
2664 /// ~~~
2665 /// but do the following:
2666 /// ~~~ {.cpp}
2667 /// TFile *file = new TFile("myfile.root","recreate");
2668 /// TTree *T = new TTree("T","title");
2669 /// T->Fill(); //loop
2670 /// file = T->GetCurrentFile(); //to get the pointer to the current file
2671 /// file->Write();
2672 /// file->Close();
2673 /// ~~~
2674 
2677  file->cd();
2678  Write();
2679  Reset();
2680  char* fname = new char[2000];
2681  ++fFileNumber;
2682  char uscore[10];
2683  for (Int_t i = 0; i < 10; ++i) {
2684  uscore[i] = 0;
2685  }
2686  Int_t nus = 0;
2687  // Try to find a suitable file name that does not already exist.
2688  while (nus < 10) {
2689  uscore[nus] = '_';
2690  fname[0] = 0;
2691  strlcpy(fname, file->GetName(),2000);
2692 
2693  if (fFileNumber > 1) {
2694  char* cunder = strrchr(fname, '_');
2695  if (cunder) {
2696  snprintf(cunder,2000-Int_t(cunder-fname), "%s%d", uscore, fFileNumber);
2697  const char* cdot = strrchr(file->GetName(), '.');
2698  if (cdot) {
2699  strlcat(fname, cdot,2000);
2700  }
2701  } else {
2702  char fcount[10];
2703  snprintf(fcount,10, "%s%d", uscore, fFileNumber);
2704  strlcat(fname, fcount,2000);
2705  }
2706  } else {
2707  char* cdot = strrchr(fname, '.');
2708  if (cdot) {
2709  snprintf(cdot,2000-Int_t(fname-cdot), "%s%d", uscore, fFileNumber);
2710  strlcat(fname, strrchr(file->GetName(), '.'),2000);
2711  } else {
2712  char fcount[10];
2713  snprintf(fcount,10, "%s%d", uscore, fFileNumber);
2714  strlcat(fname, fcount,2000);
2715  }
2716  }
2717  if (gSystem->AccessPathName(fname)) {
2718  break;
2719  }
2720  ++nus;
2721  Warning("ChangeFile", "file %s already exist, trying with %d underscores", fname, nus+1);
2722  }
2723  Int_t compress = file->GetCompressionSettings();
2724  TFile* newfile = TFile::Open(fname, "recreate", "chain files", compress);
2725  if (newfile == 0) {
2726  Error("Fill","Failed to open new file %s, continuing as a memory tree.",fname);
2727  } else {
2728  Printf("Fill: Switching to new file: %s", fname);
2729  }
2730  // The current directory may contain histograms and trees.
2731  // These objects must be moved to the new file.
2732  TBranch* branch = 0;
2733  TObject* obj = 0;
2734  while ((obj = file->GetList()->First())) {
2735  file->Remove(obj);
2736  // Histogram: just change the directory.
2737  if (obj->InheritsFrom("TH1")) {
2738  gROOT->ProcessLine(TString::Format("((%s*)0x%lx)->SetDirectory((TDirectory*)0x%lx);", obj->ClassName(), (Long_t) obj, (Long_t) newfile));
2739  continue;
2740  }
2741  // Tree: must save all trees in the old file, reset them.
2742  if (obj->InheritsFrom(TTree::Class())) {
2743  TTree* t = (TTree*) obj;
2744  if (t != this) {
2745  t->AutoSave();
2746  t->Reset();
2747  t->fFileNumber = fFileNumber;
2748  }
2749  t->SetDirectory(newfile);
2750  TIter nextb(t->GetListOfBranches());
2751  while ((branch = (TBranch*)nextb())) {
2752  branch->SetFile(newfile);
2753  }
2754  if (t->GetBranchRef()) {
2755  t->GetBranchRef()->SetFile(newfile);
2756  }
2757  continue;
2758  }
2759  // Not a TH1 or a TTree, move object to new file.
2760  if (newfile) newfile->Append(obj);
2761  file->Remove(obj);
2762  }
2763  delete file;
2764  file = 0;
2765  delete[] fname;
2766  fname = 0;
2767  return newfile;
2768 }
2769 
2770 ////////////////////////////////////////////////////////////////////////////////
2771 /// Check whether or not the address described by the last 3 parameters
2772 /// matches the content of the branch. If a Data Model Evolution conversion
2773 /// is involved, reset the fInfo of the branch.
2774 /// The return values are:
2775 //
2776 /// - kMissingBranch (-5) : Missing branch
2777 /// - kInternalError (-4) : Internal error (could not find the type corresponding to a data type number)
2778 /// - kMissingCompiledCollectionProxy (-3) : Missing compiled collection proxy for a compiled collection
2779 /// - kMismatch (-2) : Non-Class Pointer type given does not match the type expected by the branch
2780 /// - kClassMismatch (-1) : Class Pointer type given does not match the type expected by the branch
2781 /// - kMatch (0) : perfect match
2782 /// - kMatchConversion (1) : match with (I/O) conversion
2783 /// - kMatchConversionCollection (2) : match with (I/O) conversion of the content of a collection
2784 /// - kMakeClass (3) : MakeClass mode so we can not check.
2785 /// - kVoidPtr (4) : void* passed so no check was made.
2786 /// - kNoCheck (5) : Underlying TBranch not yet available so no check was made.
2787 
2788 Int_t TTree::CheckBranchAddressType(TBranch* branch, TClass* ptrClass, EDataType datatype, Bool_t isptr)
2790  if (GetMakeClass()) {
2791  // If we are in MakeClass mode so we do not really use classes.
2792  return kMakeClass;
2793  }
2794 
2795  // Let's determine what we need!
2796  TClass* expectedClass = 0;
2797  EDataType expectedType = kOther_t;
2798  if (0 != branch->GetExpectedType(expectedClass,expectedType) ) {
2799  // Something went wrong, the warning message has already be issued.
2800  return kInternalError;
2801  }
2802  if (expectedClass && datatype == kOther_t && ptrClass == 0) {
2803  if (branch->InheritsFrom( TBranchElement::Class() )) {
2804  TBranchElement* bEl = (TBranchElement*)branch;
2805  bEl->SetTargetClass( expectedClass->GetName() );
2806  }
2807  if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2808  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2809  "The class expected (%s) refers to an stl collection and do not have a compiled CollectionProxy. "
2810  "Please generate the dictionary for this class (%s)",
2811  branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2813  }
2814  if (!expectedClass->IsLoaded()) {
2815  // The originally expected class does not have a dictionary, it is then plausible that the pointer being passed is the right type
2816  // (we really don't know). So let's express that.
2817  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2818  "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."
2819  "Please generate the dictionary for this class (%s)",
2820  branch->GetName(), expectedClass->GetName(), expectedClass->GetName());
2821  } else {
2822  Error("SetBranchAddress", "Unable to determine the type given for the address for \"%s\". "
2823  "This is probably due to a missing dictionary, the original data class for this branch is %s.", branch->GetName(), expectedClass->GetName());
2824  }
2825  return kClassMismatch;
2826  }
2827  if (expectedClass && ptrClass && (branch->GetMother() == branch)) {
2828  // Top Level branch
2829  if (!isptr) {
2830  Error("SetBranchAddress", "The address for \"%s\" should be the address of a pointer!", branch->GetName());
2831  }
2832  }
2833  if (expectedType == kFloat16_t) {
2834  expectedType = kFloat_t;
2835  }
2836  if (expectedType == kDouble32_t) {
2837  expectedType = kDouble_t;
2838  }
2839  if (datatype == kFloat16_t) {
2840  datatype = kFloat_t;
2841  }
2842  if (datatype == kDouble32_t) {
2843  datatype = kDouble_t;
2844  }
2845 
2846  /////////////////////////////////////////////////////////////////////////////
2847  // Deal with the class renaming
2848  /////////////////////////////////////////////////////////////////////////////
2849 
2850  if( expectedClass && ptrClass &&
2851  expectedClass != ptrClass &&
2852  branch->InheritsFrom( TBranchElement::Class() ) &&
2853  ptrClass->GetSchemaRules() &&
2854  ptrClass->GetSchemaRules()->HasRuleWithSourceClass( expectedClass->GetName() ) ) {
2855  TBranchElement* bEl = (TBranchElement*)branch;
2856 
2857  if ( ptrClass->GetCollectionProxy() && expectedClass->GetCollectionProxy() ) {
2858  if (gDebug > 7)
2859  Info("SetBranchAddress", "Matching STL collection (at least according to the SchemaRuleSet when "
2860  "reading a %s into a %s",expectedClass->GetName(),ptrClass->GetName());
2861 
2862  bEl->SetTargetClass( ptrClass->GetName() );
2863  return kMatchConversion;
2864 
2865  } else if ( !ptrClass->GetConversionStreamerInfo( expectedClass, bEl->GetClassVersion() ) &&
2866  !ptrClass->FindConversionStreamerInfo( expectedClass, bEl->GetCheckSum() ) ) {
2867  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());
2868 
2869  bEl->SetTargetClass( expectedClass->GetName() );
2870  return kClassMismatch;
2871  }
2872  else {
2873 
2874  bEl->SetTargetClass( ptrClass->GetName() );
2875  return kMatchConversion;
2876  }
2877 
2878  } else if (expectedClass && ptrClass && !expectedClass->InheritsFrom(ptrClass)) {
2879 
2880  if (expectedClass->GetCollectionProxy() && ptrClass->GetCollectionProxy() &&
2881  branch->InheritsFrom( TBranchElement::Class() ) &&
2882  expectedClass->GetCollectionProxy()->GetValueClass() &&
2883  ptrClass->GetCollectionProxy()->GetValueClass() )
2884  {
2885  // In case of collection, we know how to convert them, if we know how to convert their content.
2886  // NOTE: we need to extend this to std::pair ...
2887 
2888  TClass *onfileValueClass = expectedClass->GetCollectionProxy()->GetValueClass();
2889  TClass *inmemValueClass = ptrClass->GetCollectionProxy()->GetValueClass();
2890 
2891  if (inmemValueClass->GetSchemaRules() &&
2892  inmemValueClass->GetSchemaRules()->HasRuleWithSourceClass(onfileValueClass->GetName() ) )
2893  {
2894  TBranchElement* bEl = (TBranchElement*)branch;
2895  bEl->SetTargetClass( ptrClass->GetName() );
2897  }
2898  }
2899 
2900  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());
2901  if (branch->InheritsFrom( TBranchElement::Class() )) {
2902  TBranchElement* bEl = (TBranchElement*)branch;
2903  bEl->SetTargetClass( expectedClass->GetName() );
2904  }
2905  return kClassMismatch;
2906 
2907  } else if ((expectedType != kOther_t) && (datatype != kOther_t) && (expectedType != kNoType_t) && (datatype != kNoType_t) && (expectedType != datatype)) {
2908  if (datatype != kChar_t) {
2909  // For backward compatibility we assume that (char*) was just a cast and/or a generic address
2910  Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2911  TDataType::GetTypeName(datatype), datatype, TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2912  return kMismatch;
2913  }
2914  } else if ((expectedClass && (datatype != kOther_t && datatype != kNoType_t && datatype != kInt_t)) ||
2915  (ptrClass && (expectedType != kOther_t && expectedType != kNoType_t && datatype != kInt_t)) ) {
2916  // Sometime a null pointer can look an int, avoid complaining in that case.
2917  if (expectedClass) {
2918  Error("SetBranchAddress", "The pointer type given \"%s\" (%d) does not correspond to the type needed \"%s\" by the branch: %s",
2919  TDataType::GetTypeName(datatype), datatype, expectedClass->GetName(), branch->GetName());
2920  if (branch->InheritsFrom( TBranchElement::Class() )) {
2921  TBranchElement* bEl = (TBranchElement*)branch;
2922  bEl->SetTargetClass( expectedClass->GetName() );
2923  }
2924  } else {
2925  // 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
2926  // a struct).
2927  bool found = false;
2928  if (ptrClass->IsLoaded()) {
2929  TIter next(ptrClass->GetListOfRealData());
2930  TRealData *rdm;
2931  while ((rdm = (TRealData*)next())) {
2932  if (rdm->GetThisOffset() == 0) {
2933  TDataType *dmtype = rdm->GetDataMember()->GetDataType();
2934  if (dmtype) {
2935  EDataType etype = (EDataType)dmtype->GetType();
2936  if (etype == expectedType) {
2937  found = true;
2938  }
2939  }
2940  break;
2941  }
2942  }
2943  } else {
2944  TIter next(ptrClass->GetListOfDataMembers());
2945  TDataMember *dm;
2946  while ((dm = (TDataMember*)next())) {
2947  if (dm->GetOffset() == 0) {
2948  TDataType *dmtype = dm->GetDataType();
2949  if (dmtype) {
2950  EDataType etype = (EDataType)dmtype->GetType();
2951  if (etype == expectedType) {
2952  found = true;
2953  }
2954  }
2955  break;
2956  }
2957  }
2958  }
2959  if (found) {
2960  // let's check the size.
2961  TLeaf *last = (TLeaf*)branch->GetListOfLeaves()->Last();
2962  long len = last->GetOffset() + last->GetLenType() * last->GetLen();
2963  if (len <= ptrClass->Size()) {
2964  return kMatch;
2965  }
2966  }
2967  Error("SetBranchAddress", "The pointer type given \"%s\" does not correspond to the type needed \"%s\" (%d) by the branch: %s",
2968  ptrClass->GetName(), TDataType::GetTypeName(expectedType), expectedType, branch->GetName());
2969  }
2970  return kMismatch;
2971  }
2972  if (expectedClass && expectedClass->GetCollectionProxy() && dynamic_cast<TEmulatedCollectionProxy*>(expectedClass->GetCollectionProxy())) {
2973  Error("SetBranchAddress", writeStlWithoutProxyMsg,
2974  expectedClass->GetName(), branch->GetName(), expectedClass->GetName());
2975  if (branch->InheritsFrom( TBranchElement::Class() )) {
2976  TBranchElement* bEl = (TBranchElement*)branch;
2977  bEl->SetTargetClass( expectedClass->GetName() );
2978  }
2980  }
2981  if (expectedClass && branch->InheritsFrom( TBranchElement::Class() )) {
2982  TBranchElement* bEl = (TBranchElement*)branch;
2983  bEl->SetTargetClass( expectedClass->GetName() );
2984  }
2985  return kMatch;
2986 }
2987 
2988 ////////////////////////////////////////////////////////////////////////////////
2989 /// Create a clone of this tree and copy nentries.
2990 ///
2991 /// By default copy all entries.
2992 /// The compression level of the cloned tree is set to the destination
2993 /// file's compression level.
2994 ///
2995 /// NOTE: Only active branches are copied.
2996 /// NOTE: If the TTree is a TChain, the structure of the first TTree
2997 /// is used for the copy.
2998 ///
2999 /// IMPORTANT: The cloned tree stays connected with this tree until
3000 /// this tree is deleted. In particular, any changes in
3001 /// branch addresses in this tree are forwarded to the
3002 /// clone trees, unless a branch in a clone tree has had
3003 /// its address changed, in which case that change stays in
3004 /// effect. When this tree is deleted, all the addresses of
3005 /// the cloned tree are reset to their default values.
3006 ///
3007 /// If 'option' contains the word 'fast' and nentries is -1, the
3008 /// cloning will be done without unzipping or unstreaming the baskets
3009 /// (i.e., a direct copy of the raw bytes on disk).
3010 ///
3011 /// When 'fast' is specified, 'option' can also contain a sorting
3012 /// order for the baskets in the output file.
3013 ///
3014 /// There are currently 3 supported sorting order:
3015 ///
3016 /// - SortBasketsByOffset (the default)
3017 /// - SortBasketsByBranch
3018 /// - SortBasketsByEntry
3019 ///
3020 /// When using SortBasketsByOffset the baskets are written in the
3021 /// output file in the same order as in the original file (i.e. the
3022 /// baskets are sorted by their offset in the original file; Usually
3023 /// this also means that the baskets are sorted by the index/number of
3024 /// the _last_ entry they contain)
3025 ///
3026 /// When using SortBasketsByBranch all the baskets of each individual
3027 /// branches are stored contiguously. This tends to optimize reading
3028 /// speed when reading a small number (1->5) of branches, since all
3029 /// their baskets will be clustered together instead of being spread
3030 /// across the file. However it might decrease the performance when
3031 /// reading more branches (or the full entry).
3032 ///
3033 /// When using SortBasketsByEntry the baskets with the lowest starting
3034 /// entry are written first. (i.e. the baskets are sorted by the
3035 /// index/number of the first entry they contain). This means that on
3036 /// the file the baskets will be in the order in which they will be
3037 /// needed when reading the whole tree sequentially.
3038 ///
3039 /// For examples of CloneTree, see tutorials:
3040 ///
3041 /// - copytree.C:
3042 /// A macro to copy a subset of a TTree to a new TTree.
3043 /// The input file has been generated by the program in
3044 /// $ROOTSYS/test/Event with: Event 1000 1 1 1
3045 ///
3046 /// - copytree2.C:
3047 /// A macro to copy a subset of a TTree to a new TTree.
3048 /// One branch of the new Tree is written to a separate file.
3049 /// The input file has been generated by the program in
3050 /// $ROOTSYS/test/Event with: Event 1000 1 1 1
3051 
3052 TTree* TTree::CloneTree(Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3054  // Options
3055  Bool_t fastClone = kFALSE;
3056 
3057  TString opt = option;
3058  opt.ToLower();
3059  if (opt.Contains("fast")) {
3060  fastClone = kTRUE;
3061  }
3062 
3063  // If we are a chain, switch to the first tree.
3064  if ((fEntries > 0) && (LoadTree(0) < 0)) {
3065  // FIXME: We need an error message here.
3066  return 0;
3067  }
3068 
3069  // Note: For a tree we get the this pointer, for
3070  // a chain we get the chain's current tree.
3071  TTree* thistree = GetTree();
3072 
3073  // We will use this to override the IO features on the cloned branches.
3074  ROOT::TIOFeatures features = this->GetIOFeatures();
3075  ;
3076 
3077  // Note: For a chain, the returned clone will be
3078  // a clone of the chain's first tree.
3079  TTree* newtree = (TTree*) thistree->Clone();
3080  if (!newtree) {
3081  return 0;
3082  }
3083 
3084  // The clone should not delete any objects allocated by SetAddress().
3085  TObjArray* branches = newtree->GetListOfBranches();
3086  Int_t nb = branches->GetEntriesFast();
3087  for (Int_t i = 0; i < nb; ++i) {
3088  TBranch* br = (TBranch*) branches->UncheckedAt(i);
3089  if (br->InheritsFrom(TBranchElement::Class())) {
3090  ((TBranchElement*) br)->ResetDeleteObject();
3091  }
3092  }
3093 
3094  // Add the new tree to the list of clones so that
3095  // we can later inform it of changes to branch addresses.
3096  thistree->AddClone(newtree);
3097  if (thistree != this) {
3098  // In case this object is a TChain, add the clone
3099  // also to the TChain's list of clones.
3100  AddClone(newtree);
3101  }
3102 
3103  newtree->Reset();
3104 
3105  TDirectory* ndir = newtree->GetDirectory();
3106  TFile* nfile = 0;
3107  if (ndir) {
3108  nfile = ndir->GetFile();
3109  }
3110  Int_t newcomp = -1;
3111  if (nfile) {
3112  newcomp = nfile->GetCompressionSettings();
3113  }
3114 
3115  //
3116  // Delete non-active branches from the clone.
3117  //
3118  // Note: If we are a chain, this does nothing
3119  // since chains have no leaves.
3120  TObjArray* leaves = newtree->GetListOfLeaves();
3121  Int_t nleaves = leaves->GetEntriesFast();
3122  for (Int_t lndx = 0; lndx < nleaves; ++lndx) {
3123  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(lndx);
3124  if (!leaf) {
3125  continue;
3126  }
3127  TBranch* branch = leaf->GetBranch();
3128  if (branch && (newcomp > -1)) {
3129  branch->SetCompressionSettings(newcomp);
3130  }
3131  if (branch) branch->SetIOFeatures(features);
3132  if (!branch || !branch->TestBit(kDoNotProcess)) {
3133  continue;
3134  }
3135  // size might change at each iteration of the loop over the leaves.
3136  nb = branches->GetEntriesFast();
3137  for (Long64_t i = 0; i < nb; ++i) {
3138  TBranch* br = (TBranch*) branches->UncheckedAt(i);
3139  if (br == branch) {
3140  branches->RemoveAt(i);
3141  delete br;
3142  br = 0;
3143  branches->Compress();
3144  break;
3145  }
3146  TObjArray* lb = br->GetListOfBranches();
3147  Int_t nb1 = lb->GetEntriesFast();
3148  for (Int_t j = 0; j < nb1; ++j) {
3149  TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
3150  if (!b1) {
3151  continue;
3152  }
3153  if (b1 == branch) {
3154  lb->RemoveAt(j);
3155  delete b1;
3156  b1 = 0;
3157  lb->Compress();
3158  break;
3159  }
3160  TObjArray* lb1 = b1->GetListOfBranches();
3161  Int_t nb2 = lb1->GetEntriesFast();
3162  for (Int_t k = 0; k < nb2; ++k) {
3163  TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
3164  if (!b2) {
3165  continue;
3166  }
3167  if (b2 == branch) {
3168  lb1->RemoveAt(k);
3169  delete b2;
3170  b2 = 0;
3171  lb1->Compress();
3172  break;
3173  }
3174  }
3175  }
3176  }
3177  }
3178  leaves->Compress();
3179 
3180  // Copy MakeClass status.
3181  newtree->SetMakeClass(fMakeClass);
3182 
3183  // Copy branch addresses.
3184  CopyAddresses(newtree);
3185 
3186  //
3187  // Copy entries if requested.
3188  //
3189 
3190  if (nentries != 0) {
3191  if (fastClone && (nentries < 0)) {
3192  if ( newtree->CopyEntries( this, -1, option ) < 0 ) {
3193  // There was a problem!
3194  Error("CloneTTree", "TTree has not been cloned\n");
3195  delete newtree;
3196  newtree = 0;
3197  return 0;
3198  }
3199  } else {
3200  newtree->CopyEntries( this, nentries, option );
3201  }
3202  }
3203 
3204  return newtree;
3205 }
3206 
3207 ////////////////////////////////////////////////////////////////////////////////
3208 /// Set branch addresses of passed tree equal to ours.
3209 /// If undo is true, reset the branch address instead of copying them.
3210 /// This insures 'separation' of a cloned tree from its original
3211 
3214  // Copy branch addresses starting from branches.
3216  Int_t nbranches = branches->GetEntriesFast();
3217  for (Int_t i = 0; i < nbranches; ++i) {
3218  TBranch* branch = (TBranch*) branches->UncheckedAt(i);
3219  if (branch->TestBit(kDoNotProcess)) {
3220  continue;
3221  }
3222  if (undo) {
3223  TBranch* br = tree->GetBranch(branch->GetName());
3224  tree->ResetBranchAddress(br);
3225  } else {
3226  char* addr = branch->GetAddress();
3227  if (!addr) {
3228  if (branch->IsA() == TBranch::Class()) {
3229  // If the branch was created using a leaflist, the branch itself may not have
3230  // an address but the leaf might already.
3231  TLeaf *firstleaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
3232  if (!firstleaf || firstleaf->GetValuePointer()) {
3233  // Either there is no leaf (and thus no point in copying the address)
3234  // or the leaf has an address but we can not copy it via the branche
3235  // this will be copied via the next loop (over the leaf).
3236  continue;
3237  }
3238  }
3239  // Note: This may cause an object to be allocated.
3240  branch->SetAddress(0);
3241  addr = branch->GetAddress();
3242  }
3243  // FIXME: The GetBranch() function is braindead and may
3244  // not find the branch!
3245  TBranch* br = tree->GetBranch(branch->GetName());
3246  if (br) {
3247  br->SetAddress(addr);
3248  // The copy does not own any object allocated by SetAddress().
3249  if (br->InheritsFrom(TBranchElement::Class())) {
3250  ((TBranchElement*) br)->ResetDeleteObject();
3251  }
3252  } else {
3253  Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3254  }
3255  }
3256  }
3257 
3258  // Copy branch addresses starting from leaves.
3259  TObjArray* tleaves = tree->GetListOfLeaves();
3260  Int_t ntleaves = tleaves->GetEntriesFast();
3261  for (Int_t i = 0; i < ntleaves; ++i) {
3262  TLeaf* tleaf = (TLeaf*) tleaves->UncheckedAt(i);
3263  TBranch* tbranch = tleaf->GetBranch();
3264  TBranch* branch = GetBranch(tbranch->GetName());
3265  if (!branch) {
3266  continue;
3267  }
3268  TLeaf* leaf = branch->GetLeaf(tleaf->GetName());
3269  if (!leaf) {
3270  continue;
3271  }
3272  if (branch->TestBit(kDoNotProcess)) {
3273  continue;
3274  }
3275  if (undo) {
3276  // Now we know whether the address has been transfered
3277  tree->ResetBranchAddress(tbranch);
3278  } else {
3279  if (!branch->GetAddress() && !leaf->GetValuePointer()) {
3280  // We should attempts to set the address of the branch.
3281  // something like:
3282  //(TBranchElement*)branch->GetMother()->SetAddress(0)
3283  //plus a few more subtilities (see TBranchElement::GetEntry).
3284  //but for now we go the simplest route:
3285  //
3286  // Note: This may result in the allocation of an object.
3287  branch->SetupAddresses();
3288  }
3289  if (branch->GetAddress()) {
3290  tree->SetBranchAddress(branch->GetName(), (void*) branch->GetAddress());
3291  TBranch* br = tree->GetBranch(branch->GetName());
3292  if (br) {
3293  // The copy does not own any object allocated by SetAddress().
3294  // FIXME: We do too much here, br may not be a top-level branch.
3295  if (br->InheritsFrom(TBranchElement::Class())) {
3296  ((TBranchElement*) br)->ResetDeleteObject();
3297  }
3298  } else {
3299  Warning("CopyAddresses", "Could not find branch named '%s' in tree named '%s'", branch->GetName(), tree->GetName());
3300  }
3301  } else {
3302  tleaf->SetAddress(leaf->GetValuePointer());
3303  }
3304  }
3305  }
3306 
3307  if (undo &&
3308  ( tree->IsA()->InheritsFrom("TNtuple") || tree->IsA()->InheritsFrom("TNtupleD") )
3309  ) {
3310  tree->ResetBranchAddresses();
3311  }
3312 }
3313 
3314 namespace {
3315 
3316  enum EOnIndexError { kDrop, kKeep, kBuild };
3318  static Bool_t R__HandleIndex(EOnIndexError onIndexError, TTree *newtree, TTree *oldtree)
3319  {
3320  // Return true if we should continue to handle indices, false otherwise.
3321 
3322  Bool_t withIndex = kTRUE;
3323 
3324  if ( newtree->GetTreeIndex() ) {
3325  if ( oldtree->GetTree()->GetTreeIndex() == 0 ) {
3326  switch (onIndexError) {
3327  case kDrop:
3328  delete newtree->GetTreeIndex();
3329  newtree->SetTreeIndex(0);
3330  withIndex = kFALSE;
3331  break;
3332  case kKeep:
3333  // Nothing to do really.
3334  break;
3335  case kBuild:
3336  // Build the index then copy it
3337  if (oldtree->GetTree()->BuildIndex(newtree->GetTreeIndex()->GetMajorName(), newtree->GetTreeIndex()->GetMinorName())) {
3338  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3339  // Clean up
3340  delete oldtree->GetTree()->GetTreeIndex();
3341  oldtree->GetTree()->SetTreeIndex(0);
3342  }
3343  break;
3344  }
3345  } else {
3346  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3347  }
3348  } else if ( oldtree->GetTree()->GetTreeIndex() != 0 ) {
3349  // We discover the first index in the middle of the chain.
3350  switch (onIndexError) {
3351  case kDrop:
3352  // Nothing to do really.
3353  break;
3354  case kKeep: {
3355  TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3356  index->SetTree(newtree);
3357  newtree->SetTreeIndex(index);
3358  break;
3359  }
3360  case kBuild:
3361  if (newtree->GetEntries() == 0) {
3362  // Start an index.
3363  TVirtualIndex *index = (TVirtualIndex*) oldtree->GetTree()->GetTreeIndex()->Clone();
3364  index->SetTree(newtree);
3365  newtree->SetTreeIndex(index);
3366  } else {
3367  // Build the index so far.
3368  if (newtree->BuildIndex(oldtree->GetTree()->GetTreeIndex()->GetMajorName(), oldtree->GetTree()->GetTreeIndex()->GetMinorName())) {
3369  newtree->GetTreeIndex()->Append(oldtree->GetTree()->GetTreeIndex(), kTRUE);
3370  }
3371  }
3372  break;
3373  }
3374  } else if ( onIndexError == kDrop ) {
3375  // There is no index on this or on tree->GetTree(), we know we have to ignore any further
3376  // index
3377  withIndex = kFALSE;
3378  }
3379  return withIndex;
3380  }
3381 }
3382 
3383 ////////////////////////////////////////////////////////////////////////////////
3384 /// Copy nentries from given tree to this tree.
3385 /// This routines assumes that the branches that intended to be copied are
3386 /// already connected. The typical case is that this tree was created using
3387 /// tree->CloneTree(0).
3388 ///
3389 /// By default copy all entries.
3390 ///
3391 /// Returns number of bytes copied to this tree.
3392 ///
3393 /// If 'option' contains the word 'fast' and nentries is -1, the cloning will be
3394 /// done without unzipping or unstreaming the baskets (i.e., a direct copy of the
3395 /// raw bytes on disk).
3396 ///
3397 /// When 'fast' is specified, 'option' can also contains a sorting order for the
3398 /// baskets in the output file.
3399 ///
3400 /// There are currently 3 supported sorting order:
3401 ///
3402 /// - SortBasketsByOffset (the default)
3403 /// - SortBasketsByBranch
3404 /// - SortBasketsByEntry
3405 ///
3406 /// See TTree::CloneTree for a detailed explanation of the semantics of these 3 options.
3407 ///
3408 /// If the tree or any of the underlying tree of the chain has an index, that index and any
3409 /// index in the subsequent underlying TTree objects will be merged.
3410 ///
3411 /// There are currently three 'options' to control this merging:
3412 /// - NoIndex : all the TTreeIndex object are dropped.
3413 /// - DropIndexOnError : if any of the underlying TTree object do no have a TTreeIndex,
3414 /// they are all dropped.
3415 /// - AsIsIndexOnError [default]: In case of missing TTreeIndex, the resulting TTree index has gaps.
3416 /// - BuildIndexOnError : If any of the underlying TTree objects do not have a TTreeIndex,
3417 /// all TTreeIndex are 'ignored' and the missing piece are rebuilt.
3418 
3419 Long64_t TTree::CopyEntries(TTree* tree, Long64_t nentries /* = -1 */, Option_t* option /* = "" */)
3421  if (!tree) {
3422  return 0;
3423  }
3424  // Options
3425  TString opt = option;
3426  opt.ToLower();
3427  Bool_t fastClone = opt.Contains("fast");
3428  Bool_t withIndex = !opt.Contains("noindex");
3429  EOnIndexError onIndexError;
3430  if (opt.Contains("asisindex")) {
3431  onIndexError = kKeep;
3432  } else if (opt.Contains("buildindex")) {
3433  onIndexError = kBuild;
3434  } else if (opt.Contains("dropindex")) {
3435  onIndexError = kDrop;
3436  } else {
3437  onIndexError = kBuild;
3438  }
3439  Ssiz_t cacheSizeLoc = opt.Index("cachesize=");
3440  Int_t cacheSize = -1;
3441  if (cacheSizeLoc != TString::kNPOS) {
3442  // If the parse faile, cacheSize stays at -1.
3443  Ssiz_t cacheSizeEnd = opt.Index(" ",cacheSizeLoc+10) - (cacheSizeLoc+10);
3444  TSubString cacheSizeStr( opt(cacheSizeLoc+10,cacheSizeEnd) );
3445  auto parseResult = ROOT::FromHumanReadableSize(cacheSizeStr,cacheSize);
3446  if (parseResult == ROOT::EFromHumanReadableSize::kParseFail) {
3447  Warning("CopyEntries","The cachesize option can not be parsed: %s. The default size will be used.",cacheSizeStr.String().Data());
3448  } else if (parseResult == ROOT::EFromHumanReadableSize::kOverflow) {
3449  double m;
3450  const char *munit = nullptr;
3451  ROOT::ToHumanReadableSize(std::numeric_limits<decltype(cacheSize)>::max(),false,&m,&munit);
3452 
3453  Warning("CopyEntries","The cachesize option is too large: %s (%g%s max). The default size will be used.",cacheSizeStr.String().Data(),m,munit);
3454  }
3455  }
3456  if (gDebug > 0 && cacheSize != -1) Info("CopyEntries","Using Cache size: %d\n",cacheSize);
3457 
3458  Long64_t nbytes = 0;
3459  Long64_t treeEntries = tree->GetEntriesFast();
3460  if (nentries < 0) {
3461  nentries = treeEntries;
3462  } else if (nentries > treeEntries) {
3463  nentries = treeEntries;
3464  }
3465 
3466  if (fastClone && (nentries < 0 || nentries == tree->GetEntriesFast())) {
3467  // Quickly copy the basket without decompression and streaming.
3468  Long64_t totbytes = GetTotBytes();
3469  for (Long64_t i = 0; i < nentries; i += tree->GetTree()->GetEntries()) {
3470  if (tree->LoadTree(i) < 0) {
3471  break;
3472  }
3473  if ( withIndex ) {
3474  withIndex = R__HandleIndex( onIndexError, this, tree );
3475  }
3476  if (this->GetDirectory()) {
3477  TFile* file2 = this->GetDirectory()->GetFile();
3478  if (file2 && (file2->GetEND() > TTree::GetMaxTreeSize())) {
3479  if (this->GetDirectory() == (TDirectory*) file2) {
3480  this->ChangeFile(file2);
3481  }
3482  }
3483  }
3484  TTreeCloner cloner(tree->GetTree(), this, option, TTreeCloner::kNoWarnings);
3485  if (cloner.IsValid()) {
3486  this->SetEntries(this->GetEntries() + tree->GetTree()->GetEntries());
3487  if (cacheSize != -1) cloner.SetCacheSize(cacheSize);
3488  cloner.Exec();
3489  } else {
3490  if (i == 0) {
3491  Warning("CopyEntries","%s",cloner.GetWarning());
3492  // If the first cloning does not work, something is really wrong
3493  // (since apriori the source and target are exactly the same structure!)
3494  return -1;
3495  } else {
3496  if (cloner.NeedConversion()) {
3497  TTree *localtree = tree->GetTree();
3498  Long64_t tentries = localtree->GetEntries();
3499  for (Long64_t ii = 0; ii < tentries; ii++) {
3500  if (localtree->GetEntry(ii) <= 0) {
3501  break;
3502  }
3503  this->Fill();
3504  }
3505  if (this->GetTreeIndex()) {
3506  this->GetTreeIndex()->Append(tree->GetTree()->GetTreeIndex(), kTRUE);
3507  }
3508  } else {
3509  Warning("CopyEntries","%s",cloner.GetWarning());
3510  if (tree->GetDirectory() && tree->GetDirectory()->GetFile()) {
3511  Warning("CopyEntries", "Skipped file %s\n", tree->GetDirectory()->GetFile()->GetName());
3512  } else {
3513  Warning("CopyEntries", "Skipped file number %d\n", tree->GetTreeNumber());
3514  }
3515  }
3516  }
3517  }
3518 
3519  }
3520  if (this->GetTreeIndex()) {
3521  this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3522  }
3523  nbytes = GetTotBytes() - totbytes;
3524  } else {
3525  if (nentries < 0) {
3526  nentries = treeEntries;
3527  } else if (nentries > treeEntries) {
3528  nentries = treeEntries;
3529  }
3530  Int_t treenumber = -1;
3531  for (Long64_t i = 0; i < nentries; i++) {
3532  if (tree->LoadTree(i) < 0) {
3533  break;
3534  }
3535  if (treenumber != tree->GetTreeNumber()) {
3536  if ( withIndex ) {
3537  withIndex = R__HandleIndex( onIndexError, this, tree );
3538  }
3539  treenumber = tree->GetTreeNumber();
3540  }
3541  if (tree->GetEntry(i) <= 0) {
3542  break;
3543  }
3544  nbytes += this->Fill();
3545  }
3546  if (this->GetTreeIndex()) {
3547  this->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
3548  }
3549  }
3550  return nbytes;
3551 }
3552 
3553 ////////////////////////////////////////////////////////////////////////////////
3554 /// Copy a tree with selection.
3555 ///
3556 /// ### Important:
3557 ///
3558 /// The returned copied tree stays connected with the original tree
3559 /// until the original tree is deleted. In particular, any changes
3560 /// to the branch addresses in the original tree are also made to
3561 /// the copied tree. Any changes made to the branch addresses of the
3562 /// copied tree are overridden anytime the original tree changes its
3563 /// branch addresses. When the original tree is deleted, all the
3564 /// branch addresses of the copied tree are set to zero.
3565 ///
3566 /// For examples of CopyTree, see the tutorials:
3567 ///
3568 /// - copytree.C:
3569 /// Example macro to copy a subset of a tree to a new tree.
3570 /// The input file was generated by running the program in
3571 /// $ROOTSYS/test/Event in this way:
3572 /// ~~~ {.cpp}
3573 /// ./Event 1000 1 1 1
3574 /// ~~~
3575 /// - copytree2.C
3576 /// Example macro to copy a subset of a tree to a new tree.
3577 /// One branch of the new tree is written to a separate file.
3578 /// The input file was generated by running the program in
3579 /// $ROOTSYS/test/Event in this way:
3580 /// ~~~ {.cpp}
3581 /// ./Event 1000 1 1 1
3582 /// ~~~
3583 /// - copytree3.C
3584 /// Example macro to copy a subset of a tree to a new tree.
3585 /// Only selected entries are copied to the new tree.
3586 /// NOTE that only the active branches are copied.
3587 
3588 TTree* TTree::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
3590  GetPlayer();
3591  if (fPlayer) {
3592  return fPlayer->CopyTree(selection, option, nentries, firstentry);
3593  }
3594  return 0;
3595 }
3596 
3597 ////////////////////////////////////////////////////////////////////////////////
3598 /// Create a basket for this tree and given branch.
3599 
3602  if (!branch) {
3603  return 0;
3604  }
3605  return new TBasket(branch->GetName(), GetName(), branch);
3606 }
3607 
3608 ////////////////////////////////////////////////////////////////////////////////
3609 /// Delete this tree from memory or/and disk.
3610 ///
3611 /// - if option == "all" delete Tree object from memory AND from disk
3612 /// all baskets on disk are deleted. All keys with same name
3613 /// are deleted.
3614 /// - if option =="" only Tree object in memory is deleted.
3615 
3616 void TTree::Delete(Option_t* option /* = "" */)
3618  TFile *file = GetCurrentFile();
3619 
3620  // delete all baskets and header from file
3621  if (file && !strcmp(option,"all")) {
3622  if (!file->IsWritable()) {
3623  Error("Delete","File : %s is not writable, cannot delete Tree:%s", file->GetName(),GetName());
3624  return;
3625  }
3626 
3627  //find key and import Tree header in memory
3628  TKey *key = fDirectory->GetKey(GetName());
3629  if (!key) return;
3630 
3631  TDirectory *dirsav = gDirectory;
3632  file->cd();
3633 
3634  //get list of leaves and loop on all the branches baskets
3635  TIter next(GetListOfLeaves());
3636  TLeaf *leaf;
3637  char header[16];
3638  Int_t ntot = 0;
3639  Int_t nbask = 0;
3640  Int_t nbytes,objlen,keylen;
3641  while ((leaf = (TLeaf*)next())) {
3642  TBranch *branch = leaf->GetBranch();
3643  Int_t nbaskets = branch->GetMaxBaskets();
3644  for (Int_t i=0;i<nbaskets;i++) {
3645  Long64_t pos = branch->GetBasketSeek(i);
3646  if (!pos) continue;
3647  TFile *branchFile = branch->GetFile();
3648  if (!branchFile) continue;
3649  branchFile->GetRecordHeader(header,pos,16,nbytes,objlen,keylen);
3650  if (nbytes <= 0) continue;
3651  branchFile->MakeFree(pos,pos+nbytes-1);
3652  ntot += nbytes;
3653  nbask++;
3654  }
3655  }
3656 
3657  // delete Tree header key and all keys with the same name
3658  // A Tree may have been saved many times. Previous cycles are invalid.
3659  while (key) {
3660  ntot += key->GetNbytes();
3661  key->Delete();
3662  delete key;
3663  key = fDirectory->GetKey(GetName());
3664  }
3665  if (dirsav) dirsav->cd();
3666  if (gDebug) Info("TTree::Delete", "Deleting Tree: %s: %d baskets deleted. Total space freed = %d bytes\n",GetName(),nbask,ntot);
3667  }
3668 
3669  if (fDirectory) {
3670  fDirectory->Remove(this);
3671  //delete the file cache if it points to this Tree
3672  MoveReadCache(file,0);
3673  fDirectory = 0;
3675  }
3676 
3677  // Delete object from CINT symbol table so it can not be used anymore.
3678  gCling->DeleteGlobal(this);
3679 
3680  // Warning: We have intentional invalidated this object while inside a member function!
3681  delete this;
3682 }
3683 
3684  ///////////////////////////////////////////////////////////////////////////////
3685  /// Called by TKey and TObject::Clone to automatically add us to a directory
3686  /// when we are read from a file.
3687 
3690  if (fDirectory == dir) return;
3691  if (fDirectory) {
3692  fDirectory->Remove(this);
3693  // Delete or move the file cache if it points to this Tree
3694  TFile *file = fDirectory->GetFile();
3695  MoveReadCache(file,dir);
3696  }
3697  fDirectory = dir;
3698  TBranch* b = 0;
3699  TIter next(GetListOfBranches());
3700  while((b = (TBranch*) next())) {
3701  b->UpdateFile();
3702  }
3703  if (fBranchRef) {
3705  }
3706  if (fDirectory) fDirectory->Append(this);
3707 }
3708 
3709 ////////////////////////////////////////////////////////////////////////////////
3710 /// Draw expression varexp for specified entries.
3711 ///
3712 /// \return -1 in case of error or number of selected events in case of success.
3713 ///
3714 /// This function accepts TCut objects as arguments.
3715 /// Useful to use the string operator +
3716 ///
3717 /// Example:
3718 ///
3719 /// ~~~ {.cpp}
3720 /// ntuple.Draw("x",cut1+cut2+cut3);
3721 /// ~~~
3722 
3723 
3724 Long64_t TTree::Draw(const char* varexp, const TCut& selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
3726  return TTree::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
3727 }
3728 
3729 ////////////////////////////////////////////////////////////////////////////////
3730 /// Draw expression varexp for specified entries.
3731 ///
3732 /// \return -1 in case of error or number of selected events in case of success.
3733 ///
3734 /// \param [in] varexp is an expression of the general form
3735 /// - "e1" produces a 1-d histogram (TH1F) of expression "e1"
3736 /// - "e1:e2" produces an unbinned 2-d scatter-plot (TGraph) of "e1"
3737 /// on the y-axis versus "e2" on the x-axis
3738 /// - "e1:e2:e3" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3739 /// vs "e2" vs "e3" on the x-, y-, z-axis, respectively.
3740 /// - "e1:e2:e3:e4" produces an unbinned 3-d scatter-plot (TPolyMarker3D) of "e1"
3741 /// vs "e2" vs "e3" and "e4" mapped on the current color palette.
3742 /// (to create histograms in the 2, 3, and 4 dimensional case,
3743 /// see section "Saving the result of Draw to an histogram")
3744 ///
3745 /// Example:
3746 /// - varexp = x simplest case: draw a 1-Dim distribution of column named x
3747 /// - varexp = sqrt(x) : draw distribution of sqrt(x)
3748 /// - varexp = x*y/z
3749 /// - varexp = y:sqrt(x) 2-Dim distribution of y versus sqrt(x)
3750 /// - varexp = px:py:pz:2.5*E produces a 3-d scatter-plot of px vs py ps pz
3751 /// and the color number of each marker will be 2.5*E.
3752 /// If the color number is negative it is set to 0.
3753 /// If the color number is greater than the current number of colors
3754 /// it is set to the highest color number.The default number of
3755 /// colors is 50. see TStyle::SetPalette for setting a new color palette.
3756 ///
3757 /// Note that the variables e1, e2 or e3 may contain a selection.
3758 /// example, if e1= x*(y<0), the value histogrammed will be x if y<0
3759 /// and will be 0 otherwise.
3760 ///
3761 /// The expressions can use all the operations and build-in functions
3762 /// supported by TFormula (See TFormula::Analyze), including free
3763 /// standing function taking numerical arguments (TMath::Bessel).
3764 /// In addition, you can call member functions taking numerical
3765 /// arguments. For example:
3766 /// ~~~ {.cpp}
3767 /// TMath::BreitWigner(fPx,3,2)
3768 /// event.GetHistogram().GetXaxis().GetXmax()
3769 /// ~~~
3770 /// Note: You can only pass expression that depend on the TTree's data
3771 /// to static functions and you can only call non-static member function
3772 /// with 'fixed' parameters.
3773 ///
3774 /// \param [in] selection is an expression with a combination of the columns.
3775 /// In a selection all the C++ operators are authorized.
3776 /// The value corresponding to the selection expression is used as a weight
3777 /// to fill the histogram.
3778 /// If the expression includes only boolean operations, the result
3779 /// is 0 or 1. If the result is 0, the histogram is not filled.
3780 /// In general, the expression may be of the form:
3781 /// ~~~ {.cpp}
3782 /// value*(boolean expression)
3783 /// ~~~
3784 /// if boolean expression is true, the histogram is filled with
3785 /// a `weight = value`.
3786 /// Examples:
3787 /// - selection1 = "x<y && sqrt(z)>3.2"
3788 /// - selection2 = "(x+y)*(sqrt(z)>3.2)"
3789 /// - selection1 returns a weight = 0 or 1
3790 /// - selection2 returns a weight = x+y if sqrt(z)>3.2
3791 /// returns a weight = 0 otherwise.
3792 ///
3793 /// \param [in] option is the drawing option.
3794 /// - When an histogram is produced it can be any histogram drawing option
3795 /// listed in THistPainter.
3796 /// - when no option is specified:
3797 /// - the default histogram drawing option is used
3798 /// if the expression is of the form "e1".
3799 /// - if the expression is of the form "e1:e2"or "e1:e2:e3" a cloud of
3800 /// unbinned 2D or 3D points is drawn respectively.
3801 /// - if the expression has four fields "e1:e2:e3:e4" a 2D scatter is
3802 /// produced with e1 vs e2 vs e3, and e4 is mapped on the current color
3803 /// palette.
3804 /// - If option COL is specified when varexp has three fields:
3805 /// ~~~ {.cpp}
3806 /// tree.Draw("e1:e2:e3","","col");
3807 /// ~~~
3808 /// a 2D scatter is produced with e1 vs e2, and e3 is mapped on the current
3809 /// color palette. The colors for e3 are evaluated once in linear scale before
3810 /// painting. Therefore changing the pad to log scale along Z as no effect
3811 /// on the colors.
3812 /// - if expression has more than four fields the option "PARA"or "CANDLE"
3813 /// can be used.
3814 /// - If option contains the string "goff", no graphics is generated.
3815 ///
3816 /// \param [in] nentries is the number of entries to process (default is all)
3817 ///
3818 /// \param [in] firstentry is the first entry to process (default is 0)
3819 ///
3820 /// ### Drawing expressions using arrays and array elements
3821 ///
3822 /// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
3823 /// or a TClonesArray.
3824 /// In a TTree::Draw expression you can now access fMatrix using the following
3825 /// syntaxes:
3826 ///
3827 /// | String passed | What is used for each entry of the tree
3828 /// |-----------------|--------------------------------------------------------|
3829 /// | `fMatrix` | the 9 elements of fMatrix |
3830 /// | `fMatrix[][]` | the 9 elements of fMatrix |
3831 /// | `fMatrix[2][2]` | only the elements fMatrix[2][2] |
3832 /// | `fMatrix[1]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3833 /// | `fMatrix[1][]` | the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2] |
3834 /// | `fMatrix[][0]` | the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0] |
3835 ///
3836 /// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
3837 ///
3838 /// In summary, if a specific index is not specified for a dimension, TTree::Draw
3839 /// will loop through all the indices along this dimension. Leaving off the
3840 /// last (right most) dimension of specifying then with the two characters '[]'
3841 /// is equivalent. For variable size arrays (and TClonesArray) the range
3842 /// of the first dimension is recalculated for each entry of the tree.
3843 /// You can also specify the index as an expression of any other variables from the
3844 /// tree.
3845 ///
3846 /// TTree::Draw also now properly handling operations involving 2 or more arrays.
3847 ///
3848 /// Let assume a second matrix fResults[5][2], here are a sample of some
3849 /// of the possible combinations, the number of elements they produce and
3850 /// the loop used:
3851 ///
3852 /// | expression | element(s) | Loop |
3853 /// |----------------------------------|------------|--------------------------|
3854 /// | `fMatrix[2][1] - fResults[5][2]` | one | no loop |
3855 /// | `fMatrix[2][] - fResults[5][2]` | three | on 2nd dim fMatrix |
3856 /// | `fMatrix[2][] - fResults[5][]` | two | on both 2nd dimensions |
3857 /// | `fMatrix[][2] - fResults[][1]` | three | on both 1st dimensions |
3858 /// | `fMatrix[][2] - fResults[][]` | six | on both 1st and 2nd dimensions of fResults |
3859 /// | `fMatrix[][2] - fResults[3][]` | two | on 1st dim of fMatrix and 2nd of fResults (at the same time) |
3860 /// | `fMatrix[][] - fResults[][]` | six | on 1st dim then on 2nd dim |
3861 /// | `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.|
3862 ///
3863 ///
3864 /// In summary, TTree::Draw loops through all unspecified dimensions. To
3865 /// figure out the range of each loop, we match each unspecified dimension
3866 /// from left to right (ignoring ALL dimensions for which an index has been
3867 /// specified), in the equivalent loop matched dimensions use the same index
3868 /// and are restricted to the smallest range (of only the matched dimensions).
3869 /// When involving variable arrays, the range can of course be different
3870 /// for each entry of the tree.
3871 ///
3872 /// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
3873 /// ~~~ {.cpp}
3874 /// for (Int_t i0; i < min(3,2); i++) {
3875 /// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
3876 /// }
3877 /// ~~~
3878 /// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
3879 /// ~~~ {.cpp}
3880 /// for (Int_t i0; i < min(3,5); i++) {
3881 /// for (Int_t i1; i1 < 2; i1++) {
3882 /// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
3883 /// }
3884 /// }
3885 /// ~~~
3886 /// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
3887 /// ~~~ {.cpp}
3888 /// for (Int_t i0; i < min(3,5); i++) {
3889 /// for (Int_t i1; i1 < min(3,2); i1++) {
3890 /// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
3891 /// }
3892 /// }
3893 /// ~~~
3894 /// So the loop equivalent to "fMatrix[][fResults[][]]" is:
3895 /// ~~~ {.cpp}
3896 /// for (Int_t i0; i0 < 3; i0++) {
3897 /// for (Int_t j2; j2 < 5; j2++) {
3898 /// for (Int_t j3; j3 < 2; j3++) {
3899 /// i1 = fResults[j2][j3];
3900 /// use the value of fMatrix[i0][i1]
3901 /// }
3902 /// }
3903 /// ~~~
3904 /// ### Retrieving the result of Draw
3905 ///
3906 /// By default the temporary histogram created is called "htemp", but only in
3907 /// the one dimensional Draw("e1") it contains the TTree's data points. For
3908 /// a two dimensional Draw, the data is filled into a TGraph which is named
3909 /// "Graph". They can be retrieved by calling
3910 /// ~~~ {.cpp}
3911 /// TH1F *htemp = (TH1F*)gPad->GetPrimitive("htemp"); // 1D
3912 /// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3913 /// ~~~
3914 /// For a three and four dimensional Draw the TPolyMarker3D is unnamed, and
3915 /// cannot be retrieved.
3916 ///
3917 /// gPad always contains a TH1 derived object called "htemp" which allows to
3918 /// access the axes:
3919 /// ~~~ {.cpp}
3920 /// TGraph *graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
3921 /// TH2F *htemp = (TH2F*)gPad->GetPrimitive("htemp"); // empty, but has axes
3922 /// TAxis *xaxis = htemp->GetXaxis();
3923 /// ~~~
3924 /// ### Saving the result of Draw to an histogram
3925 ///
3926 /// If varexp0 contains >>hnew (following the variable(s) name(s),
3927 /// the new histogram created is called hnew and it is kept in the current
3928 /// directory (and also the current pad). This works for all dimensions.
3929 ///
3930 /// Example:
3931 /// ~~~ {.cpp}
3932 /// tree.Draw("sqrt(x)>>hsqrt","y>0")
3933 /// ~~~
3934 /// will draw `sqrt(x)` and save the histogram as "hsqrt" in the current
3935 /// directory. To retrieve it do:
3936 /// ~~~ {.cpp}
3937 /// TH1F *hsqrt = (TH1F*)gDirectory->Get("hsqrt");
3938 /// ~~~
3939 /// The binning information is taken from the environment variables
3940 /// ~~~ {.cpp}
3941 /// Hist.Binning.?D.?
3942 /// ~~~
3943 /// In addition, the name of the histogram can be followed by up to 9
3944 /// numbers between '(' and ')', where the numbers describe the
3945 /// following:
3946 ///
3947 /// - 1 - bins in x-direction
3948 /// - 2 - lower limit in x-direction
3949 /// - 3 - upper limit in x-direction
3950 /// - 4-6 same for y-direction
3951 /// - 7-9 same for z-direction
3952 ///
3953 /// When a new binning is used the new value will become the default.
3954 /// Values can be skipped.
3955 ///
3956 /// Example:
3957 /// ~~~ {.cpp}
3958 /// tree.Draw("sqrt(x)>>hsqrt(500,10,20)")
3959 /// // plot sqrt(x) between 10 and 20 using 500 bins
3960 /// tree.Draw("sqrt(x):sin(y)>>hsqrt(100,10,60,50,.1,.5)")
3961 /// // plot sqrt(x) against sin(y)
3962 /// // 100 bins in x-direction; lower limit on x-axis is 10; upper limit is 60
3963 /// // 50 bins in y-direction; lower limit on y-axis is .1; upper limit is .5
3964 /// ~~~
3965 /// By default, the specified histogram is reset.
3966 /// To continue to append data to an existing histogram, use "+" in front
3967 /// of the histogram name.
3968 ///
3969 /// A '+' in front of the histogram name is ignored, when the name is followed by
3970 /// binning information as described in the previous paragraph.
3971 /// ~~~ {.cpp}
3972 /// tree.Draw("sqrt(x)>>+hsqrt","y>0")
3973 /// ~~~
3974 /// will not reset `hsqrt`, but will continue filling. This works for 1-D, 2-D
3975 /// and 3-D histograms.
3976 ///
3977 /// ### Accessing collection objects
3978 ///
3979 /// TTree::Draw default's handling of collections is to assume that any
3980 /// request on a collection pertain to it content. For example, if fTracks
3981 /// is a collection of Track objects, the following:
3982 /// ~~~ {.cpp}
3983 /// tree->Draw("event.fTracks.fPx");
3984 /// ~~~
3985 /// will plot the value of fPx for each Track objects inside the collection.
3986 /// Also
3987 /// ~~~ {.cpp}
3988 /// tree->Draw("event.fTracks.size()");
3989 /// ~~~
3990 /// would plot the result of the member function Track::size() for each
3991 /// Track object inside the collection.
3992 /// To access information about the collection itself, TTree::Draw support
3993 /// the '@' notation. If a variable which points to a collection is prefixed
3994 /// or postfixed with '@', the next part of the expression will pertain to
3995 /// the collection object. For example:
3996 /// ~~~ {.cpp}
3997 /// tree->Draw("event.@fTracks.size()");
3998 /// ~~~
3999 /// will plot the size of the collection referred to by `fTracks` (i.e the number
4000 /// of Track objects).
4001 ///
4002 /// ### Drawing 'objects'
4003 ///
4004 /// When a class has a member function named AsDouble or AsString, requesting
4005 /// to directly draw the object will imply a call to one of the 2 functions.
4006 /// If both AsDouble and AsString are present, AsDouble will be used.
4007 /// AsString can return either a char*, a std::string or a TString.s
4008 /// For example, the following
4009 /// ~~~ {.cpp}
4010 /// tree->Draw("event.myTTimeStamp");
4011 /// ~~~
4012 /// will draw the same histogram as
4013 /// ~~~ {.cpp}
4014 /// tree->Draw("event.myTTimeStamp.AsDouble()");
4015 /// ~~~
4016 /// In addition, when the object is a type TString or std::string, TTree::Draw
4017 /// will call respectively `TString::Data` and `std::string::c_str()`
4018 ///
4019 /// If the object is a TBits, the histogram will contain the index of the bit
4020 /// that are turned on.
4021 ///
4022 /// ### Retrieving information about the tree itself.
4023 ///
4024 /// You can refer to the tree (or chain) containing the data by using the
4025 /// string 'This'.
4026 /// You can then could any TTree methods. For example:
4027 /// ~~~ {.cpp}
4028 /// tree->Draw("This->GetReadEntry()");
4029 /// ~~~
4030 /// will display the local entry numbers be read.
4031 /// ~~~ {.cpp}
4032 /// tree->Draw("This->GetUserInfo()->At(0)->GetName()");
4033 /// ~~~
4034 /// will display the name of the first 'user info' object.
4035 ///
4036 /// ### Special functions and variables
4037 ///
4038 /// `Entry$`: A TTree::Draw formula can use the special variable `Entry$`
4039 /// to access the entry number being read. For example to draw every
4040 /// other entry use:
4041 /// ~~~ {.cpp}
4042 /// tree.Draw("myvar","Entry$%2==0");
4043 /// ~~~
4044 /// - `Entry$` : return the current entry number (`== TTree::GetReadEntry()`)
4045 /// - `LocalEntry$` : return the current entry number in the current tree of a
4046 /// chain (`== GetTree()->GetReadEntry()`)
4047 /// - `Entries$` : return the total number of entries (== TTree::GetEntries())
4048 /// - `LocalEntries$` : return the total number of entries in the current tree
4049 /// of a chain (== GetTree()->TTree::GetEntries())
4050 /// - `Length$` : return the total number of element of this formula for this
4051 /// entry (`==TTreeFormula::GetNdata()`)
4052 /// - `Iteration$` : return the current iteration over this formula for this
4053 /// entry (i.e. varies from 0 to `Length$`).
4054 /// - `Length$(formula )` : return the total number of element of the formula
4055 /// given as a parameter.
4056 /// - `Sum$(formula )` : return the sum of the value of the elements of the
4057 /// formula given as a parameter. For example the mean for all the elements in
4058 /// one entry can be calculated with: `Sum$(formula )/Length$(formula )`
4059 /// - `Min$(formula )` : return the minimun (within one TTree entry) of the value of the
4060 /// elements of the formula given as a parameter.
4061 /// - `Max$(formula )` : return the maximum (within one TTree entry) of the value of the
4062 /// elements of the formula given as a parameter.
4063 /// - `MinIf$(formula,condition)`
4064 /// - `MaxIf$(formula,condition)` : return the minimum (maximum) (within one TTree entry)
4065 /// of the value of the elements of the formula given as a parameter
4066 /// if they match the condition. If no element matches the condition,
4067 /// the result is zero. To avoid the resulting peak at zero, use the
4068 /// pattern:
4069 /// ~~~ {.cpp}
4070 /// tree->Draw("MinIf$(formula,condition)","condition");
4071 /// ~~~
4072 /// which will avoid calculation `MinIf$` for the entries that have no match
4073 /// for the condition.
4074 /// - `Alt$(primary,alternate)` : return the value of "primary" if it is available
4075 /// for the current iteration otherwise return the value of "alternate".
4076 /// For example, with arr1[3] and arr2[2]
4077 /// ~~~ {.cpp}
4078 /// tree->Draw("arr1+Alt$(arr2,0)");
4079 /// ~~~
4080 /// will draw arr1[0]+arr2[0] ; arr1[1]+arr2[1] and arr1[2]+0
4081 /// Or with a variable size array arr3
4082 /// ~~~ {.cpp}
4083 /// tree->Draw("Alt$(arr3[0],0)+Alt$(arr3[1],0)+Alt$(arr3[2],0)");
4084 /// ~~~
4085 /// will draw the sum arr3 for the index 0 to min(2,actual_size_of_arr3-1)
4086 /// As a comparison
4087 /// ~~~ {.cpp}
4088 /// tree->Draw("arr3[0]+arr3[1]+arr3[2]");
4089 /// ~~~
4090 /// will draw the sum arr3 for the index 0 to 2 only if the
4091 /// actual_size_of_arr3 is greater or equal to 3.
4092 /// Note that the array in 'primary' is flattened/linearized thus using
4093 /// `Alt$` with multi-dimensional arrays of different dimensions in unlikely
4094 /// to yield the expected results. To visualize a bit more what elements
4095 /// would be matched by TTree::Draw, TTree::Scan can be used:
4096 /// ~~~ {.cpp}
4097 /// tree->Scan("arr1:Alt$(arr2,0)");
4098 /// ~~~
4099 /// will print on one line the value of arr1 and (arr2,0) that will be
4100 /// matched by
4101 /// ~~~ {.cpp}
4102 /// tree->Draw("arr1-Alt$(arr2,0)");
4103 /// ~~~
4104 /// The ternary operator is not directly supported in TTree::Draw however, to plot the
4105 /// equivalent of `var2<20 ? -99 : var1`, you can use:
4106 /// ~~~ {.cpp}
4107 /// tree->Draw("(var2<20)*99+(var2>=20)*var1","");
4108 /// ~~~
4109 ///
4110 /// ### Drawing a user function accessing the TTree data directly
4111 ///
4112 /// If the formula contains a file name, TTree::MakeProxy will be used
4113 /// to load and execute this file. In particular it will draw the
4114 /// result of a function with the same name as the file. The function
4115 /// will be executed in a context where the name of the branches can
4116 /// be used as a C++ variable.
4117 ///
4118 /// For example draw px using the file hsimple.root (generated by the
4119 /// hsimple.C tutorial), we need a file named hsimple.cxx:
4120 /// ~~~ {.cpp}
4121 /// double hsimple() {
4122 /// return px;
4123 /// }
4124 /// ~~~
4125 /// MakeProxy can then be used indirectly via the TTree::Draw interface
4126 /// as follow:
4127 /// ~~~ {.cpp}
4128 /// new TFile("hsimple.root")
4129 /// ntuple->Draw("hsimple.cxx");
4130 /// ~~~
4131 /// A more complete example is available in the tutorials directory:
4132 /// `h1analysisProxy.cxx`, `h1analysProxy.h` and `h1analysisProxyCut.C`
4133 /// which reimplement the selector found in `h1analysis.C`
4134 ///
4135 /// The main features of this facility are:
4136 ///
4137 /// * on-demand loading of branches
4138 /// * ability to use the 'branchname' as if it was a data member
4139 /// * protection against array out-of-bound
4140 /// * ability to use the branch data as object (when the user code is available)
4141 ///
4142 /// See TTree::MakeProxy for more details.
4143 ///
4144 /// ### Making a Profile histogram
4145 ///
4146 /// In case of a 2-Dim expression, one can generate a TProfile histogram
4147 /// instead of a TH2F histogram by specifying option=prof or option=profs
4148 /// or option=profi or option=profg ; the trailing letter select the way
4149 /// the bin error are computed, See TProfile2D::SetErrorOption for
4150 /// details on the differences.
4151 /// The option=prof is automatically selected in case of y:x>>pf
4152 /// where pf is an existing TProfile histogram.
4153 ///
4154 /// ### Making a 2D Profile histogram
4155 ///
4156 /// In case of a 3-Dim expression, one can generate a TProfile2D histogram
4157 /// instead of a TH3F histogram by specifying option=prof or option=profs.
4158 /// or option=profi or option=profg ; the trailing letter select the way
4159 /// the bin error are computed, See TProfile2D::SetErrorOption for
4160 /// details on the differences.
4161 /// The option=prof is automatically selected in case of z:y:x>>pf
4162 /// where pf is an existing TProfile2D histogram.
4163 ///
4164 /// ### Making a 5D plot using GL
4165 ///
4166 /// If option GL5D is specified together with 5 variables, a 5D plot is drawn
4167 /// using OpenGL. See $ROOTSYS/tutorials/tree/staff.C as example.
4168 ///
4169 /// ### Making a parallel coordinates plot
4170 ///
4171 /// In case of a 2-Dim or more expression with the option=para, one can generate
4172 /// a parallel coordinates plot. With that option, the number of dimensions is
4173 /// arbitrary. Giving more than 4 variables without the option=para or
4174 /// option=candle or option=goff will produce an error.
4175 ///
4176 /// ### Making a candle sticks chart
4177 ///
4178 /// In case of a 2-Dim or more expression with the option=candle, one can generate
4179 /// a candle sticks chart. With that option, the number of dimensions is
4180 /// arbitrary. Giving more than 4 variables without the option=para or
4181 /// option=candle or option=goff will produce an error.
4182 ///
4183 /// ### Normalizing the output histogram to 1
4184 ///
4185 /// When option contains "norm" the output histogram is normalized to 1.
4186 ///
4187 /// ### Saving the result of Draw to a TEventList, a TEntryList or a TEntryListArray
4188 ///
4189 /// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
4190 /// instead of histogramming one variable.
4191 /// If varexp0 has the form >>elist , a TEventList object named "elist"
4192 /// is created in the current directory. elist will contain the list
4193 /// of entry numbers satisfying the current selection.
4194 /// If option "entrylist" is used, a TEntryList object is created
4195 /// If the selection contains arrays, vectors or any container class and option
4196 /// "entrylistarray" is used, a TEntryListArray object is created
4197 /// containing also the subentries satisfying the selection, i.e. the indices of
4198 /// the branches which hold containers classes.
4199 /// Example:
4200 /// ~~~ {.cpp}
4201 /// tree.Draw(">>yplus","y>0")
4202 /// ~~~
4203 /// will create a TEventList object named "yplus" in the current directory.
4204 /// In an interactive session, one can type (after TTree::Draw)
4205 /// ~~~ {.cpp}
4206 /// yplus.Print("all")
4207 /// ~~~
4208 /// to print the list of entry numbers in the list.
4209 /// ~~~ {.cpp}
4210 /// tree.Draw(">>yplus", "y>0", "entrylist")
4211 /// ~~~
4212 /// will create a TEntryList object names "yplus" in the current directory
4213 /// ~~~ {.cpp}
4214 /// tree.Draw(">>yplus", "y>0", "entrylistarray")
4215 /// ~~~
4216 /// will create a TEntryListArray object names "yplus" in the current directory
4217 ///
4218 /// By default, the specified entry list is reset.
4219 /// To continue to append data to an existing list, use "+" in front
4220 /// of the list name;
4221 /// ~~~ {.cpp}
4222 /// tree.Draw(">>+yplus","y>0")
4223 /// ~~~
4224 /// will not reset yplus, but will enter the selected entries at the end
4225 /// of the existing list.
4226 ///
4227 /// ### Using a TEventList, TEntryList or TEntryListArray as Input
4228 ///
4229 /// Once a TEventList or a TEntryList object has been generated, it can be used as input
4230 /// for TTree::Draw. Use TTree::SetEventList or TTree::SetEntryList to set the
4231 /// current event list
4232 ///
4233 /// Example 1:
4234 /// ~~~ {.cpp}
4235 /// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
4236 /// tree->SetEventList(elist);
4237 /// tree->Draw("py");
4238 /// ~~~
4239 /// Example 2:
4240 /// ~~~ {.cpp}
4241 /// TEntryList *elist = (TEntryList*)gDirectory->Get("yplus");
4242 /// tree->SetEntryList(elist);
4243 /// tree->Draw("py");
4244 /// ~~~
4245 /// If a TEventList object is used as input, a new TEntryList object is created
4246 /// inside the SetEventList function. In case of a TChain, all tree headers are loaded
4247 /// for this transformation. This new object is owned by the chain and is deleted
4248 /// with it, unless the user extracts it by calling GetEntryList() function.
4249 /// See also comments to SetEventList() function of TTree and TChain.
4250 ///
4251 /// If arrays are used in the selection criteria and TEntryListArray is not used,
4252 /// all the entries that have at least one element of the array that satisfy the selection
4253 /// are entered in the list.
4254 ///
4255 /// Example:
4256 /// ~~~ {.cpp}
4257 /// tree.Draw(">>pyplus","fTracks.fPy>0");
4258 /// tree->SetEventList(pyplus);
4259 /// tree->Draw("fTracks.fPy");
4260 /// ~~~
4261 /// will draw the fPy of ALL tracks in event with at least one track with
4262 /// a positive fPy.
4263 ///
4264 /// To select only the elements that did match the original selection
4265 /// use TEventList::SetReapplyCut or TEntryList::SetReapplyCut.
4266 ///
4267 /// Example:
4268 /// ~~~ {.cpp}
4269 /// tree.Draw(">>pyplus","fTracks.fPy>0");
4270 /// pyplus->SetReapplyCut(kTRUE);
4271 /// tree->SetEventList(pyplus);
4272 /// tree->Draw("fTracks.fPy");
4273 /// ~~~
4274 /// will draw the fPy of only the tracks that have a positive fPy.
4275 ///
4276 /// To draw only the elements that match a selection in case of arrays,
4277 /// you can also use TEntryListArray (faster in case of a more general selection).
4278 ///
4279 /// Example:
4280 /// ~~~ {.cpp}
4281 /// tree.Draw(">>pyplus","fTracks.fPy>0", "entrylistarray");
4282 /// tree->SetEntryList(pyplus);
4283 /// tree->Draw("fTracks.fPy");
4284 /// ~~~
4285 /// will draw the fPy of only the tracks that have a positive fPy,
4286 /// but without redoing the selection.
4287 ///
4288 /// Note: Use tree->SetEventList(0) if you do not want use the list as input.
4289 ///
4290 /// ### How to obtain more info from TTree::Draw
4291 ///
4292 /// Once TTree::Draw has been called, it is possible to access useful
4293 /// information still stored in the TTree object via the following functions:
4294 ///
4295 /// - GetSelectedRows() // return the number of values accepted by the selection expression. In case where no selection was specified, returns the number of values processed.
4296 /// - GetV1() // returns a pointer to the double array of V1
4297 /// - GetV2() // returns a pointer to the double array of V2
4298 /// - GetV3() // returns a pointer to the double array of V3
4299 /// - GetV4() // returns a pointer to the double array of V4
4300 /// - GetW() // returns a pointer to the double array of Weights where weight equal the result of the selection expression.
4301 ///
4302 /// where V1,V2,V3 correspond to the expressions in
4303 /// ~~~ {.cpp}
4304 /// TTree::Draw("V1:V2:V3:V4",selection);
4305 /// ~~~
4306 /// If the expression has more than 4 component use GetVal(index)
4307 ///
4308 /// Example:
4309 /// ~~~ {.cpp}
4310 /// Root > ntuple->Draw("py:px","pz>4");
4311 /// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
4312 /// ntuple->GetV2(), ntuple->GetV1());
4313 /// Root > gr->Draw("ap"); //draw graph in current pad
4314 /// ~~~
4315 ///
4316 /// A more complete complete tutorial (treegetval.C) shows how to use the
4317 /// GetVal() method.
4318 ///
4319 /// creates a TGraph object with a number of points corresponding to the
4320 /// number of entries selected by the expression "pz>4", the x points of the graph
4321 /// being the px values of the Tree and the y points the py values.
4322 ///
4323 /// Important note: By default TTree::Draw creates the arrays obtained
4324 /// with GetW, GetV1, GetV2, GetV3, GetV4, GetVal with a length corresponding
4325 /// to the parameter fEstimate. The content will be the last `GetSelectedRows() % GetEstimate()`
4326 /// values calculated.
4327 /// By default fEstimate=1000000 and can be modified
4328 /// via TTree::SetEstimate. To keep in memory all the results (in case
4329 /// where there is only one result per entry), use
4330 /// ~~~ {.cpp}
4331 /// tree->SetEstimate(tree->GetEntries()+1); // same as tree->SetEstimate(-1);
4332 /// ~~~
4333 /// You must call SetEstimate if the expected number of selected rows
4334 /// you need to look at is greater than 1000000.
4335 ///
4336 /// You can use the option "goff" to turn off the graphics output
4337 /// of TTree::Draw in the above example.
4338 ///
4339 /// ### Automatic interface to TTree::Draw via the TTreeViewer
4340 ///
4341 /// A complete graphical interface to this function is implemented
4342 /// in the class TTreeViewer.
4343 /// To start the TTreeViewer, three possibilities:
4344 /// - select TTree context menu item "StartViewer"
4345 /// - type the command "TTreeViewer TV(treeName)"
4346 /// - execute statement "tree->StartViewer();"
4347 
4348 Long64_t TTree::Draw(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
4350  GetPlayer();
4351  if (fPlayer)
4352  return fPlayer->DrawSelect(varexp,selection,option,nentries,firstentry);
4353  return -1;
4354 }
4355 
4356 ////////////////////////////////////////////////////////////////////////////////
4357 /// Remove some baskets from memory.
4358 
4359 void TTree::DropBaskets()
4361  TBranch* branch = 0;
4363  for (Int_t i = 0; i < nb; ++i) {
4364  branch = (TBranch*) fBranches.UncheckedAt(i);
4365  branch->DropBaskets("all");
4366  }
4367 }
4368 
4369 ////////////////////////////////////////////////////////////////////////////////
4370 /// Drop branch buffers to accommodate nbytes below MaxVirtualsize.
4371 
4374  // Be careful not to remove current read/write buffers.
4375  Int_t ndrop = 0;
4376  Int_t nleaves = fLeaves.GetEntriesFast();
4377  for (Int_t i = 0; i < nleaves; ++i) {
4378  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
4379  TBranch* branch = (TBranch*) leaf->GetBranch();
4380  Int_t nbaskets = branch->GetListOfBaskets()->GetEntries();
4381  for (Int_t j = 0; j < nbaskets - 1; ++j) {
4382  if ((j == branch->GetReadBasket()) || (j == branch->GetWriteBasket())) {
4383  continue;
4384  }
4385  TBasket* basket = (TBasket*)branch->GetListOfBaskets()->UncheckedAt(j);
4386  if (basket) {
4387  ndrop += basket->DropBuffers();
4389  return;
4390  }
4391  }
4392  }
4393  }
4394 }
4395 
4396 ////////////////////////////////////////////////////////////////////////////////
4397 /// Fill all branches.
4398 ///
4399 /// This function loops on all the branches of this tree. For
4400 /// each branch, it copies to the branch buffer (basket) the current
4401 /// values of the leaves data types. If a leaf is a simple data type,
4402 /// a simple conversion to a machine independent format has to be done.
4403 ///
4404 /// This machine independent version of the data is copied into a
4405 /// basket (each branch has its own basket). When a basket is full
4406 /// (32k worth of data by default), it is then optionally compressed
4407 /// and written to disk (this operation is also called committing or
4408 /// 'flushing' the basket). The committed baskets are then
4409 /// immediately removed from memory.
4410 ///
4411 /// The function returns the number of bytes committed to the
4412 /// individual branches.
4413 ///
4414 /// If a write error occurs, the number of bytes returned is -1.
4415 ///
4416 /// If no data are written, because, e.g., the branch is disabled,
4417 /// the number of bytes returned is 0.
4418 ///
4419 /// __The baskets are flushed and the Tree header saved at regular intervals__
4420 ///
4421 /// At regular intervals, when the amount of data written so far is
4422 /// greater than fAutoFlush (see SetAutoFlush) all the baskets are flushed to disk.
4423 /// This makes future reading faster as it guarantees that baskets belonging to nearby
4424 /// entries will be on the same disk region.
4425 /// When the first call to flush the baskets happen, we also take this opportunity
4426 /// to optimize the baskets buffers.
4427 /// We also check if the amount of data written is greater than fAutoSave (see SetAutoSave).
4428 /// In this case we also write the Tree header. This makes the Tree recoverable up to this point
4429 /// in case the program writing the Tree crashes.
4430 /// The decisions to FlushBaskets and Auto Save can be made based either on the number
4431 /// of bytes written (fAutoFlush and fAutoSave negative) or on the number of entries
4432 /// written (fAutoFlush and fAutoSave positive).
4433 /// Note that the user can decide to call FlushBaskets and AutoSave in her event loop
4434 /// base on the number of events written instead of the number of bytes written.
4435 ///
4436 /// Note that calling FlushBaskets too often increases the IO time.
4437 ///
4438 /// Note that calling AutoSave too often increases the IO time and also the file size.
4439 
4442  Int_t nbytes = 0;
4443  Int_t nwrite = 0;
4444  Int_t nerror = 0;
4445  Int_t nbranches = fBranches.GetEntriesFast();
4446 
4447  // Case of one single super branch. Automatically update
4448  // all the branch addresses if a new object was created.
4449  if (nbranches == 1)
4450  ((TBranch *)fBranches.UncheckedAt(0))->UpdateAddress();
4451 
4452  if (fBranchRef)
4453  fBranchRef->Clear();
4454 
4455 #ifdef R__USE_IMT
4457  if (fIMTEnabled) {
4458  fIMTFlush = true;
4459  fIMTZipBytes.store(0);
4460  fIMTTotBytes.store(0);
4461  }
4462 #endif
4463 
4464  for (Int_t i = 0; i < nbranches; ++i) {
4465  // Loop over all branches, filling and accumulating bytes written and error counts.
4466  TBranch *branch = (TBranch *)fBranches.UncheckedAt(i);
4467 
4468  if (branch->TestBit(kDoNotProcess))
4469  continue;
4470 
4471 #ifndef R__USE_IMT
4472  nwrite = branch->FillImpl(nullptr);
4473 #else
4474  nwrite = branch->FillImpl(fIMTEnabled ? &imtHelper : nullptr);
4475 #endif
4476  if (nwrite < 0) {
4477  if (nerror < 2) {
4478  Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld\n"
4479  " This error is symptomatic of a Tree created as a memory-resident Tree\n"
4480  " Instead of doing:\n"
4481  " TTree *T = new TTree(...)\n"
4482  " TFile *f = new TFile(...)\n"
4483  " you should do:\n"
4484  " TFile *f = new TFile(...)\n"
4485  " TTree *T = new TTree(...)\n\n",
4486  GetName(), branch->GetName(), nwrite, fEntries + 1);
4487  } else {
4488  Error("Fill", "Failed filling branch:%s.%s, nbytes=%d, entry=%lld", GetName(), branch->GetName(), nwrite,
4489  fEntries + 1);
4490  }
4491  ++nerror;
4492  } else {
4493  nbytes += nwrite;
4494  }
4495  }
4496 
4497 #ifdef R__USE_IMT
4498  if (fIMTFlush) {
4499  imtHelper.Wait();
4500  fIMTFlush = false;
4501  const_cast<TTree *>(this)->AddTotBytes(fIMTTotBytes);
4502  const_cast<TTree *>(this)->AddZipBytes(fIMTZipBytes);
4503  nbytes += imtHelper.GetNbytes();
4504  nerror += imtHelper.GetNerrors();
4505  }
4506 #endif
4507 
4508  if (fBranchRef)
4509  fBranchRef->Fill();
4510 
4511  ++fEntries;
4512 
4513  if (fEntries > fMaxEntries)
4514  KeepCircular();
4515 
4516  if (gDebug > 0)
4517  Info("TTree::Fill", " - A: %d %lld %lld %lld %lld %lld %lld \n", nbytes, fEntries, fAutoFlush, fAutoSave,
4519 
4520  bool autoFlush = false;
4521  bool autoSave = false;
4522 
4523  if (fAutoFlush != 0 || fAutoSave != 0) {
4524  // Is it time to flush or autosave baskets?
4525  if (fFlushedBytes == 0) {
4526  // If fFlushedBytes == 0, it means we never flushed or saved, so
4527  // we need to check if it's time to do it and recompute the values
4528  // of fAutoFlush and fAutoSave in terms of the number of entries.
4529  // Decision can be based initially either on the number of bytes
4530  // or the number of entries written.
4531  Long64_t zipBytes = GetZipBytes();
4532 
4533  if (fAutoFlush)
4534  autoFlush = fAutoFlush < 0 ? (zipBytes > -fAutoFlush) : fEntries % fAutoFlush == 0;
4535 
4536  if (fAutoSave)
4537  autoSave = fAutoSave < 0 ? (zipBytes > -fAutoSave) : fEntries % fAutoSave == 0;
4538 
4539  if (autoFlush || autoSave) {
4540  // First call FlushBasket to make sure that fTotBytes is up to date.
4541  FlushBaskets();
4542  OptimizeBaskets(GetTotBytes(), 1, "");
4543  autoFlush = false; // avoid auto flushing again later
4544 
4545  if (gDebug > 0)
4546  Info("TTree::Fill", "OptimizeBaskets called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n",
4548 
4550  fAutoFlush = fEntries; // Use test on entries rather than bytes
4551 
4552  // subsequently in run
4553  if (fAutoSave < 0) {
4554  // Set fAutoSave to the largest integer multiple of
4555  // fAutoFlush events such that fAutoSave*fFlushedBytes
4556  // < (minus the input value of fAutoSave)
4557  Long64_t totBytes = GetTotBytes();
4558  if (zipBytes != 0) {
4559  fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / zipBytes) / fEntries));
4560  } else if (totBytes != 0) {
4561  fAutoSave = TMath::Max(fAutoFlush, fEntries * ((-fAutoSave / totBytes) / fEntries));
4562  } else {
4563  TBufferFile b(TBuffer::kWrite, 10000);
4564  TTree::Class()->WriteBuffer(b, (TTree *)this);
4565  Long64_t total = b.Length();
4567  }
4568  } else if (fAutoSave > 0) {
4570  }
4571 
4572  if (fAutoSave != 0 && fEntries >= fAutoSave)
4573  autoSave = true;
4574 
4575  if (gDebug > 0)
4576  Info("TTree::Fill", "First AutoFlush. fAutoFlush = %lld, fAutoSave = %lld\n", fAutoFlush, fAutoSave);
4577  }
4578  } else {
4579  // Check if we need to auto flush
4580  if (fAutoFlush) {
4581  if (fNClusterRange == 0)
4582  autoFlush = fEntries > 1 && fEntries % fAutoFlush == 0;
4583  else
4584  autoFlush = (fEntries - fClusterRangeEnd[fNClusterRange - 1]) % fAutoFlush == 0;
4585  }
4586  // Check if we need to auto save
4587  if (fAutoSave)
4588  autoSave = fEntries % fAutoSave == 0;
4589  }
4590  }
4591 
4592  if (autoFlush) {
4593  FlushBaskets();
4594  if (gDebug > 0)
4595  Info("TTree::Fill", "FlushBaskets() called at entry %lld, fZipBytes=%lld, fFlushedBytes=%lld\n", fEntries,
4598  }
4599 
4600  if (autoSave) {
4601  AutoSave(); // does not call FlushBaskets() again
4602  if (gDebug > 0)
4603  Info("TTree::Fill", "AutoSave called at entry %lld, fZipBytes=%lld, fSavedBytes=%lld\n", fEntries,
4605  }
4606 
4607  // Check that output file is still below the maximum size.
4608  // If above, close the current file and continue on a new file.
4609  // Currently, the automatic change of file is restricted
4610  // to the case where the tree is in the top level directory.
4611  if (fDirectory)
4612  if (TFile *file = fDirectory->GetFile())
4613  if ((TDirectory *)file == fDirectory && (file->GetEND() > fgMaxTreeSize))
4614  ChangeFile(file);
4615 
4616  return nerror == 0 ? nbytes : -1;
4617 }
4618 
4619 ////////////////////////////////////////////////////////////////////////////////
4620 /// Search in the array for a branch matching the branch name,
4621 /// with the branch possibly expressed as a 'full' path name (with dots).
4622 
4623 static TBranch *R__FindBranchHelper(TObjArray *list, const char *branchname) {
4624  if (list==0 || branchname == 0 || branchname[0] == '\0') return 0;
4625 
4626  Int_t nbranches = list->GetEntries();
4627 
4628  UInt_t brlen = strlen(branchname);
4629 
4630  for(Int_t index = 0; index < nbranches; ++index) {
4631  TBranch *where = (TBranch*)list->UncheckedAt(index);
4632 
4633  const char *name = where->GetName();
4634  UInt_t len = strlen(name);
4635  if (len && name[len-1]==']') {
4636  const char *dim = strchr(name,'[');
4637  if (dim) {
4638  len = dim - name;
4639  }
4640  }
4641  if (brlen == len && strncmp(branchname,name,len)==0) {
4642  return where;
4643  }
4644  TBranch *next = 0;
4645  if ((brlen >= len) && (branchname[len] == '.')
4646  && strncmp(name, branchname, len) == 0) {
4647  // The prefix subbranch name match the branch name.
4648 
4649  next = where->FindBranch(branchname);
4650  if (!next) {
4651  next = where->FindBranch(branchname+len+1);
4652  }
4653  if (next) return next;
4654  }
4655  const char *dot = strchr((char*)branchname,'.');
4656  if (dot) {
4657  if (len==(size_t)(dot-branchname) &&
4658  strncmp(branchname,name,dot-branchname)==0 ) {
4659  return R__FindBranchHelper(where->GetListOfBranches(),dot+1);
4660  }
4661  }
4662  }
4663  return 0;
4664 }
4665 
4666 ////////////////////////////////////////////////////////////////////////////////
4667 /// Return the branch that correspond to the path 'branchname', which can
4668 /// include the name of the tree or the omitted name of the parent branches.
4669 /// In case of ambiguity, returns the first match.
4670 
4671 TBranch* TTree::FindBranch(const char* branchname)
4673  // We already have been visited while recursively looking
4674  // through the friends tree, let return
4676  return 0;
4677  }
4678 
4679  TBranch* branch = 0;
4680  // If the first part of the name match the TTree name, look for the right part in the
4681  // list of branches.
4682  // This will allow the branchname to be preceded by
4683  // the name of this tree.
4684  if (strncmp(fName.Data(),branchname,fName.Length())==0 && branchname[fName.Length()]=='.') {
4685  branch = R__FindBranchHelper( GetListOfBranches(), branchname + fName.Length() + 1);
4686  if (branch) return branch;
4687  }
4688  // If we did not find it, let's try to find the full name in the list of branches.
4689  branch = R__FindBranchHelper(GetListOfBranches(), branchname);
4690  if (branch) return branch;
4691 
4692  // If we still did not find, let's try to find it within each branch assuming it does not the branch name.
4693  TIter next(GetListOfBranches());
4694  while ((branch = (TBranch*) next())) {
4695  TBranch* nestedbranch = branch->FindBranch(branchname);
4696  if (nestedbranch) {
4697  return nestedbranch;
4698  }
4699  }
4700 
4701  // Search in list of friends.
4702  if (!fFriends) {
4703  return 0;
4704  }
4705  TFriendLock lock(this, kFindBranch);
4706  TIter nextf(fFriends);
4707  TFriendElement* fe = 0;
4708  while ((fe = (TFriendElement*) nextf())) {
4709  TTree* t = fe->GetTree();
4710  if (!t) {
4711  continue;
4712  }
4713  // If the alias is present replace it with the real name.
4714  const char *subbranch = strstr(branchname, fe->GetName());
4715  if (subbranch != branchname) {
4716  subbranch = 0;
4717  }
4718  if (subbranch) {
4719  subbranch += strlen(fe->GetName());
4720  if (*subbranch != '.') {
4721  subbranch = 0;
4722  } else {
4723  ++subbranch;
4724  }
4725  }
4726  std::ostringstream name;
4727  if (subbranch) {
4728  name << t->GetName() << "." << subbranch;
4729  } else {
4730  name << branchname;
4731  }
4732  branch = t->FindBranch(name.str().c_str());
4733  if (branch) {
4734  return branch;
4735  }
4736  }
4737  return 0;
4738 }
4739 
4740 ////////////////////////////////////////////////////////////////////////////////
4741 /// Find leaf..
4742 
4743 TLeaf* TTree::FindLeaf(const char* searchname)
4745  // We already have been visited while recursively looking
4746  // through the friends tree, let's return.
4747  if (kFindLeaf & fFriendLockStatus) {
4748  return 0;
4749  }
4750 
4751  // This will allow the branchname to be preceded by
4752  // the name of this tree.
4753  char* subsearchname = (char*) strstr(searchname, GetName());
4754  if (subsearchname != searchname) {
4755  subsearchname = 0;
4756  }
4757  if (subsearchname) {
4758  subsearchname += strlen(GetName());
4759  if (*subsearchname != '.') {
4760  subsearchname = 0;
4761  } else {
4762  ++subsearchname;
4763  if (subsearchname[0]==0) {
4764  subsearchname = 0;
4765  }
4766  }
4767  }
4768 
4769  TString leafname;
4770  TString leaftitle;
4771  TString longname;
4772  TString longtitle;
4773 
4774  // For leaves we allow for one level up to be prefixed to the name.
4775  TIter next(GetListOfLeaves());
4776  TLeaf* leaf = 0;
4777  while ((leaf = (TLeaf*) next())) {
4778  leafname = leaf->GetName();
4779  Ssiz_t dim = leafname.First('[');
4780  if (dim >= 0) leafname.Remove(dim);
4781 
4782  if (leafname == searchname) {
4783  return leaf;
4784  }
4785  if (subsearchname && leafname == subsearchname) {
4786  return leaf;
4787  }
4788  // The TLeafElement contains the branch name
4789  // in its name, let's use the title.
4790  leaftitle = leaf->GetTitle();
4791  dim = leaftitle.First('[');
4792  if (dim >= 0) leaftitle.Remove(dim);
4793 
4794  if (leaftitle == searchname) {
4795  return leaf;
4796  }
4797  if (subsearchname && leaftitle == subsearchname) {
4798  return leaf;
4799  }
4800  TBranch* branch = leaf->GetBranch();
4801  if (branch) {
4802  longname.Form("%s.%s",branch->GetName(),leafname.Data());
4803  dim = longname.First('[');
4804  if (dim>=0) longname.Remove(dim);
4805  if (longname == searchname) {
4806  return leaf;
4807  }
4808  if (subsearchname && longname == subsearchname) {
4809  return leaf;
4810  }
4811  longtitle.Form("%s.%s",branch->GetName(),leaftitle.Data());
4812  dim = longtitle.First('[');
4813  if (dim>=0) longtitle.Remove(dim);
4814  if (longtitle == searchname) {
4815  return leaf;
4816  }
4817  if (subsearchname && longtitle == subsearchname) {
4818  return leaf;
4819  }
4820  // The following is for the case where the branch is only
4821  // a sub-branch. Since we do not see it through
4822  // TTree::GetListOfBranches, we need to see it indirectly.
4823  // This is the less sturdy part of this search ... it may
4824  // need refining ...
4825  if (strstr(searchname, ".") && !strcmp(searchname, branch->GetName())) {
4826  return leaf;
4827  }
4828  if (subsearchname && strstr(subsearchname, ".") && !strcmp(subsearchname, branch->GetName())) {
4829  return leaf;
4830  }
4831  }
4832  }
4833  // Search in list of friends.
4834  if (!fFriends) {
4835  return 0;
4836  }
4837  TFriendLock lock(this, kFindLeaf);
4838  TIter nextf(fFriends);
4839  TFriendElement* fe = 0;
4840  while ((fe = (TFriendElement*) nextf())) {
4841  TTree* t = fe->GetTree();
4842  if (!t) {
4843  continue;
4844  }
4845  // If the alias is present replace it with the real name.
4846  subsearchname = (char*) strstr(searchname, fe->GetName());
4847  if (subsearchname != searchname) {
4848  subsearchname = 0;
4849  }
4850  if (subsearchname) {
4851  subsearchname += strlen(fe->GetName());
4852  if (*subsearchname != '.') {
4853  subsearchname = 0;
4854  } else {
4855  ++subsearchname;
4856  }
4857  }
4858  if (subsearchname) {
4859  leafname.Form("%s.%s",t->GetName(),subsearchname);
4860  } else {
4861  leafname = searchname;
4862  }
4863  leaf = t->FindLeaf(leafname);
4864  if (leaf) {
4865  return leaf;
4866  }
4867  }
4868  return 0;
4869 }
4870 
4871 ////////////////////////////////////////////////////////////////////////////////
4872 /// Fit a projected item(s) from a tree.
4873 ///
4874 /// funcname is a TF1 function.
4875 ///
4876 /// See TTree::Draw() for explanations of the other parameters.
4877 ///
4878 /// By default the temporary histogram created is called htemp.
4879 /// If varexp contains >>hnew , the new histogram created is called hnew
4880 /// and it is kept in the current directory.
4881 ///
4882 /// The function returns the number of selected entries.
4883 ///
4884 /// Example:
4885 /// ~~~ {.cpp}
4886 /// tree.Fit(pol4,"sqrt(x)>>hsqrt","y>0")
4887 /// ~~~
4888 /// will fit sqrt(x) and save the histogram as "hsqrt" in the current
4889 /// directory.
4890 ///
4891 /// See also TTree::UnbinnedFit
4892 ///
4893 /// ## Return status
4894 ///
4895 /// The function returns the status of the histogram fit (see TH1::Fit)
4896 /// If no entries were selected, the function returns -1;
4897 /// (i.e. fitResult is null if the fit is OK)
4898 
4899 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)
4901  GetPlayer();
4902  if (fPlayer) {
4903  return fPlayer->Fit(funcname, varexp, selection, option, goption, nentries, firstentry);
4904  }
4905  return -1;
4906 }
4907 
4908 namespace {
4909 struct BoolRAIIToggle {
4910  Bool_t &m_val;
4911 
4912  BoolRAIIToggle(Bool_t &val) : m_val(val) { m_val = true; }
4913  ~BoolRAIIToggle() { m_val = false; }
4914 };
4915 }
4916 
4917 ////////////////////////////////////////////////////////////////////////////////
4918 /// Write to disk all the basket that have not yet been individually written.
4919 ///
4920 /// If ROOT has IMT-mode enabled, this will launch multiple TBB tasks in parallel
4921 /// via TThreadExecutor to do this operation; one per basket compression. If the
4922 /// caller utilizes TBB also, care must be taken to prevent deadlocks.
4923 ///
4924 /// For example, let's say the caller holds mutex A and calls FlushBaskets; while
4925 /// TBB is waiting for the ROOT compression tasks to complete, it may decide to
4926 /// run another one of the user's tasks in this thread. If the second user task
4927 /// tries to acquire A, then a deadlock will occur. The example call sequence
4928 /// looks like this:
4929 ///
4930 /// - User acquires mutex A
4931 /// - User calls FlushBaskets.
4932 /// - ROOT launches N tasks and calls wait.
4933 /// - TBB schedules another user task, T2.
4934 /// - T2 tries to acquire mutex A.
4935 ///
4936 /// At this point, the thread will deadlock: the code may function with IMT-mode
4937 /// disabled if the user assumed the legacy code never would run their own TBB
4938 /// tasks.
4939 ///
4940 /// SO: users of TBB who want to enable IMT-mode should carefully review their
4941 /// locking patterns and make sure they hold no coarse-grained application
4942 /// locks when they invoke ROOT.
4943 ///
4944 /// Return the number of bytes written or -1 in case of write error.
4945 
4946 Int_t TTree::FlushBaskets() const
4948  if (!fDirectory) return 0;
4949  Int_t nbytes = 0;
4950  Int_t nerror = 0;
4951  TObjArray *lb = const_cast<TTree*>(this)->GetListOfBranches();
4952  Int_t nb = lb->GetEntriesFast();
4953 
4954 #ifdef R__USE_IMT
4955  if (fIMTEnabled) {
4956  if (fSortedBranches.empty()) { const_cast<TTree*>(this)->InitializeBranchLists(false); }
4957 
4958  BoolRAIIToggle sentry(fIMTFlush);
4959  fIMTZipBytes.store(0);
4960  fIMTTotBytes.store(0);
4961  std::atomic<Int_t> nerrpar(0);
4962  std::atomic<Int_t> nbpar(0);
4963  std::atomic<Int_t> pos(0);
4964 
4965  auto mapFunction = [&]() {
4966  // The branch to process is obtained when the task starts to run.
4967  // This way, since branches are sorted, we make sure that branches
4968  // leading to big tasks are processed first. If we assigned the
4969  // branch at task creation time, the scheduler would not necessarily
4970  // respect our sorting.
4971  Int_t j = pos.fetch_add(1);
4972 
4973  auto branch = fSortedBranches[j].second;
4974  if (R__unlikely(!branch)) { return; }
4975 
4976  if (R__unlikely(gDebug > 0)) {
4977  std::stringstream ss;
4978  ss << std::this_thread::get_id();
4979  Info("FlushBaskets", "[IMT] Thread %s", ss.str().c_str());
4980  Info("FlushBaskets", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
4981  }
4982 
4983  Int_t nbtask = branch->FlushBaskets();
4984 
4985  if (nbtask < 0) { nerrpar++; }
4986  else { nbpar += nbtask; }
4987  };
4988 
4989  ROOT::TThreadExecutor pool;
4990  pool.Foreach(mapFunction, nb);
4991 
4992  fIMTFlush = false;
4993  const_cast<TTree*>(this)->AddTotBytes(fIMTTotBytes);
4994  const_cast<TTree*>(this)->AddZipBytes(fIMTZipBytes);
4995 
4996  return nerrpar ? -1 : nbpar.load();
4997  }
4998 #endif
4999  for (Int_t j = 0; j < nb; j++) {
5000  TBranch* branch = (TBranch*) lb->UncheckedAt(j);
5001  if (branch) {
5002  Int_t nwrite = branch->FlushBaskets();
5003  if (nwrite<0) {
5004  ++nerror;
5005  } else {
5006  nbytes += nwrite;
5007  }
5008  }
5009  }
5010  if (nerror) {
5011  return -1;
5012  } else {
5013  return nbytes;
5014  }
5015 }
5016 
5017 ////////////////////////////////////////////////////////////////////////////////
5018 /// Returns the expanded value of the alias. Search in the friends if any.
5019 
5020 const char* TTree::GetAlias(const char* aliasName) const
5022  // We already have been visited while recursively looking
5023  // through the friends tree, let's return.
5024  if (kGetAlias & fFriendLockStatus) {
5025  return 0;
5026  }
5027  if (fAliases) {
5028  TObject* alias = fAliases->FindObject(aliasName);
5029  if (alias) {
5030  return alias->GetTitle();
5031  }
5032  }
5033  if (!fFriends) {
5034  return 0;
5035  }
5036  TFriendLock lock(const_cast<TTree*>(this), kGetAlias);
5037  TIter nextf(fFriends);
5038  TFriendElement* fe = 0;
5039  while ((fe = (TFriendElement*) nextf())) {
5040  TTree* t = fe->GetTree();
5041  if (t) {
5042  const char* alias = t->GetAlias(aliasName);
5043  if (alias) {
5044  return alias;
5045  }
5046  const char* subAliasName = strstr(aliasName, fe->GetName());
5047  if (subAliasName && (subAliasName[strlen(fe->GetName())] == '.')) {
5048  alias = t->GetAlias(aliasName + strlen(fe->GetName()) + 1);
5049  if (alias) {
5050  return alias;
5051  }
5052  }
5053  }
5054  }
5055  return 0;
5056 }
5057 
5058 ////////////////////////////////////////////////////////////////////////////////
5059 /// Return pointer to the branch with the given name in this tree or its friends.
5060 
5061 TBranch* TTree::GetBranch(const char* name)
5063  if (name == 0) return 0;
5064 
5065  // We already have been visited while recursively
5066  // looking through the friends tree, let's return.
5067  if (kGetBranch & fFriendLockStatus) {
5068  return 0;
5069  }
5070 
5071  // Search using branches.
5073  for (Int_t i = 0; i < nb; i++) {
5074  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
5075  if (!strcmp(branch->GetName(), name)) {
5076  return branch;
5077  }
5078  TObjArray* lb = branch->GetListOfBranches();
5079  Int_t nb1 = lb->GetEntriesFast();
5080  for (Int_t j = 0; j < nb1; j++) {
5081  TBranch* b1 = (TBranch*) lb->UncheckedAt(j);
5082  if (!strcmp(b1->GetName(), name)) {
5083  return b1;
5084  }
5085  TObjArray* lb1 = b1->GetListOfBranches();
5086  Int_t nb2 = lb1->GetEntriesFast();
5087  for (Int_t k = 0; k < nb2; k++) {
5088  TBranch* b2 = (TBranch*) lb1->UncheckedAt(k);
5089  if (!strcmp(b2->GetName(), name)) {
5090  return b2;
5091  }
5092  }
5093  }
5094  }
5095 
5096  // Search using leaves.
5097  TObjArray* leaves = GetListOfLeaves();
5098  Int_t nleaves = leaves->GetEntriesFast();
5099  for (Int_t i = 0; i < nleaves; i++) {
5100  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
5101  TBranch* branch = leaf->GetBranch();
5102  if (!strcmp(branch->GetName(), name)) {
5103  return branch;
5104  }
5105  }
5106 
5107  if (!fFriends) {
5108  return 0;
5109  }
5110 
5111  // Search in list of friends.
5112  TFriendLock lock(this, kGetBranch);
5113  TIter next(fFriends);
5114  TFriendElement* fe = 0;
5115  while ((fe = (TFriendElement*) next())) {
5116  TTree* t = fe->GetTree();
5117  if (t) {
5118  TBranch* branch = t->GetBranch(name);
5119  if (branch) {
5120  return branch;
5121  }
5122  }
5123  }
5124 
5125  // Second pass in the list of friends when
5126  // the branch name is prefixed by the tree name.
5127  next.Reset();
5128  while ((fe = (TFriendElement*) next())) {
5129  TTree* t = fe->GetTree();
5130  if (!t) {
5131  continue;
5132  }
5133  char* subname = (char*) strstr(name, fe->GetName());
5134  if (subname != name) {
5135  continue;
5136  }
5137  Int_t l = strlen(fe->GetName());
5138  subname += l;
5139  if (*subname != '.') {
5140  continue;
5141  }
5142  subname++;
5143  TBranch* branch = t->GetBranch(subname);
5144  if (branch) {
5145  return branch;
5146  }
5147  }
5148  return 0;
5149 }
5150 
5151 ////////////////////////////////////////////////////////////////////////////////
5152 /// Return status of branch with name branchname.
5153 ///
5154 /// - 0 if branch is not activated
5155 /// - 1 if branch is activated
5156 
5157 Bool_t TTree::GetBranchStatus(const char* branchname) const
5159  TBranch* br = const_cast<TTree*>(this)->GetBranch(branchname);
5160  if (br) {
5161  return br->TestBit(kDoNotProcess) == 0;
5162  }
5163  return 0;
5164 }
5165 
5166 ////////////////////////////////////////////////////////////////////////////////
5167 /// Static function returning the current branch style.
5168 ///
5169 /// - style = 0 old Branch
5170 /// - style = 1 new Bronch
5171 
5174  return fgBranchStyle;
5175 }
5176 
5177 ////////////////////////////////////////////////////////////////////////////////
5178 /// Used for automatic sizing of the cache.
5179 ///
5180 /// Estimates a suitable size for the tree cache based on AutoFlush.
5181 /// A cache sizing factor is taken from the configuration. If this yields zero
5182 /// and withDefault is true the historical algorithm for default size is used.
5183 
5184 Long64_t TTree::GetCacheAutoSize(Bool_t withDefault /* = kFALSE */ ) const
5186  const char *stcs;
5187  Double_t cacheFactor = 0.0;
5188  if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) {
5189  cacheFactor = gEnv->GetValue("TTreeCache.Size", 1.0);
5190  } else {
5191  cacheFactor = TString(stcs).Atof();
5192  }
5193 
5194  if (cacheFactor < 0.0) {
5195  // ignore negative factors
5196  cacheFactor = 0.0;
5197  }
5198 
5199  Long64_t cacheSize = 0;
5200 
5201  if (fAutoFlush < 0) cacheSize = Long64_t(-cacheFactor*fAutoFlush);
5202  else if (fAutoFlush == 0) cacheSize = 0;
5203  else cacheSize = Long64_t(cacheFactor*1.5*fAutoFlush*GetZipBytes()/(fEntries+1));
5204 
5205  if (cacheSize >= (INT_MAX / 4)) {
5206  cacheSize = INT_MAX / 4;
5207  }
5208 
5209  if (cacheSize < 0) {
5210  cacheSize = 0;
5211  }
5212 
5213  if (cacheSize == 0 && withDefault) {
5214  if (fAutoFlush < 0) cacheSize = -fAutoFlush;
5215  else if (fAutoFlush == 0) cacheSize = 0;
5216  else cacheSize = Long64_t(1.5*fAutoFlush*GetZipBytes()/(fEntries+1));
5217  }
5218 
5219  return cacheSize;
5220 }
5221 
5222 ////////////////////////////////////////////////////////////////////////////////
5223 /// Return an iterator over the cluster of baskets starting at firstentry.
5224 ///
5225 /// This iterator is not yet supported for TChain object.
5226 /// ~~~ {.cpp}
5227 /// TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
5228 /// Long64_t clusterStart;
5229 /// while( (clusterStart = clusterIter()) < tree->GetEntries() ) {
5230 /// printf("The cluster starts at %lld and ends at %lld (inclusive)\n",clusterStart,clusterIter.GetNextEntry()-1);
5231 /// }
5232 /// ~~~
5233 
5236  // create cache if wanted
5238 
5239  return TClusterIterator(this,firstentry);
5240 }
5241 
5242 ////////////////////////////////////////////////////////////////////////////////
5243 /// Return pointer to the current file.
5244 
5247  if (!fDirectory || fDirectory==gROOT) {
5248  return 0;
5249  }
5250  return fDirectory->GetFile();
5251 }
5252 
5253 ////////////////////////////////////////////////////////////////////////////////
5254 /// Return the number of entries matching the selection.
5255 /// Return -1 in case of errors.
5256 ///
5257 /// If the selection uses any arrays or containers, we return the number
5258 /// of entries where at least one element match the selection.
5259 /// GetEntries is implemented using the selector class TSelectorEntries,
5260 /// which can be used directly (see code in TTreePlayer::GetEntries) for
5261 /// additional option.
5262 /// If SetEventList was used on the TTree or TChain, only that subset
5263 /// of entries will be considered.
5264 
5265 Long64_t TTree::GetEntries(const char *selection)
5267  GetPlayer();
5268  if (fPlayer) {
5269  return fPlayer->GetEntries(selection);
5270  }
5271  return -1;
5272 }
5273 
5274 ////////////////////////////////////////////////////////////////////////////////
5275 /// Return pointer to the 1st Leaf named name in any Branch of this Tree or
5276 /// any branch in the list of friend trees.
5277 
5280  if (fEntries) return fEntries;
5281  if (!fFriends) return 0;
5283  if (!fr) return 0;
5284  TTree *t = fr->GetTree();
5285  if (t==0) return 0;
5286  return t->GetEntriesFriend();
5287 }
5288 
5289 ////////////////////////////////////////////////////////////////////////////////
5290 /// Read all branches of entry and return total number of bytes read.
5291 ///
5292 /// - `getall = 0` : get only active branches
5293 /// - `getall = 1` : get all branches
5294 ///
5295 /// The function returns the number of bytes read from the input buffer.
5296 /// If entry does not exist the function returns 0.
5297 /// If an I/O error occurs, the function returns -1.
5298 ///
5299 /// If the Tree has friends, also read the friends entry.
5300 ///
5301 /// To activate/deactivate one or more branches, use TBranch::SetBranchStatus
5302 /// For example, if you have a Tree with several hundred branches, and you
5303 /// are interested only by branches named "a" and "b", do
5304 /// ~~~ {.cpp}
5305 /// mytree.SetBranchStatus("*",0); //disable all branches
5306 /// mytree.SetBranchStatus("a",1);
5307 /// mytree.SetBranchStatus("b",1);
5308 /// ~~~
5309 /// when calling mytree.GetEntry(i); only branches "a" and "b" will be read.
5310 ///
5311 /// __WARNING!!__
5312 /// If your Tree has been created in split mode with a parent branch "parent.",
5313 /// ~~~ {.cpp}
5314 /// mytree.SetBranchStatus("parent",1);
5315 /// ~~~
5316 /// will not activate the sub-branches of "parent". You should do:
5317 /// ~~~ {.cpp}
5318 /// mytree.SetBranchStatus("parent*",1);
5319 /// ~~~
5320 /// Without the trailing dot in the branch creation you have no choice but to
5321 /// call SetBranchStatus explicitly for each of the sub branches.
5322 ///
5323 /// An alternative is to call directly
5324 /// ~~~ {.cpp}
5325 /// brancha.GetEntry(i)
5326 /// branchb.GetEntry(i);
5327 /// ~~~
5328 /// ## IMPORTANT NOTE
5329 ///
5330 /// By default, GetEntry reuses the space allocated by the previous object
5331 /// for each branch. You can force the previous object to be automatically
5332 /// deleted if you call mybranch.SetAutoDelete(kTRUE) (default is kFALSE).
5333 ///
5334 /// Example:
5335 ///
5336 /// Consider the example in $ROOTSYS/test/Event.h
5337 /// The top level branch in the tree T is declared with:
5338 /// ~~~ {.cpp}
5339 /// Event *event = 0; //event must be null or point to a valid object
5340 /// //it must be initialized
5341 /// T.SetBranchAddress("event",&event);
5342 /// ~~~
5343 /// When reading the Tree, one can choose one of these 3 options:
5344 ///
5345 /// ## OPTION 1
5346 ///
5347 /// ~~~ {.cpp}
5348 /// for (Long64_t i=0;i<nentries;i++) {
5349 /// T.GetEntry(i);
5350 /// // the object event has been filled at this point
5351 /// }
5352 /// ~~~
5353 /// The default (recommended). At the first entry an object of the class
5354 /// Event will be created and pointed by event. At the following entries,
5355 /// event will be overwritten by the new data. All internal members that are
5356 /// TObject* are automatically deleted. It is important that these members
5357 /// be in a valid state when GetEntry is called. Pointers must be correctly
5358 /// initialized. However these internal members will not be deleted if the
5359 /// characters "->" are specified as the first characters in the comment
5360 /// field of the data member declaration.
5361 ///
5362 /// If "->" is specified, the pointer member is read via pointer->Streamer(buf).
5363 /// In this case, it is assumed that the pointer is never null (case of
5364 /// pointer TClonesArray *fTracks in the Event example). If "->" is not
5365 /// specified, the pointer member is read via buf >> pointer. In this case
5366 /// the pointer may be null. Note that the option with "->" is faster to
5367 /// read or write and it also consumes less space in the file.
5368 ///
5369 /// ## OPTION 2
5370 ///
5371 /// The option AutoDelete is set
5372 /// ~~~ {.cpp}
5373 /// TBranch *branch = T.GetBranch("event");
5374 /// branch->SetAddress(&event);
5375 /// branch->SetAutoDelete(kTRUE);
5376 /// for (Long64_t i=0;i<nentries;i++) {
5377 /// T.GetEntry(i);
5378 /// // the object event has been filled at this point
5379 /// }
5380 /// ~~~
5381 /// In this case, at each iteration, the object event is deleted by GetEntry
5382 /// and a new instance of Event is created and filled.
5383 ///
5384 /// ## OPTION 3
5385 /// ~~~ {.cpp}
5386 /// Same as option 1, but you delete yourself the event.
5387 ///
5388 /// for (Long64_t i=0;i<nentries;i++) {
5389 /// delete event;
5390 /// event = 0; // EXTREMELY IMPORTANT
5391 /// T.GetEntry(i);
5392 /// // the object event has been filled at this point
5393 /// }
5394 /// ~~~
5395 /// It is strongly recommended to use the default option 1. It has the
5396 /// additional advantage that functions like TTree::Draw (internally calling
5397 /// TTree::GetEntry) will be functional even when the classes in the file are
5398 /// not available.
5399 ///
5400 /// Note: See the comments in TBranchElement::SetAddress() for the
5401 /// object ownership policy of the underlying (user) data.
5402 
5403 Int_t TTree::GetEntry(Long64_t entry, Int_t getall)
5405 
5406  // We already have been visited while recursively looking
5407  // through the friends tree, let return
5408  if (kGetEntry & fFriendLockStatus) return 0;
5409 
5410  if (entry < 0 || entry >= fEntries) return 0;
5411  Int_t i;
5412  Int_t nbytes = 0;
5413  fReadEntry = entry;
5414 
5415  // create cache if wanted
5417 
5418  Int_t nbranches = fBranches.GetEntriesFast();
5419  Int_t nb=0;
5420 
5421  auto seqprocessing = [&]() {
5422  TBranch *branch;
5423  for (i=0;i<nbranches;i++) {
5424  branch = (TBranch*)fBranches.UncheckedAt(i);
5425  nb = branch->GetEntry(entry, getall);
5426  if (nb < 0) break;
5427  nbytes += nb;
5428  }
5429  };
5430 
5431 #ifdef R__USE_IMT
5433  if (fSortedBranches.empty()) InitializeBranchLists(true);
5434 
5435  // Count branches are processed first and sequentially
5436  for (auto branch : fSeqBranches) {
5437  nb = branch->GetEntry(entry, getall);
5438  if (nb < 0) break;
5439  nbytes += nb;
5440  }
5441  if (nb < 0) return nb;
5442 
5443  // Enable this IMT use case (activate its locks)
5445 
5446  Int_t errnb = 0;
5447  std::atomic<Int_t> pos(0);
5448  std::atomic<Int_t> nbpar(0);
5449 
5450  auto mapFunction = [&]() {
5451  // The branch to process is obtained when the task starts to run.
5452  // This way, since branches are sorted, we make sure that branches
5453  // leading to big tasks are processed first. If we assigned the
5454  // branch at task creation time, the scheduler would not necessarily
5455  // respect our sorting.
5456  Int_t j = pos.fetch_add(1);
5457 
5458  Int_t nbtask = 0;
5459  auto branch = fSortedBranches[j].second;
5460 
5461  if (gDebug > 0) {
5462  std::stringstream ss;
5463  ss << std::this_thread::get_id();
5464  Info("GetEntry", "[IMT] Thread %s", ss.str().c_str());
5465  Info("GetEntry", "[IMT] Running task for branch #%d: %s", j, branch->GetName());
5466  }
5467 
5468  std::chrono::time_point<std::chrono::system_clock> start, end;
5469 
5470  start = std::chrono::system_clock::now();
5471  nbtask = branch->GetEntry(entry, getall);
5472  end = std::chrono::system_clock::now();
5473 
5474  Long64_t tasktime = (Long64_t)std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
5475  fSortedBranches[j].first += tasktime;
5476 
5477  if (nbtask < 0) errnb = nbtask;
5478  else nbpar += nbtask;
5479  };
5480 
5481  ROOT::TThreadExecutor pool;
5482  pool.Foreach(mapFunction, fSortedBranches.size());
5483 
5484  if (errnb < 0) {
5485  nb = errnb;
5486  }
5487  else {
5488  // Save the number of bytes read by the tasks
5489  nbytes += nbpar;
5490 
5491  // Re-sort branches if necessary
5495  }
5496  }
5497  }
5498  else {
5499  seqprocessing();
5500  }
5501 #else
5502  seqprocessing();
5503 #endif
5504  if (nb < 0) return nb;
5505 
5506  // GetEntry in list of friends
5507  if (!fFriends) return nbytes;
5508  TFriendLock lock(this,kGetEntry);
5509  TIter nextf(fFriends);
5510  TFriendElement *fe;
5511  while ((fe = (TFriendElement*)nextf())) {
5512  TTree *t = fe->GetTree();
5513  if (t) {
5515  nb = t->GetEntry(t->GetReadEntry(),getall);
5516  } else {
5517  if ( t->LoadTreeFriend(entry,this) >= 0 ) {
5518  nb = t->GetEntry(t->GetReadEntry(),getall);
5519  } else nb = 0;
5520  }
5521  if (nb < 0) return nb;
5522  nbytes += nb;
5523  }
5524  }
5525  return nbytes;
5526 }
5527 
5528 
5529 ////////////////////////////////////////////////////////////////////////////////
5530 /// Divides the top-level branches into two vectors: (i) branches to be
5531 /// processed sequentially and (ii) branches to be processed in parallel.
5532 /// Even if IMT is on, some branches might need to be processed first and in a
5533 /// sequential fashion: in the parallelization of GetEntry, those are the
5534 /// branches that store the size of another branch for every entry
5535 /// (e.g. the size of an array branch). If such branches were processed
5536 /// in parallel with the rest, there could be two threads invoking
5537 /// TBranch::GetEntry on one of them at the same time, since a branch that
5538 /// depends on a size (or count) branch will also invoke GetEntry on the latter.
5539 /// \param[in] checkLeafCount True if we need to check whether some branches are
5540 /// count leaves.
5541 
5542 void TTree::InitializeBranchLists(bool checkLeafCount)
5544  Int_t nbranches = fBranches.GetEntriesFast();
5545 
5546  // The branches to be processed sequentially are those that are the leaf count of another branch
5547  if (checkLeafCount) {
5548  for (Int_t i = 0; i < nbranches; i++) {
5549  TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5550  auto leafCount = ((TLeaf*)branch->GetListOfLeaves()->At(0))->GetLeafCount();
5551  if (leafCount) {
5552  auto countBranch = leafCount->GetBranch();
5553  if (std::find(fSeqBranches.begin(), fSeqBranches.end(), countBranch) == fSeqBranches.end()) {
5554  fSeqBranches.push_back(countBranch);
5555  }
5556  }
5557  }
5558  }
5559 
5560  // The special branch fBranchRef also needs to be processed sequentially
5561  if (fBranchRef) {
5562  fSeqBranches.push_back(fBranchRef);
5563  }
5564 
5565  // Any branch that is not a leaf count can be safely processed in parallel when reading
5566  for (Int_t i = 0; i < nbranches; i++) {
5567  Long64_t bbytes = 0;
5568  TBranch* branch = (TBranch*)fBranches.UncheckedAt(i);
5569  if (std::find(fSeqBranches.begin(), fSeqBranches.end(), branch) == fSeqBranches.end()) {
5570  bbytes = branch->GetTotBytes("*");
5571  fSortedBranches.emplace_back(bbytes, branch);
5572  }
5573  }
5574 
5575  // Initially sort parallel branches by size
5576  std::sort(fSortedBranches.begin(),
5577  fSortedBranches.end(),
5578  [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5579  return a.first > b.first;
5580  });
5581 
5582  for (size_t i = 0; i < fSortedBranches.size(); i++) {
5583  fSortedBranches[i].first = 0LL;
5584  }
5585 }
5586 
5587 ////////////////////////////////////////////////////////////////////////////////
5588 /// Sorts top-level branches by the last average task time recorded per branch.
5589 
5592  for (size_t i = 0; i < fSortedBranches.size(); i++) {
5593  fSortedBranches[i].first *= kNEntriesResortInv;
5594  }
5595 
5596  std::sort(fSortedBranches.begin(),
5597  fSortedBranches.end(),
5598  [](std::pair<Long64_t,TBranch*> a, std::pair<Long64_t,TBranch*> b) {
5599  return a.first > b.first;
5600  });
5601 
5602  for (size_t i = 0; i < fSortedBranches.size(); i++) {
5603  fSortedBranches[i].first = 0LL;
5604  }
5605 }
5606 
5607 ////////////////////////////////////////////////////////////////////////////////
5608 ///Returns the entry list, set to this tree
5609 
5612  return fEntryList;
5613 }
5614 
5615 ////////////////////////////////////////////////////////////////////////////////
5616 /// Return entry number corresponding to entry.
5617 ///
5618 /// if no TEntryList set returns entry
5619 /// else returns the entry number corresponding to the list index=entry
5620 
5623  if (!fEntryList) {
5624  return entry;
5625  }
5626 
5627  return fEntryList->GetEntry(entry);
5628 }
5629 
5630 ////////////////////////////////////////////////////////////////////////////////
5631 /// Return entry number corresponding to major and minor number.
5632 /// Note that this function returns only the entry number, not the data
5633 /// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5634 /// the BuildIndex function has created a table of Long64_t* of sorted values
5635 /// corresponding to val = major<<31 + minor;
5636 /// The function performs binary search in this sorted table.
5637 /// If it finds a pair that matches val, it returns directly the
5638 /// index in the table.
5639 /// If an entry corresponding to major and minor is not found, the function
5640 /// returns the index of the major,minor pair immediately lower than the
5641 /// requested value, ie it will return -1 if the pair is lower than
5642 /// the first entry in the index.
5643 ///
5644 /// See also GetEntryNumberWithIndex
5645 
5648  if (!fTreeIndex) {
5649  return -1;
5650  }
5651  return fTreeIndex->GetEntryNumberWithBestIndex(major, minor);
5652 }
5653 
5654 ////////////////////////////////////////////////////////////////////////////////
5655 /// Return entry number corresponding to major and minor number.
5656 /// Note that this function returns only the entry number, not the data
5657 /// To read the data corresponding to an entry number, use TTree::GetEntryWithIndex
5658 /// the BuildIndex function has created a table of Long64_t* of sorted values
5659 /// corresponding to val = major<<31 + minor;
5660 /// The function performs binary search in this sorted table.
5661 /// If it finds a pair that matches val, it returns directly the
5662 /// index in the table, otherwise it returns -1.
5663 ///
5664 /// See also GetEntryNumberWithBestIndex
5665 
5668  if (!fTreeIndex) {
5669  return -1;
5670  }
5671  return fTreeIndex->GetEntryNumberWithIndex(major, minor);
5672 }
5673 
5674 ////////////////////////////////////////////////////////////////////////////////
5675 /// Read entry corresponding to major and minor number.
5676 ///
5677 /// The function returns the total number of bytes read.
5678 /// If the Tree has friend trees, the corresponding entry with
5679 /// the index values (major,minor) is read. Note that the master Tree
5680 /// and its friend may have different entry serial numbers corresponding
5681 /// to (major,minor).
5682 
5685  // We already have been visited while recursively looking
5686  // through the friends tree, let's return.
5688  return 0;
5689  }
5690  Long64_t serial = GetEntryNumberWithIndex(major, minor);
5691  if (serial < 0) {
5692  return -1;
5693  }
5694  // create cache if wanted
5696 
5697  Int_t i;
5698  Int_t nbytes = 0;
5699  fReadEntry = serial;
5700  TBranch *branch;
5701  Int_t nbranches = fBranches.GetEntriesFast();
5702  Int_t nb;
5703  for (i = 0; i < nbranches; ++i) {
5704  branch = (TBranch*)fBranches.UncheckedAt(i);
5705  nb = branch->GetEntry(serial);
5706  if (nb < 0) return nb;
5707  nbytes += nb;
5708  }
5709  // GetEntry in list of friends
5710  if (!fFriends) return nbytes;
5711  TFriendLock lock(this,kGetEntryWithIndex);
5712  TIter nextf(fFriends);
5713  TFriendElement* fe = 0;
5714  while ((fe = (TFriendElement*) nextf())) {
5715  TTree *t = fe->GetTree();
5716  if (t) {
5717  serial = t->GetEntryNumberWithIndex(major,minor);
5718  if (serial <0) return -nbytes;
5719  nb = t->GetEntry(serial);
5720  if (nb < 0) return nb;
5721  nbytes += nb;
5722  }
5723  }
5724  return nbytes;
5725 }
5726 
5727 ////////////////////////////////////////////////////////////////////////////////
5728 /// Return a pointer to the TTree friend whose name or alias is 'friendname.
5729 
5730 TTree* TTree::GetFriend(const char *friendname) const
5732 
5733  // We already have been visited while recursively
5734  // looking through the friends tree, let's return.
5735  if (kGetFriend & fFriendLockStatus) {
5736  return 0;
5737  }
5738  if (!fFriends) {
5739  return 0;
5740  }
5741  TFriendLock lock(const_cast<TTree*>(this), kGetFriend);
5742  TIter nextf(fFriends);
5743  TFriendElement* fe = 0;
5744  while ((fe = (TFriendElement*) nextf())) {
5745  if (strcmp(friendname,fe->GetName())==0
5746  || strcmp(friendname,fe->GetTreeName())==0) {
5747  return fe->GetTree();
5748  }
5749  }
5750  // After looking at the first level,
5751  // let's see if it is a friend of friends.
5752  nextf.Reset();
5753  fe = 0;
5754  while ((fe = (TFriendElement*) nextf())) {
5755  TTree *res = fe->GetTree()->GetFriend(friendname);
5756  if (res) {
5757  return res;
5758  }
5759  }
5760  return 0;
5761 }
5762 
5763 ////////////////////////////////////////////////////////////////////////////////
5764 /// If the 'tree' is a friend, this method returns its alias name.
5765 ///
5766 /// This alias is an alternate name for the tree.
5767 ///
5768 /// It can be used in conjunction with a branch or leaf name in a TTreeFormula,
5769 /// to specify in which particular tree the branch or leaf can be found if
5770 /// the friend trees have branches or leaves with the same name as the master
5771 /// tree.
5772 ///
5773 /// It can also be used in conjunction with an alias created using
5774 /// TTree::SetAlias in a TTreeFormula, e.g.:
5775 /// ~~~ {.cpp}
5776 /// maintree->Draw("treealias.fPx - treealias.myAlias");
5777 /// ~~~
5778 /// where fPx is a branch of the friend tree aliased as 'treealias' and 'myAlias'
5779 /// was created using TTree::SetAlias on the friend tree.
5780 ///
5781 /// However, note that 'treealias.myAlias' will be expanded literally,
5782 /// without remembering that it comes from the aliased friend and thus
5783 /// the branch name might not be disambiguated properly, which means
5784 /// that you may not be able to take advantage of this feature.
5785 ///
5786 
5787 const char* TTree::GetFriendAlias(TTree* tree) const
5789  if ((tree == this) || (tree == GetTree())) {
5790  return 0;
5791  }
5792 
5793  // We already have been visited while recursively
5794  // looking through the friends tree, let's return.
5796  return 0;
5797  }
5798  if (!fFriends) {
5799  return 0;
5800  }
5801  TFriendLock lock(const_cast<TTree*>(this), kGetFriendAlias);
5802  TIter nextf(fFriends);
5803  TFriendElement* fe = 0;
5804  while ((fe = (TFriendElement*) nextf())) {
5805  TTree* t = fe->GetTree();
5806  if (t == tree) {
5807  return fe->GetName();
5808  }
5809  // Case of a chain:
5810  if (t && t->GetTree() == tree) {
5811  return fe->GetName();
5812  }
5813  }
5814  // After looking at the first level,
5815  // let's see if it is a friend of friends.
5816  nextf.Reset();
5817  fe = 0;
5818  while ((fe = (TFriendElement*) nextf())) {
5819  const char* res = fe->GetTree()->GetFriendAlias(tree);
5820  if (res) {
5821  return res;
5822  }
5823  }
5824  return 0;
5825 }
5826 
5827 ////////////////////////////////////////////////////////////////////////////////
5828 /// Returns the current set of IO settings
5831  return fIOFeatures;
5832 }
5833 
5834 ////////////////////////////////////////////////////////////////////////////////
5835 /// Creates a new iterator that will go through all the leaves on the tree itself and its friend.
5836 
5839  return new TTreeFriendLeafIter(this, dir);
5840 }
5841 
5842 ////////////////////////////////////////////////////////////////////////////////
5843 /// Return pointer to the 1st Leaf named name in any Branch of this
5844 /// Tree or any branch in the list of friend trees.
5845 ///
5846 /// The leaf name can contain the name of a friend tree with the
5847 /// syntax: friend_dir_and_tree.full_leaf_name
5848 /// the friend_dir_and_tree can be of the form:
5849 /// ~~~ {.cpp}
5850 /// TDirectoryName/TreeName
5851 /// ~~~
5852 
5853 TLeaf* TTree::GetLeafImpl(const char* branchname, const char *leafname)
5855  TLeaf *leaf = 0;
5856  if (branchname) {
5857  TBranch *branch = FindBranch(branchname);
5858  if (branch) {
5859  leaf = branch->GetLeaf(leafname);
5860  if (leaf) {
5861  return leaf;
5862  }
5863  }
5864  }
5865  TIter nextl(GetListOfLeaves());
5866  while ((leaf = (TLeaf*)nextl())) {
5867  if (strcmp(leaf->GetName(),leafname)) continue;
5868  if (branchname) {
5869  UInt_t nbch = strlen(branchname);
5870  TBranch *br = leaf->GetBranch();
5871  const char* brname = br->GetName();
5872  TBranch *mother = br->GetMother();
5873  if (strncmp(brname,branchname,nbch)) {
5874  if (mother != br) {
5875  const char *mothername = mother->GetName();
5876  UInt_t motherlen = strlen(mothername);
5877  if (nbch > motherlen && strncmp(mothername,branchname,motherlen)==0 && (mothername[motherlen-1]=='.' || branchname[motherlen]=='.')) {
5878  // 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.
5879  if (strncmp(brname,branchname+motherlen+1,nbch-motherlen-1)) {
5880  // No it does not
5881  continue;
5882  } // else we have match so we can proceed.
5883  } else {
5884  // no match
5885  continue;
5886  }
5887  } else {
5888  continue;
5889  }
5890  }
5891  // The start of the branch name is identical to the content
5892  // of 'aname' before the first '/'.
5893  // Let's make sure that it is not longer (we are trying
5894  // to avoid having jet2/value match the branch jet23
5895  if ((strlen(brname) > nbch) && (brname[nbch] != '.') && (brname[nbch] != '[')) {
5896  continue;
5897  }
5898  }
5899  return leaf;
5900  }
5901  if (!fFriends) return 0;
5902  TFriendLock lock(this,kGetLeaf);
5903  TIter next(fFriends);
5904  TFriendElement *fe;
5905  while ((fe = (TFriendElement*)next())) {
5906  TTree *t = fe->GetTree();
5907  if (t) {
5908  leaf = t->GetLeaf(leafname);
5909  if (leaf) return leaf;
5910  }
5911  }
5912 
5913  //second pass in the list of friends when the leaf name
5914  //is prefixed by the tree name
5915  TString strippedArg;
5916  next.Reset();
5917  while ((fe = (TFriendElement*)next())) {
5918  TTree *t = fe->GetTree();
5919  if (t==0) continue;
5920  char *subname = (char*)strstr(leafname,fe->GetName());
5921  if (subname != leafname) continue;
5922  Int_t l = strlen(fe->GetName());
5923  subname += l;
5924  if (*subname != '.') continue;
5925  subname++;
5926  strippedArg += subname;
5927  leaf = t->GetLeaf(branchname,subname);
5928  if (leaf) return leaf;
5929  }
5930  return 0;
5931 }
5932 
5933 ////////////////////////////////////////////////////////////////////////////////
5934 /// Return pointer to the 1st Leaf named name in any Branch of this
5935 /// Tree or any branch in the list of friend trees.
5936 ///
5937 /// The leaf name can contain the name of a friend tree with the
5938 /// syntax: friend_dir_and_tree.full_leaf_name
5939 /// the friend_dir_and_tree can be of the form:
5940 ///
5941 /// TDirectoryName/TreeName
5942 
5943 TLeaf* TTree::GetLeaf(const char* branchname, const char *leafname)
5945  if (leafname == 0) return 0;
5946 
5947  // We already have been visited while recursively looking
5948  // through the friends tree, let return
5949  if (kGetLeaf & fFriendLockStatus) {
5950  return 0;
5951  }
5952 
5953  return GetLeafImpl(branchname,leafname);
5954 }
5955 
5956 ////////////////////////////////////////////////////////////////////////////////
5957 /// Return pointer to the 1st Leaf named name in any Branch of this
5958 /// Tree or any branch in the list of friend trees.
5959 ///
5960 /// aname may be of the form branchname/leafname
5961 
5962 TLeaf* TTree::GetLeaf(const char* aname)
5964  if (aname == 0) return 0;
5965 
5966  // We already have been visited while recursively looking
5967  // through the friends tree, let return
5968  if (kGetLeaf & fFriendLockStatus) {
5969  return 0;
5970  }
5971  char* slash = (char*) strrchr(aname, '/');
5972  char* name = 0;
5973  UInt_t nbch = 0;
5974  if (slash) {
5975  name = slash + 1;
5976  nbch = slash - aname;
5977  TString brname(aname,nbch);
5978  return GetLeafImpl(brname.Data(),name);
5979  } else {
5980  return GetLeafImpl(0,aname);
5981  }
5982 }
5983 
5984 ////////////////////////////////////////////////////////////////////////////////
5985 /// Return maximum of column with name columname.
5986 /// if the Tree has an associated TEventList or TEntryList, the maximum
5987 /// is computed for the entries in this list.
5988 
5989 Double_t TTree::GetMaximum(const char* columname)
5991  TLeaf* leaf = this->GetLeaf(columname);
5992  if (!leaf) {
5993  return 0;
5994  }
5995 
5996  // create cache if wanted
5998 
5999  TBranch* branch = leaf->GetBranch();
6000  Double_t cmax = -DBL_MAX;
6001  for (Long64_t i = 0; i < fEntries; ++i) {
6002  Long64_t entryNumber = this->GetEntryNumber(i);
6003  if (entryNumber < 0) break;
6004  branch->GetEntry(entryNumber);
6005  for (Int_t j = 0; j < leaf->GetLen(); ++j) {
6006  Double_t val = leaf->GetValue(j);
6007  if (val > cmax) {
6008  cmax = val;
6009  }
6010  }
6011  }
6012  return cmax;
6013 }
6014 
6015 ////////////////////////////////////////////////////////////////////////////////
6016 /// Static function which returns the tree file size limit in bytes.
6017 
6020  return fgMaxTreeSize;
6021 }
6022 
6023 ////////////////////////////////////////////////////////////////////////////////
6024 /// Return minimum of column with name columname.
6025 /// if the Tree has an associated TEventList or TEntryList, the minimum
6026 /// is computed for the entries in this list.
6027 
6028 Double_t TTree::GetMinimum(const char* columname)
6030  TLeaf* leaf = this->GetLeaf(columname);
6031  if (!leaf) {
6032  return 0;
6033  }
6034 
6035  // create cache if wanted
6037 
6038  TBranch* branch = leaf->GetBranch();
6039  Double_t cmin = DBL_MAX;
6040  for (Long64_t i = 0; i < fEntries; ++i) {
6041  Long64_t entryNumber = this->GetEntryNumber(i);
6042  if (entryNumber < 0) break;
6043  branch->GetEntry(entryNumber);
6044  for (Int_t j = 0;j < leaf->GetLen(); ++j) {
6045  Double_t val = leaf->GetValue(j);
6046  if (val < cmin) {
6047  cmin = val;
6048  }
6049  }
6050  }
6051  return cmin;
6052 }
6053 
6054 ////////////////////////////////////////////////////////////////////////////////
6055 /// Load the TTreePlayer (if not already done).
6056 
6059  if (fPlayer) {
6060  return fPlayer;
6061  }
6063  return fPlayer;
6064 }
6065 
6066 ////////////////////////////////////////////////////////////////////////////////
6067 /// Find and return the TTreeCache registered with the file and which may
6068 /// contain branches for us. If create is true and there is no cache
6069 /// a new cache is created with default size.
6070 
6071 TTreeCache *TTree::GetReadCache(TFile *file, Bool_t create /* = kFALSE */ )
6073  TTreeCache *pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
6074  if (pe && pe->GetTree() != this) pe = 0;
6075  if (create && !pe) {
6077  pe = dynamic_cast<TTreeCache*>(file->GetCacheRead(this));
6078  if (pe && pe->GetTree() != this) pe = 0;
6079  }
6080  return pe;
6081 }
6082 
6083 ////////////////////////////////////////////////////////////////////////////////
6084 /// Return a pointer to the list containing user objects associated to this tree.
6085 ///
6086 /// The list is automatically created if it does not exist.
6087 ///
6088 /// WARNING: By default the TTree destructor will delete all objects added
6089 /// to this list. If you do not want these objects to be deleted,
6090 /// call:
6091 ///
6092 /// mytree->GetUserInfo()->Clear();
6093 ///
6094 /// before deleting the tree.
6095 
6098  if (!fUserInfo) {
6099  fUserInfo = new TList();
6100  fUserInfo->SetName("UserInfo");
6101  }
6102  return fUserInfo;
6103 }
6104 
6105 ////////////////////////////////////////////////////////////////////////////////
6106 /// Appends the cluster range information stored in 'fromtree' to this tree,
6107 /// including the value of fAutoFlush.
6108 ///
6109 /// This is used when doing a fast cloning (by TTreeCloner).
6110 /// See also fAutoFlush and fAutoSave if needed.
6111 
6112 void TTree::ImportClusterRanges(TTree *fromtree)
6114  Long64_t autoflush = fromtree->GetAutoFlush();
6115  if (fNClusterRange || fromtree->fNClusterRange) {
6116  Int_t newsize = fNClusterRange + 1 + fromtree->fNClusterRange;
6117  if (newsize > fMaxClusterRange) {
6118  if (fMaxClusterRange) {
6120  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6122  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
6123  fMaxClusterRange = newsize;
6124  } else {
6125  fMaxClusterRange = newsize;
6128  }
6129  }
6132  ++fNClusterRange;
6133  for (Int_t i = 0 ; i < fromtree->fNClusterRange; ++i) {
6135  fClusterSize[fNClusterRange] = fromtree->fClusterSize[i];
6136  ++fNClusterRange;
6137  }
6138  fAutoFlush = autoflush;
6139  } else {
6140  SetAutoFlush( autoflush );
6141  }
6142  Long64_t autosave = GetAutoSave();
6143  if (autoflush > 0 && autosave > 0) {
6144  SetAutoSave( autoflush*(autosave/autoflush) );
6145  }
6146 }
6147 
6148 ////////////////////////////////////////////////////////////////////////////////
6149 /// Keep a maximum of fMaxEntries in memory.
6150 
6151 void TTree::KeepCircular()
6154  Long64_t maxEntries = fMaxEntries - (fMaxEntries / 10);
6155  for (Int_t i = 0; i < nb; ++i) {
6156  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
6157  branch->KeepCircular(maxEntries);
6158  }
6159  if (fNClusterRange) {
6160  Long64_t entriesOffset = fEntries - maxEntries;
6161  Int_t oldsize = fNClusterRange;
6162  for(Int_t i = 0, j = 0; j < oldsize; ++j) {
6163  if (fClusterRangeEnd[j] > entriesOffset) {
6164  fClusterRangeEnd[i] = fClusterRangeEnd[j] - entriesOffset;
6165  ++i;
6166  } else {
6167  --fNClusterRange;
6168  }
6169  }
6170  }
6171  fEntries = maxEntries;
6172  fReadEntry = -1;
6173 }
6174 
6175 ////////////////////////////////////////////////////////////////////////////////
6176 /// Read in memory all baskets from all branches up to the limit of maxmemory bytes.
6177 ///
6178 /// If maxmemory is non null and positive SetMaxVirtualSize is called
6179 /// with this value. Default for maxmemory is 2000000000 (2 Gigabytes).
6180 /// The function returns the total number of baskets read into memory
6181 /// if negative an error occurred while loading the branches.
6182 /// This method may be called to force branch baskets in memory
6183 /// when random access to branch entries is required.
6184 /// If random access to only a few branches is required, you should
6185 /// call directly TBranch::LoadBaskets.
6186 
6189  if (maxmemory > 0) SetMaxVirtualSize(maxmemory);
6190 
6191  TIter next(GetListOfLeaves());
6192  TLeaf *leaf;
6193  Int_t nimported = 0;
6194  while ((leaf=(TLeaf*)next())) {
6195  nimported += leaf->GetBranch()->LoadBaskets();//break;
6196  }
6197  return nimported;
6198 }
6199 
6200 ////////////////////////////////////////////////////////////////////////////////
6201 /// Set current entry.
6202 ///
6203 /// Returns -2 if entry does not exist (just as TChain::LoadTree()).
6204 ///
6205 /// Note: This function is overloaded in TChain.
6206 ///
6207 
6210  // We already have been visited while recursively looking
6211  // through the friends tree, let return
6212  if (kLoadTree & fFriendLockStatus) {
6213  // We need to return a negative value to avoid a circular list of friend
6214  // to think that there is always an entry somewhere in the list.
6215  return -1;
6216  }
6217 
6218  if (fNotify) {
6219  if (fReadEntry < 0) {
6220  fNotify->Notify();
6221  }
6222  }
6223  fReadEntry = entry;
6224 
6225  Bool_t friendHasEntry = kFALSE;
6226  if (fFriends) {
6227  // Set current entry in friends as well.
6228  //
6229  // An alternative would move this code to each of the
6230  // functions calling LoadTree (and to overload a few more).
6231  Bool_t needUpdate = kFALSE;
6232  {
6233  // This scope is need to insure the lock is released at the right time
6234  TIter nextf(fFriends);
6235  TFriendLock lock(this, kLoadTree);
6236  TFriendElement* fe = 0;
6237  while ((fe = (TFriendElement*) nextf())) {
6239  // This friend element was added by the chain that owns this
6240  // tree, the chain will deal with loading the correct entry.
6241  continue;
6242  }
6243  TTree* friendTree = fe->GetTree();
6244  if (friendTree == 0) {
6245  // Somehow we failed to retrieve the friend TTree.
6246  } else if (friendTree->IsA() == TTree::Class()) {
6247  // Friend is actually a tree.
6248  if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6249  friendHasEntry = kTRUE;
6250  }
6251  } else {
6252  // Friend is actually a chain.
6253  // FIXME: This logic should be in the TChain override.
6254  Int_t oldNumber = friendTree->GetTreeNumber();
6255  if (friendTree->LoadTreeFriend(entry, this) >= 0) {
6256  friendHasEntry = kTRUE;
6257  }
6258  Int_t newNumber = friendTree->GetTreeNumber();
6259  if (oldNumber != newNumber) {
6260  // We can not just compare the tree pointers because they could be reused.
6261  // So we compare the tree number instead.
6262  needUpdate = kTRUE;
6263  }
6264  }
6265  } // for each friend
6266  }
6267  if (needUpdate) {
6268  //update list of leaves in all TTreeFormula of the TTreePlayer (if any)
6269  if (fPlayer) {
6271  }
6272  //Notify user if requested
6273  if (fNotify) {
6274  fNotify->Notify();
6275  }
6276  }
6277  }
6278 
6279  if ((fReadEntry >= fEntries) && !friendHasEntry) {
6280  fReadEntry = -1;
6281  return -2;
6282  }
6283  return fReadEntry;
6284 }
6285 
6286 ////////////////////////////////////////////////////////////////////////////////
6287 /// Load entry on behalf of our master tree, we may use an index.
6288 ///
6289 /// Called by LoadTree() when the masterTree looks for the entry
6290 /// number in a friend tree (us) corresponding to the passed entry
6291 /// number in the masterTree.
6292 ///
6293 /// If we have no index, our entry number and the masterTree entry
6294 /// number are the same.
6295 ///
6296 /// If we *do* have an index, we must find the (major, minor) value pair
6297 /// in masterTree to locate our corresponding entry.
6298 ///
6299 
6300 Long64_t TTree::LoadTreeFriend(Long64_t entry, TTree* masterTree)
6302  if (!fTreeIndex) {
6303  return LoadTree(entry);
6304  }
6305  return LoadTree(fTreeIndex->GetEntryNumberFriend(masterTree));
6306 }
6307 
6308 ////////////////////////////////////////////////////////////////////////////////
6309 /// Generate a skeleton analysis class for this tree.
6310 ///
6311 /// The following files are produced: classname.h and classname.C.
6312 /// If classname is 0, classname will be called "nameoftree".
6313 ///
6314 /// The generated code in classname.h includes the following:
6315 ///
6316 /// - Identification of the original tree and the input file name.
6317 /// - Definition of an analysis class (data members and member functions).
6318 /// - The following member functions:
6319 /// - constructor (by default opening the tree file),
6320 /// - GetEntry(Long64_t entry),
6321 /// - Init(TTree* tree) to initialize a new TTree,
6322 /// - Show(Long64_t entry) to read and dump entry.
6323 ///
6324 /// The generated code in classname.C includes only the main
6325 /// analysis function Loop.
6326 ///
6327 /// To use this function:
6328 ///
6329 /// - Open your tree file (eg: TFile f("myfile.root");)
6330 /// - T->MakeClass("MyClass");
6331 ///
6332 /// where T is the name of the TTree in file myfile.root,
6333 /// and MyClass.h, MyClass.C the name of the files created by this function.
6334 /// In a ROOT session, you can do:
6335 /// ~~~ {.cpp}
6336 /// root > .L MyClass.C
6337 /// root > MyClass* t = new MyClass;
6338 /// root > t->GetEntry(12); // Fill data members of t with entry number 12.
6339 /// root > t->Show(); // Show values of entry 12.
6340 /// root > t->Show(16); // Read and show values of entry 16.
6341 /// root > t->Loop(); // Loop on all entries.
6342 /// ~~~
6343 /// NOTE: Do not use the code generated for a single TTree which is part
6344 /// of a TChain to process that entire TChain. The maximum dimensions
6345 /// calculated for arrays on the basis of a single TTree from the TChain
6346 /// might be (will be!) too small when processing all of the TTrees in
6347 /// the TChain. You must use myChain.MakeClass() to generate the code,
6348 /// not myTree.MakeClass(...).
6349 
6350 Int_t TTree::MakeClass(const char* classname, Option_t* option)
6352  GetPlayer();
6353  if (!fPlayer) {
6354  return 0;
6355  }
6356  return fPlayer->MakeClass(classname, option);
6357 }
6358 
6359 ////////////////////////////////////////////////////////////////////////////////
6360 /// Generate a skeleton function for this tree.
6361 ///
6362 /// The function code is written on filename.
6363 /// If filename is 0, filename will be called nameoftree.C
6364 ///
6365 /// The generated code includes the following:
6366 /// - Identification of the original Tree and Input file name,
6367 /// - Opening the Tree file,
6368 /// - Declaration of Tree variables,
6369 /// - Setting of branches addresses,
6370 /// - A skeleton for the entry loop.
6371 ///
6372 /// To use this function:
6373 ///
6374 /// - Open your Tree file (eg: TFile f("myfile.root");)
6375 /// - T->MakeCode("MyAnalysis.C");
6376 ///
6377 /// where T is the name of the TTree in file myfile.root
6378 /// and MyAnalysis.C the name of the file created by this function.
6379 ///
6380 /// NOTE: Since the implementation of this function, a new and better
6381 /// function TTree::MakeClass() has been developed.
6382 
6383 Int_t TTree::MakeCode(const char* filename)
6385  Warning("MakeCode", "MakeCode is obsolete. Use MakeClass or MakeSelector instead");
6386 
6387  GetPlayer();
6388  if (!fPlayer) return 0;
6389  return fPlayer->MakeCode(filename);
6390 }
6391 
6392 ////////////////////////////////////////////////////////////////////////////////
6393 /// Generate a skeleton analysis class for this Tree using TBranchProxy.
6394 ///
6395 /// TBranchProxy is the base of a class hierarchy implementing an
6396 /// indirect access to the content of the branches of a TTree.
6397 ///
6398 /// "proxyClassname" is expected to be of the form:
6399 /// ~~~ {.cpp}
6400 /// [path/]fileprefix
6401 /// ~~~
6402 /// The skeleton will then be generated in the file:
6403 /// ~~~ {.cpp}
6404 /// fileprefix.h
6405 /// ~~~
6406 /// located in the current directory or in 'path/' if it is specified.
6407 /// The class generated will be named 'fileprefix'
6408 ///
6409 /// "macrofilename" and optionally "cutfilename" are expected to point
6410 /// to source files which will be included by the generated skeleton.
6411 /// Method of the same name as the file(minus the extension and path)
6412 /// will be called by the generated skeleton's Process method as follow:
6413 /// ~~~ {.cpp}
6414 /// [if (cutfilename())] htemp->Fill(macrofilename());
6415 /// ~~~
6416 /// "option" can be used select some of the optional features during
6417 /// the code generation. The possible options are:
6418 ///
6419 /// - nohist : indicates that the generated ProcessFill should not fill the histogram.
6420 ///
6421 /// 'maxUnrolling' controls how deep in the class hierarchy does the
6422 /// system 'unroll' classes that are not split. Unrolling a class
6423 /// allows direct access to its data members (this emulates the behavior
6424 /// of TTreeFormula).
6425 ///
6426 /// The main features of this skeleton are:
6427 ///
6428 /// * on-demand loading of branches
6429 /// * ability to use the 'branchname' as if it was a data member
6430 /// * protection against array out-of-bounds errors
6431 /// * ability to use the branch data as an object (when the user code is available)
6432 ///
6433 /// For example with Event.root, if
6434 /// ~~~ {.cpp}
6435 /// Double_t somePx = fTracks.fPx[2];
6436 /// ~~~
6437 /// is executed by one of the method of the skeleton,
6438 /// somePx will updated with the current value of fPx of the 3rd track.
6439 ///
6440 /// Both macrofilename and the optional cutfilename are expected to be
6441 /// the name of source files which contain at least a free standing
6442 /// function with the signature:
6443 /// ~~~ {.cpp}
6444 /// x_t macrofilename(); // i.e function with the same name as the file
6445 /// ~~~
6446 /// and
6447 /// ~~~ {.cpp}
6448 /// y_t cutfilename(); // i.e function with the same name as the file
6449 /// ~~~
6450 /// x_t and y_t needs to be types that can convert respectively to a double
6451 /// and a bool (because the skeleton uses:
6452 ///
6453 /// if (cutfilename()) htemp->Fill(macrofilename());
6454 ///
6455 /// These two functions are run in a context such that the branch names are
6456 /// available as local variables of the correct (read-only) type.
6457 ///
6458 /// Note that if you use the same 'variable' twice, it is more efficient
6459 /// to 'cache' the value. For example:
6460 /// ~~~ {.cpp}
6461 /// Int_t n = fEventNumber; // Read fEventNumber
6462 /// if (n<10 || n>10) { ... }
6463 /// ~~~
6464 /// is more efficient than
6465 /// ~~~ {.cpp}
6466 /// if (fEventNumber<10 || fEventNumber>10)
6467 /// ~~~
6468 /// Also, optionally, the generated selector will also call methods named
6469 /// macrofilename_methodname in each of 6 main selector methods if the method
6470 /// macrofilename_methodname exist (Where macrofilename is stripped of its
6471 /// extension).
6472 ///
6473 /// Concretely, with the script named h1analysisProxy.C,
6474 ///
6475 /// - The method calls the method (if it exist)
6476 /// - Begin -> void h1analysisProxy_Begin(TTree*);
6477 /// - SlaveBegin -> void h1analysisProxy_SlaveBegin(TTree*);
6478 /// - Notify -> Bool_t h1analysisProxy_Notify();
6479 /// - Process -> Bool_t h1analysisProxy_Process(Long64_t);
6480 /// - SlaveTerminate -> void h1analysisProxy_SlaveTerminate();
6481 /// - Terminate -> void h1analysisProxy_Terminate();
6482 ///
6483 /// If a file name macrofilename.h (or .hh, .hpp, .hxx, .hPP, .hXX) exist
6484 /// it is included before the declaration of the proxy class. This can
6485 /// be used in particular to insure that the include files needed by
6486 /// the macro file are properly loaded.
6487 ///
6488 /// The default histogram is accessible via the variable named 'htemp'.
6489 ///
6490 /// If the library of the classes describing the data in the branch is
6491 /// loaded, the skeleton will add the needed `include` statements and
6492 /// give the ability to access the object stored in the branches.
6493 ///
6494 /// To draw px using the file hsimple.root (generated by the
6495 /// hsimple.C tutorial), we need a file named hsimple.cxx:
6496 /// ~~~ {.cpp}
6497 /// double hsimple() {
6498 /// return px;
6499 /// }
6500 /// ~~~
6501 /// MakeProxy can then be used indirectly via the TTree::Draw interface
6502 /// as follow:
6503 /// ~~~ {.cpp}
6504 /// new TFile("hsimple.root")
6505 /// ntuple->Draw("hsimple.cxx");
6506 /// ~~~
6507 /// A more complete example is available in the tutorials directory:
6508 /// h1analysisProxy.cxx , h1analysProxy.h and h1analysisProxyCut.C
6509 /// which reimplement the selector found in h1analysis.C
6510 
6511 Int_t TTree::MakeProxy(const char* proxyClassname, const char* macrofilename, const char* cutfilename, const char* option, Int_t maxUnrolling)
6513  GetPlayer();
6514  if (!fPlayer) return 0;
6515  return fPlayer->MakeProxy(proxyClassname,macrofilename,cutfilename,option,maxUnrolling);
6516 }
6517 
6518 ////////////////////////////////////////////////////////////////////////////////
6519 /// Generate skeleton selector class for this tree.
6520 ///
6521 /// The following files are produced: selector.h and selector.C.
6522 /// If selector is 0, the selector will be called "nameoftree".
6523 /// The option can be used to specify the branches that will have a data member.
6524 /// - If option is "=legacy", a pre-ROOT6 selector will be generated (data
6525 /// members and branch pointers instead of TTreeReaders).
6526 /// - If option is empty, readers will be generated for each leaf.
6527 /// - If option is "@", readers will be generated for the topmost branches.
6528 /// - Individual branches can also be picked by their name:
6529 /// - "X" generates readers for leaves of X.
6530 /// - "@X" generates a reader for X as a whole.
6531 /// - "@X;Y" generates a reader for X as a whole and also readers for the
6532 /// leaves of Y.
6533 /// - For further examples see the figure below.
6534 ///
6535 /// \image html ttree_makeselector_option_examples.png
6536 ///
6537 /// The generated code in selector.h includes the following:
6538 /// - Identification of the original Tree and Input file name
6539 /// - Definition of selector class (data and functions)
6540 /// - The following class functions:
6541 /// - constructor and destructor
6542 /// - void Begin(TTree *tree)
6543 /// - void SlaveBegin(TTree *tree)
6544 /// - void Init(TTree *tree)
6545 /// - Bool_t Notify()
6546 /// - Bool_t Process(Long64_t entry)
6547 /// - void Terminate()
6548 /// - void SlaveTerminate()
6549 ///
6550 /// The class selector derives from TSelector.
6551 /// The generated code in selector.C includes empty functions defined above.
6552 ///
6553 /// To use this function:
6554 ///
6555 /// - connect your Tree file (eg: `TFile f("myfile.root");`)
6556 /// - `T->MakeSelector("myselect");`
6557 ///
6558 /// where T is the name of the Tree in file myfile.root
6559 /// and myselect.h, myselect.C the name of the files created by this function.
6560 /// In a ROOT session, you can do:
6561 /// ~~~ {.cpp}
6562 /// root > T->Process("myselect.C")
6563 /// ~~~
6564 
6565 Int_t TTree::MakeSelector(const char* selector, Option_t* option)
6567  TString opt(option);
6568  if(opt.EqualTo("=legacy", TString::ECaseCompare::kIgnoreCase)) {
6569  return MakeClass(selector, "selector");
6570  } else {
6571  GetPlayer();
6572  if (!fPlayer) return 0;
6573  return fPlayer->MakeReader(selector, option);
6574  }
6575 }
6576 
6577 ////////////////////////////////////////////////////////////////////////////////
6578 /// Check if adding nbytes to memory we are still below MaxVirtualsize.
6579 
6582  if ((fTotalBuffers + nbytes) < fMaxVirtualSize) {
6583  return kFALSE;
6584  }
6585  return kTRUE;
6586 }
6587 
6588 ////////////////////////////////////////////////////////////////////////////////
6589 /// Static function merging the trees in the TList into a new tree.
6590 ///
6591 /// Trees in the list can be memory or disk-resident trees.
6592 /// The new tree is created in the current directory (memory if gROOT).
6593 
6594 TTree* TTree::MergeTrees(TList* li, Option_t* options)
6596  if (!li) return 0;
6597  TIter next(li);
6598  TTree *newtree = 0;
6599  TObject *obj;
6600 
6601  while ((obj=next())) {
6602  if (!obj->InheritsFrom(TTree::Class())) continue;
6603  TTree *tree = (TTree*)obj;
6604  Long64_t nentries = tree->GetEntries();
6605  if (nentries == 0) continue;
6606  if (!newtree) {
6607  newtree = (TTree*)tree->CloneTree();
6608  if (!newtree) continue;
6609 
6610  // Once the cloning is done, separate the trees,
6611  // to avoid as many side-effects as possible
6612  // The list of clones is guaranteed to exist since we
6613  // just cloned the tree.
6614  tree->GetListOfClones()->Remove(newtree);
6615  tree->ResetBranchAddresses();
6616  newtree->ResetBranchAddresses();
6617  continue;
6618  }
6619 
6620  newtree->CopyAddresses(tree);
6621 
6622  newtree->CopyEntries(tree,-1,options);
6623 
6624  tree->ResetBranchAddresses(); // Disconnect from new tree.
6625  }
6626  if (newtree && newtree->GetTreeIndex()) {
6627  newtree->GetTreeIndex()->Append(0,kFALSE); // Force the sorting
6628  }
6629  return newtree;
6630 }
6631 
6632 ////////////////////////////////////////////////////////////////////////////////
6633 /// Merge the trees in the TList into this tree.
6634 ///
6635 /// Returns the total number of entries in the merged tree.
6636 
6639  if (!li) return 0;
6640  Long64_t storeAutoSave = fAutoSave;
6641  // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6642  // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6643  // Also since this is part of a merging operation, the output file is not as precious as in
6644  // the general case since the input file should still be around.
6645  fAutoSave = 0;
6646  TIter next(li);
6647  TTree *tree;
6648  while ((tree = (TTree*)next())) {
6649  if (tree==this) continue;
6650  if (!tree->InheritsFrom(TTree::Class())) {
6651  Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6652  fAutoSave = storeAutoSave;
6653  return -1;
6654  }
6655 
6656  Long64_t nentries = tree->GetEntries();
6657  if (nentries == 0) continue;
6658 
6660 
6661  CopyEntries(tree,-1,options);
6662 
6663  tree->ResetBranchAddresses();
6664  }
6665  fAutoSave = storeAutoSave;
6666  return GetEntries();
6667 }
6668 
6669 ////////////////////////////////////////////////////////////////////////////////
6670 /// Merge the trees in the TList into this tree.
6671 /// If info->fIsFirst is true, first we clone this TTree info the directory
6672 /// info->fOutputDirectory and then overlay the new TTree information onto
6673 /// this TTree object (so that this TTree object is now the appropriate to
6674 /// use for further merging).
6675 ///
6676 /// Returns the total number of entries in the merged tree.
6677 
6680  const char *options = info ? info->fOptions.Data() : "";
6681  if (info && info->fIsFirst && info->fOutputDirectory && info->fOutputDirectory->GetFile() != GetCurrentFile()) {
6683  TIOFeatures saved_features = fIOFeatures;
6684  if (info->fIOFeatures) {
6685  fIOFeatures = *(info->fIOFeatures);
6686  }
6687  TTree *newtree = CloneTree(-1, options);
6688  fIOFeatures = saved_features;
6689  if (newtree) {
6690  newtree->Write();
6691  delete newtree;
6692  }
6693  // Make sure things are really written out to disk before attempting any reading.
6694  info->fOutputDirectory->GetFile()->Flush();
6695  info->fOutputDirectory->ReadTObject(this,this->GetName());
6696  }
6697  if (!li) return 0;
6698  Long64_t storeAutoSave = fAutoSave;
6699  // Disable the autosave as the TFileMerge keeps a list of key and deleting the underlying
6700  // key would invalidate its iteration (or require costly measure to not use the deleted keys).
6701  // Also since this is part of a merging operation, the output file is not as precious as in
6702  // the general case since the input file should still be around.
6703  fAutoSave = 0;
6704  TIter next(li);
6705  TTree *tree;
6706  while ((tree = (TTree*)next())) {
6707  if (tree==this) continue;
6708  if (!tree->InheritsFrom(TTree::Class())) {
6709  Error("Add","Attempt to add object of class: %s to a %s", tree->ClassName(), ClassName());
6710  fAutoSave = storeAutoSave;
6711  return -1;
6712  }
6713  // Copy MakeClass status.
6714  tree->SetMakeClass(fMakeClass);
6715 
6716  // Copy branch addresses.
6718 
6719  CopyEntries(tree,-1,options);
6720 
6721  tree->ResetBranchAddresses();
6722  }
6723  fAutoSave = storeAutoSave;
6724  return GetEntries();
6725 }
6726 
6727 ////////////////////////////////////////////////////////////////////////////////
6728 /// Move a cache from a file to the current file in dir.
6729 /// if src is null no operation is done, if dir is null or there is no
6730 /// current file the cache is deleted.
6731 
6732 void TTree::MoveReadCache(TFile *src, TDirectory *dir)
6734  if (!src) return;
6735  TFile *dst = (dir && dir != gROOT) ? dir->GetFile() : 0;
6736  if (src == dst) return;
6737 
6738  TTreeCache *pf = GetReadCache(src);
6739  if (dst) {
6740  src->SetCacheRead(0,this);
6741  dst->SetCacheRead(pf, this);
6742  } else {
6743  if (pf) {
6744  pf->WaitFinishPrefetch();
6745  }
6746  src->SetCacheRead(0,this);
6747  delete pf;
6748  }
6749 }
6750 
6751 ////////////////////////////////////////////////////////////////////////////////
6752 /// Function called when loading a new class library.
6753 
6756  TIter next(GetListOfLeaves());
6757  TLeaf* leaf = 0;
6758  while ((leaf = (TLeaf*) next())) {
6759  leaf->Notify();
6760  leaf->GetBranch()->Notify();
6761  }
6762  return kTRUE;
6763 }
6764 
6765 ////////////////////////////////////////////////////////////////////////////////
6766 /// This function may be called after having filled some entries in a Tree.
6767 /// Using the information in the existing branch buffers, it will reassign
6768 /// new branch buffer sizes to optimize time and memory.
6769 ///
6770 /// The function computes the best values for branch buffer sizes such that
6771 /// the total buffer sizes is less than maxMemory and nearby entries written
6772 /// at the same time.
6773 /// In case the branch compression factor for the data written so far is less
6774 /// than compMin, the compression is disabled.
6775 ///
6776 /// if option ="d" an analysis report is printed.
6777 
6778 void TTree::OptimizeBaskets(ULong64_t maxMemory, Float_t minComp, Option_t *option)
6780  //Flush existing baskets if the file is writable
6781  if (this->GetDirectory()->IsWritable()) this->FlushBaskets();
6782 
6783  TString opt( option );
6784  opt.ToLower();
6785  Bool_t pDebug = opt.Contains("d");
6786  TObjArray *leaves = this->GetListOfLeaves();
6787  Int_t nleaves = leaves->GetEntries();
6788  Double_t treeSize = (Double_t)this->GetTotBytes();
6789 
6790  if (nleaves == 0 || treeSize == 0) {
6791  // We're being called too early, we really have nothing to do ...
6792  return;
6793  }
6794  Double_t aveSize = treeSize/nleaves;
6795  UInt_t bmin = 512;
6796  UInt_t bmax = 256000;
6797  Double_t memFactor = 1;
6798  Int_t i, oldMemsize,newMemsize,oldBaskets,newBaskets;
6799  i = oldMemsize = newMemsize = oldBaskets = newBaskets = 0;
6800 
6801  //we make two passes
6802  //one pass to compute the relative branch buffer sizes
6803  //a second pass to compute the absolute values
6804  for (Int_t pass =0;pass<2;pass++) {
6805  oldMemsize = 0; //to count size of baskets in memory with old buffer size
6806  newMemsize = 0; //to count size of baskets in memory with new buffer size
6807  oldBaskets = 0; //to count number of baskets with old buffer size
6808  newBaskets = 0; //to count number of baskets with new buffer size
6809  for (i=0;i<nleaves;i++) {
6810  TLeaf *leaf = (TLeaf*)leaves->At(i);
6811  TBranch *branch = leaf->GetBranch();
6812  Double_t totBytes = (Double_t)branch->GetTotBytes();
6813  Double_t idealFactor = totBytes/aveSize;
6814  UInt_t sizeOfOneEntry;
6815  if (branch->GetEntries() == 0) {
6816  // There is no data, so let's make a guess ...
6817  sizeOfOneEntry = aveSize;
6818  } else {
6819  sizeOfOneEntry = 1+(UInt_t)(totBytes / (Double_t)branch->GetEntries());
6820  }
6821  Int_t oldBsize = branch->GetBasketSize();
6822  oldMemsize += oldBsize;
6823  oldBaskets += 1+Int_t(totBytes/oldBsize);
6824  Int_t nb = branch->GetListOfBranches()->GetEntries();
6825  if (nb > 0) {
6826  newBaskets += 1+Int_t(totBytes/oldBsize);
6827  continue;
6828  }
6829  Double_t bsize = oldBsize*idealFactor*memFactor; //bsize can be very large !
6830  if (bsize < 0) bsize = bmax;
6831  if (bsize > bmax) bsize = bmax;
6832  UInt_t newBsize = UInt_t(bsize);
6833  if (pass) { // only on the second pass so that it doesn't interfere with scaling
6834  newBsize = newBsize + (branch->GetEntries() * sizeof(Int_t) * 2); // make room for meta data
6835  // We used ATLAS fully-split xAOD for testing, which is a rather unbalanced TTree, 10K branches,
6836  // with 8K having baskets smaller than 512 bytes. To achieve good I/O performance ATLAS uses auto-flush 100,
6837  // resulting in the smallest baskets being ~300-400 bytes, so this change increases their memory by about 8k*150B =~ 1MB,
6838  // at the same time it significantly reduces the number of total baskets because it ensures that all 100 entries can be
6839  // stored in a single basket (the old optimization tended to make baskets too small). In a toy example with fixed sized
6840  // structures we found a factor of 2 fewer baskets needed in the new scheme.
6841  // rounds up, increases basket size to ensure all entries fit into single basket as intended
6842  newBsize = newBsize - newBsize%512 + 512;
6843  }
6844  if (newBsize < sizeOfOneEntry) newBsize = sizeOfOneEntry;
6845  if (newBsize < bmin) newBsize = bmin;
6846  if (newBsize > 10000000) newBsize = bmax;
6847  if (pass) {
6848  if (pDebug) Info("OptimizeBaskets", "Changing buffer size from %6d to %6d bytes for %s\n",oldBsize,newBsize,branch->GetName());
6849  branch->SetBasketSize(newBsize);
6850  }
6851  newMemsize += newBsize;
6852  // For this number to be somewhat accurate when newBsize is 'low'
6853  // we do not include any space for meta data in the requested size (newBsize) even-though SetBasketSize will
6854  // not let it be lower than 100+TBranch::fEntryOffsetLen.
6855  newBaskets += 1+Int_t(totBytes/newBsize);
6856  if (pass == 0) continue;
6857  //Reset the compression level in case the compression factor is small
6858  Double_t comp = 1;
6859  if (branch->GetZipBytes() > 0) comp = totBytes/Double_t(branch->GetZipBytes());
6860  if (comp > 1 && comp < minComp) {
6861  if (pDebug) Info("OptimizeBaskets", "Disabling compression for branch : %s\n",branch->GetName());
6862  branch->SetCompressionSettings(0);
6863  }
6864  }
6865  // coverity[divide_by_zero] newMemsize can not be zero as there is at least one leaf
6866  memFactor = Double_t(maxMemory)/Double_t(newMemsize);
6867  if (memFactor > 100) memFactor = 100;
6868  Double_t bmin_new = bmin*memFactor;
6869  Double_t bmax_new = bmax*memFactor;
6870  static const UInt_t hardmax = 1*1024*1024*1024; // Really, really never give more than 1Gb to a single buffer.
6871 
6872  // Really, really never go lower than 8 bytes (we use this number
6873  // so that the calculation of the number of basket is consistent
6874  // but in fact SetBasketSize will not let the size go below
6875  // TBranch::fEntryOffsetLen + (100 + strlen(branch->GetName())
6876  // (The 2nd part being a slight over estimate of the key length.
6877  static const UInt_t hardmin = 8;
6878  bmin = (bmin_new > hardmax) ? hardmax : ( bmin_new < hardmin ? hardmin : (UInt_t)bmin_new );
6879  bmax = (bmax_new > hardmax) ? bmin : (UInt_t)bmax_new;
6880  }
6881  if (pDebug) {
6882  Info("OptimizeBaskets", "oldMemsize = %d, newMemsize = %d\n",oldMemsize, newMemsize);
6883  Info("OptimizeBaskets", "oldBaskets = %d, newBaskets = %d\n",oldBaskets, newBaskets);
6884  }
6885 }
6886 
6887 ////////////////////////////////////////////////////////////////////////////////
6888 /// Interface to the Principal Components Analysis class.
6889 ///
6890 /// Create an instance of TPrincipal
6891 ///
6892 /// Fill it with the selected variables
6893 ///
6894 /// - if option "n" is specified, the TPrincipal object is filled with
6895 /// normalized variables.
6896 /// - If option "p" is specified, compute the principal components
6897 /// - If option "p" and "d" print results of analysis
6898 /// - If option "p" and "h" generate standard histograms
6899 /// - If option "p" and "c" generate code of conversion functions
6900 /// - return a pointer to the TPrincipal object. It is the user responsibility
6901 /// - to delete this object.
6902 /// - The option default value is "np"
6903 ///
6904 /// see TTree::Draw for explanation of the other parameters.
6905 ///
6906 /// The created object is named "principal" and a reference to it
6907 /// is added to the list of specials Root objects.
6908 /// you can retrieve a pointer to the created object via:
6909 /// ~~~ {.cpp}
6910 /// TPrincipal *principal =
6911 /// (TPrincipal*)gROOT->GetListOfSpecials()->FindObject("principal");
6912 /// ~~~
6913 
6914 TPrincipal* TTree::Principal(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
6916  GetPlayer();
6917  if (fPlayer) {
6918  return fPlayer->Principal(varexp, selection, option, nentries, firstentry);
6919  }
6920  return 0;
6921 }
6922 
6923 ////////////////////////////////////////////////////////////////////////////////
6924 /// Print a summary of the tree contents.
6925 ///
6926 /// - If option contains "all" friend trees are also printed.
6927 /// - If option contains "toponly" only the top level branches are printed.
6928 /// - If option contains "clusters" information about the cluster of baskets is printed.
6929 ///
6930 /// Wildcarding can be used to print only a subset of the branches, e.g.,
6931 /// `T.Print("Elec*")` will print all branches with name starting with "Elec".
6932 
6933 void TTree::Print(Option_t* option) const
6935  // We already have been visited while recursively looking
6936  // through the friends tree, let's return.
6937  if (kPrint & fFriendLockStatus) {
6938  return;
6939  }
6940  Int_t s = 0;
6941  Int_t skey = 0;
6942  if (fDirectory) {
6943  TKey* key = fDirectory->GetKey(GetName());
6944  if (key) {
6945  skey = key->GetKeylen();
6946  s = key->GetNbytes();
6947  }
6948  }
6949  Long64_t total = skey;
6950  Long64_t zipBytes = GetZipBytes();
6951  if (zipBytes > 0) {
6952  total += GetTotBytes();
6953  }
6954  TBufferFile b(TBuffer::kWrite, 10000);
6955  TTree::Class()->WriteBuffer(b, (TTree*) this);
6956  total += b.Length();
6957  Long64_t file = zipBytes + s;
6958  Float_t cx = 1;
6959  if (zipBytes) {
6960  cx = (GetTotBytes() + 0.00001) / zipBytes;
6961  }
6962  Printf("******************************************************************************");
6963  Printf("*Tree :%-10s: %-54s *", GetName(), GetTitle());
6964  Printf("*Entries : %8lld : Total = %15lld bytes File Size = %10lld *", fEntries, total, file);
6965  Printf("* : : Tree compression factor = %6.2f *", cx);
6966  Printf("******************************************************************************");
6967 
6968  if (strncmp(option,"clusterRange",strlen("clusters"))==0) {
6969  Printf("%-16s %-16s %-16s %5s",
6970  "Cluster Range #", "Entry Start", "Last Entry", "Size");
6971  Int_t index= 0;
6972  Long64_t clusterRangeStart = 0;
6973  if (fNClusterRange) {
6974  for( ; index < fNClusterRange; ++index) {
6975  Printf("%-16d %-16lld %-16lld %5lld",
6976  index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
6977  clusterRangeStart = fClusterRangeEnd[index] + 1;
6978  }
6979  }
6980  Printf("%-16d %-16lld %-16lld %5lld",
6981  index, clusterRangeStart, fEntries - 1, fAutoFlush);
6982  return;
6983  }
6984 
6985  Int_t nl = const_cast<TTree*>(this)->GetListOfLeaves()->GetEntries();
6986  Int_t l;
6987  TBranch* br = 0;
6988  TLeaf* leaf = 0;
6989  if (strstr(option, "toponly")) {
6990  Long64_t *count = new Long64_t[nl];
6991  Int_t keep =0;
6992  for (l=0;l<nl;l++) {
6993  leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
6994  br = leaf->GetBranch();
6995  if (strchr(br->GetName(),'.')) {
6996  count[l] = -1;
6997  count[keep] += br->GetZipBytes();
6998  } else {
6999  keep = l;
7000  count[keep] = br->GetZipBytes();
7001  }
7002  }
7003  for (l=0;l<nl;l++) {
7004  if (count[l] < 0) continue;
7005  leaf = (TLeaf *)const_cast<TTree*>(this)->GetListOfLeaves()->At(l);
7006  br = leaf->GetBranch();
7007  Printf("branch: %-20s %9lld\n",br->GetName(),count[l]);
7008  }
7009  delete [] count;
7010  } else {
7011  TString reg = "*";
7012  if (strlen(option) && strchr(option,'*')) reg = option;
7013  TRegexp re(reg,kTRUE);
7014  TIter next(const_cast<TTree*>(this)->GetListOfBranches());
7016  while ((br= (TBranch*)next())) {
7017  TString st = br->GetName();
7018  st.ReplaceAll("/","_");
7019  if (st.Index(re) == kNPOS) continue;
7020  br->Print(option);
7021  }
7022  }
7023 
7024  //print TRefTable (if one)
7025  if (fBranchRef) fBranchRef->Print(option);
7026 
7027  //print friends if option "all"
7028  if (!fFriends || !strstr(option,"all")) return;
7029  TIter nextf(fFriends);
7030  TFriendLock lock(const_cast<TTree*>(this),kPrint);
7031  TFriendElement *fr;
7032  while ((fr = (TFriendElement*)nextf())) {
7033  TTree * t = fr->GetTree();
7034  if (t) t->Print(option);
7035  }
7036 }
7037 
7038 ////////////////////////////////////////////////////////////////////////////////
7039 /// Print statistics about the TreeCache for this tree.
7040 /// Like:
7041 /// ~~~ {.cpp}
7042 /// ******TreeCache statistics for file: cms2.root ******
7043 /// Reading 73921562 bytes in 716 transactions
7044 /// Average transaction = 103.242405 Kbytes
7045 /// Number of blocks in current cache: 202, total size : 6001193
7046 /// ~~~
7047 /// if option = "a" the list of blocks in the cache is printed
7048 
7049 void TTree::PrintCacheStats(Option_t* option) const
7051  TFile *f = GetCurrentFile();
7052  if (!f) return;
7053  TTreeCache *tc = (TTreeCache*)f->GetCacheRead(const_cast<TTree*>(this));
7054  if (tc) tc->Print(option);
7055 }
7056 
7057 ////////////////////////////////////////////////////////////////////////////////
7058 /// Process this tree executing the TSelector code in the specified filename.
7059 /// The return value is -1 in case of error and TSelector::GetStatus() in
7060 /// in case of success.
7061 ///
7062 /// The code in filename is loaded (interpreted or compiled, see below),
7063 /// filename must contain a valid class implementation derived from TSelector,
7064 /// where TSelector has the following member functions:
7065 ///
7066 /// - `Begin()`: called every time a loop on the tree starts,
7067 /// a convenient place to create your histograms.
7068 /// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7069 /// slave servers.
7070 /// - `Process()`: called for each event, in this function you decide what
7071 /// to read and fill your histograms.
7072 /// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7073 /// called only on the slave servers.
7074 /// - `Terminate()`: called at the end of the loop on the tree,
7075 /// a convenient place to draw/fit your histograms.
7076 ///
7077 /// If filename is of the form file.C, the file will be interpreted.
7078 ///
7079 /// If filename is of the form file.C++, the file file.C will be compiled
7080 /// and dynamically loaded.
7081 ///
7082 /// If filename is of the form file.C+, the file file.C will be compiled
7083 /// and dynamically loaded. At next call, if file.C is older than file.o
7084 /// and file.so, the file.C is not compiled, only file.so is loaded.
7085 ///
7086 /// ## NOTE1
7087 ///
7088 /// It may be more interesting to invoke directly the other Process function
7089 /// accepting a TSelector* as argument.eg
7090 /// ~~~ {.cpp}
7091 /// MySelector *selector = (MySelector*)TSelector::GetSelector(filename);
7092 /// selector->CallSomeFunction(..);
7093 /// mytree.Process(selector,..);
7094 /// ~~~
7095 /// ## NOTE2
7096 //
7097 /// One should not call this function twice with the same selector file
7098 /// in the same script. If this is required, proceed as indicated in NOTE1,
7099 /// by getting a pointer to the corresponding TSelector,eg
7100 ///
7101 /// ### workaround 1
7102 /// ~~~ {.cpp}
7103 /// void stubs1() {
7104 /// TSelector *selector = TSelector::GetSelector("h1test.C");
7105 /// TFile *f1 = new TFile("stubs_nood_le1.root");
7106 /// TTree *h1 = (TTree*)f1->Get("h1");
7107 /// h1->Process(selector);
7108 /// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7109 /// TTree *h2 = (TTree*)f2->Get("h1");
7110 /// h2->Process(selector);
7111 /// }
7112 /// ~~~
7113 /// or use ACLIC to compile the selector
7114 ///
7115 /// ### workaround 2
7116 /// ~~~ {.cpp}
7117 /// void stubs2() {
7118 /// TFile *f1 = new TFile("stubs_nood_le1.root");
7119 /// TTree *h1 = (TTree*)f1->Get("h1");
7120 /// h1->Process("h1test.C+");
7121 /// TFile *f2 = new TFile("stubs_nood_le1_coarse.root");
7122 /// TTree *h2 = (TTree*)f2->Get("h1");
7123 /// h2->Process("h1test.C+");
7124 /// }
7125 /// ~~~
7126 
7127 Long64_t TTree::Process(const char* filename, Option_t* option, Long64_t nentries, Long64_t firstentry)
7129  GetPlayer();
7130  if (fPlayer) {
7131  return fPlayer->Process(filename, option, nentries, firstentry);
7132  }
7133  return -1;
7134 }
7135 
7136 ////////////////////////////////////////////////////////////////////////////////
7137 /// Process this tree executing the code in the specified selector.
7138 /// The return value is -1 in case of error and TSelector::GetStatus() in
7139 /// in case of success.
7140 ///
7141 /// The TSelector class has the following member functions:
7142 ///
7143 /// - `Begin()`: called every time a loop on the tree starts,
7144 /// a convenient place to create your histograms.
7145 /// - `SlaveBegin()`: called after Begin(), when on PROOF called only on the
7146 /// slave servers.
7147 /// - `Process()`: called for each event, in this function you decide what
7148 /// to read and fill your histograms.
7149 /// - `SlaveTerminate`: called at the end of the loop on the tree, when on PROOF
7150 /// called only on the slave servers.
7151 /// - `Terminate()`: called at the end of the loop on the tree,
7152 /// a convenient place to draw/fit your histograms.
7153 ///
7154 /// If the Tree (Chain) has an associated EventList, the loop is on the nentries
7155 /// of the EventList, starting at firstentry, otherwise the loop is on the
7156 /// specified Tree entries.
7157 
7158 Long64_t TTree::Process(TSelector* selector, Option_t* option, Long64_t nentries, Long64_t firstentry)
7160  GetPlayer();
7161  if (fPlayer) {
7162  return fPlayer->Process(selector, option, nentries, firstentry);
7163  }
7164  return -1;
7165 }
7166 
7167 ////////////////////////////////////////////////////////////////////////////////
7168 /// Make a projection of a tree using selections.
7169 ///
7170 /// Depending on the value of varexp (described in Draw) a 1-D, 2-D, etc.,
7171 /// projection of the tree will be filled in histogram hname.
7172 /// Note that the dimension of hname must match with the dimension of varexp.
7173 ///
7174 
7175 Long64_t TTree::Project(const char* hname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7177  TString var;
7178  var.Form("%s>>%s", varexp, hname);
7179  TString opt("goff");
7180  if (option) {
7181  opt.Form("%sgoff", option);
7182  }
7183  Long64_t nsel = Draw(var, selection, opt, nentries, firstentry);
7184  return nsel;
7185 }
7186 
7187 ////////////////////////////////////////////////////////////////////////////////
7188 /// Loop over entries and return a TSQLResult object containing entries following selection.
7189 
7190 TSQLResult* TTree::Query(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7192  GetPlayer();
7193  if (fPlayer) {
7194  return fPlayer->Query(varexp, selection, option, nentries, firstentry);
7195  }
7196  return 0;
7197 }
7198 
7199 ////////////////////////////////////////////////////////////////////////////////
7200 /// Create or simply read branches from filename.
7201 ///
7202 /// if branchDescriptor = "" (default), it is assumed that the Tree descriptor
7203 /// is given in the first line of the file with a syntax like
7204 /// ~~~ {.cpp}
7205 /// A/D:Table[2]/F:Ntracks/I:astring/C
7206 /// ~~~
7207 /// otherwise branchDescriptor must be specified with the above syntax.
7208 ///
7209 /// - If the type of the first variable is not specified, it is assumed to be "/F"
7210 /// - If the type of any other variable is not specified, the type of the previous
7211 /// variable is assumed. eg
7212 /// - `x:y:z` (all variables are assumed of type "F"
7213 /// - `x/D:y:z` (all variables are of type "D"
7214 /// - `x:y/D:z` (x is type "F", y and z of type "D"
7215 ///
7216 /// delimiter allows for the use of another delimiter besides whitespace.
7217 /// This provides support for direct import of common data file formats
7218 /// like csv. If delimiter != ' ' and branchDescriptor == "", then the
7219 /// branch description is taken from the first line in the file, but
7220 /// delimiter is used for the branch names tokenization rather than ':'.
7221 /// Note however that if the values in the first line do not use the
7222 /// /[type] syntax, all variables are assumed to be of type "F".
7223 /// If the filename ends with extensions .csv or .CSV and a delimiter is
7224 /// not specified (besides ' '), the delimiter is automatically set to ','.
7225 ///
7226 /// Lines in the input file starting with "#" are ignored. Leading whitespace
7227 /// for each column data is skipped. Empty lines are skipped.
7228 ///
7229 /// A TBranch object is created for each variable in the expression.
7230 /// The total number of rows read from the file is returned.
7231 ///
7232 /// ## FILLING a TTree WITH MULTIPLE INPUT TEXT FILES
7233 ///
7234 /// To fill a TTree with multiple input text files, proceed as indicated above
7235 /// for the first input file and omit the second argument for subsequent calls
7236 /// ~~~ {.cpp}
7237 /// T.ReadFile("file1.dat","branch descriptor");
7238 /// T.ReadFile("file2.dat");
7239 /// ~~~
7240 
7241 Long64_t TTree::ReadFile(const char* filename, const char* branchDescriptor, char delimiter)
7243  std::ifstream in;
7244  in.open(filename);
7245  if (!in.good()) {
7246  Error("ReadFile","Cannot open file: %s",filename);
7247  return 0;
7248  }
7249  const char* ext = strrchr(filename, '.');
7250  if(ext != NULL && ((strcmp(ext, ".csv") == 0) || (strcmp(ext, ".CSV") == 0)) && delimiter == ' ') {
7251  delimiter = ',';
7252  }
7253  return ReadStream(in, branchDescriptor, delimiter);
7254 }
7255 
7256 ////////////////////////////////////////////////////////////////////////////////
7257 /// Determine which newline this file is using.
7258 /// Return '\\r' for Windows '\\r\\n' as that already terminates.
7259 
7260 char TTree::GetNewlineValue(std::istream &inputStream)
7262  Long_t inPos = inputStream.tellg();
7263  char newline = '\n';
7264  while(1) {
7265  char c = 0;
7266  inputStream.get(c);
7267  if(!inputStream.good()) {
7268  Error("ReadStream","Error reading stream: no newline found.");
7269  return 0;
7270  }
7271  if(c == newline) break;
7272  if(c == '\r') {
7273  newline = '\r';
7274  break;
7275  }
7276  }
7277  inputStream.clear();
7278  inputStream.seekg(inPos);
7279  return newline;
7280 }
7281 
7282 ////////////////////////////////////////////////////////////////////////////////
7283 /// Create or simply read branches from an input stream.
7284 ///
7285 /// See reference information for TTree::ReadFile
7286 
7287 Long64_t TTree::ReadStream(std::istream& inputStream, const char *branchDescriptor, char delimiter)
7289  char newline = 0;
7290  std::stringstream ss;
7291  std::istream *inTemp;
7292  Long_t inPos = inputStream.tellg();
7293  if (!inputStream.good()) {
7294  Error("ReadStream","Error reading stream");
7295  return 0;
7296  }
7297  if (inPos == -1) {
7298  ss << std::cin.rdbuf();
7299  newline = GetNewlineValue(ss);
7300  inTemp = &ss;
7301  } else {
7302  newline = GetNewlineValue(inputStream);
7303  inTemp = &inputStream;
7304  }
7305  std::istream& in = *inTemp;
7306  Long64_t nlines = 0;
7307 
7308  TBranch *branch = 0;
7309  Int_t nbranches = fBranches.GetEntries();
7310  if (nbranches == 0) {
7311  char *bdname = new char[4000];
7312  char *bd = new char[100000];
7313  Int_t nch = 0;
7314  if (branchDescriptor) nch = strlen(branchDescriptor);
7315  // branch Descriptor is null, read its definition from the first line in the file
7316  if (!nch) {
7317  do {
7318  in.getline(bd, 100000, newline);
7319  if (!in.good()) {
7320  delete [] bdname;
7321  delete [] bd;
7322  Error("ReadStream","Error reading stream");
7323  return 0;
7324  }
7325  char *cursor = bd;
7326  while( isspace(*cursor) && *cursor != '\n' && *cursor != '\0') {
7327  ++cursor;
7328  }
7329  if (*cursor != '#' && *cursor != '\n' && *cursor != '\0') {
7330  break;
7331  }
7332  } while (true);
7333  ++nlines;
7334  nch = strlen(bd);
7335  } else {
7336  strlcpy(bd,branchDescriptor,100000);
7337  }
7338 
7339  //parse the branch descriptor and create a branch for each element
7340  //separated by ":"
7341  void *address = &bd[90000];
7342  char *bdcur = bd;
7343  TString desc="", olddesc="F";
7344  char bdelim = ':';
7345  if(delimiter != ' ') {
7346  bdelim = delimiter;
7347  if (strchr(bdcur,bdelim)==0 && strchr(bdcur,':') != 0) {
7348  // revert to the default
7349  bdelim = ':';
7350  }
7351  }
7352  while (bdcur) {
7353  char *colon = strchr(bdcur,bdelim);
7354  if (colon) *colon = 0;
7355  strlcpy(bdname,bdcur,4000);
7356  char *slash = strchr(bdname,'/');
7357  if (slash) {
7358  *slash = 0;
7359  desc = bdcur;
7360  olddesc = slash+1;
7361  } else {
7362  desc.Form("%s/%s",bdname,olddesc.Data());
7363  }
7364  char *bracket = strchr(bdname,'[');
7365  if (bracket) {
7366  *bracket = 0;
7367  }
7368  branch = new TBranch(this,bdname,address,desc.Data(),32000);
7369  if (branch->IsZombie()) {
7370  delete branch;
7371  Warning("ReadStream","Illegal branch definition: %s",bdcur);
7372  } else {
7373  fBranches.Add(branch);
7374  branch->SetAddress(0);
7375  }
7376  if (!colon)break;
7377  bdcur = colon+1;
7378  }
7379  delete [] bdname;
7380  delete [] bd;
7381  }
7382 
7383  nbranches = fBranches.GetEntries();
7384 
7385  if (gDebug > 1) {
7386  Info("ReadStream", "Will use branches:");
7387  for (int i = 0 ; i < nbranches; ++i) {
7388  TBranch* br = (TBranch*) fBranches.At(i);
7389  Info("ReadStream", " %s: %s [%s]", br->GetName(),
7390  br->GetTitle(), br->GetListOfLeaves()->At(0)->IsA()->GetName());
7391  }
7392  if (gDebug > 3) {
7393  Info("ReadStream", "Dumping read tokens, format:");
7394  Info("ReadStream", "LLLLL:BBB:gfbe:GFBE:T");
7395  Info("ReadStream", " L: line number");
7396  Info("ReadStream", " B: branch number");
7397  Info("ReadStream", " gfbe: good / fail / bad / eof of token");
7398  Info("ReadStream", " GFBE: good / fail / bad / eof of file");
7399  Info("ReadStream", " T: Token being read");
7400  }
7401  }
7402 
7403  //loop on all lines in the file
7404  Long64_t nGoodLines = 0;
7405  std::string line;
7406  const char sDelimBuf[2] = { delimiter, 0 };
7407  const char* sDelim = sDelimBuf;
7408  if (delimiter == ' ') {
7409  // ' ' really means whitespace
7410  sDelim = "[ \t]";
7411  }
7412  while(in.good()) {
7413  if (newline == '\r' && in.peek() == '\n') {
7414  // Windows, skip '\n':
7415  in.get();
7416  }
7417  std::getline(in, line, newline);
7418  ++nlines;
7419 
7420  TString sLine(line);
7421  sLine = sLine.Strip(TString::kLeading); // skip leading whitespace
7422  if (sLine.IsNull()) {
7423  if (gDebug > 2) {
7424  Info("ReadStream", "Skipping empty line number %lld", nlines);
7425  }
7426  continue; // silently skip empty lines
7427  }
7428  if (sLine[0] == '#') {
7429  if (gDebug > 2) {
7430  Info("ReadStream", "Skipping comment line number %lld: '%s'",
7431  nlines, line.c_str());
7432  }
7433  continue;
7434  }
7435  if (gDebug > 2) {
7436  Info("ReadStream", "Parsing line number %lld: '%s'",
7437  nlines, line.c_str());
7438  }
7439 
7440  // Loop on branches and read the branch values into their buffer
7441  branch = 0;
7442  TString tok; // one column's data
7443  TString leafData; // leaf data, possibly multiple tokens for e.g. /I[2]
7444  std::stringstream sToken; // string stream feeding leafData into leaves
7445  Ssiz_t pos = 0;
7446  Int_t iBranch = 0;
7447  Bool_t goodLine = kTRUE; // whether the row can be filled into the tree
7448  Int_t remainingLeafLen = 0; // remaining columns for the current leaf
7449  while (goodLine && iBranch < nbranches
7450  && sLine.Tokenize(tok, pos, sDelim)) {
7451  tok = tok.Strip(TString::kLeading); // skip leading whitespace
7452  if (tok.IsNull() && delimiter == ' ') {
7453  // 1 2 should not be interpreted as 1,,,2 but 1, 2.
7454  // Thus continue until we have a non-empty token.
7455  continue;
7456  }
7457 
7458  if (!remainingLeafLen) {
7459  // next branch!
7460  branch = (TBranch*)fBranches.At(iBranch);
7461  }
7462  TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
7463  if (!remainingLeafLen) {
7464  remainingLeafLen = leaf->GetLen();
7465  if (leaf->GetMaximum() > 0) {
7466  // This is a dynamic leaf length, i.e. most likely a TLeafC's
7467  // string size. This still translates into one token:
7468  remainingLeafLen = 1;
7469  }
7470 
7471  leafData = tok;
7472  } else {
7473  // append token to laf data:
7474  leafData += " ";
7475  leafData += tok;
7476  }
7477  --remainingLeafLen;
7478  if (remainingLeafLen) {
7479  // need more columns for this branch:
7480  continue;
7481  }
7482  ++iBranch;
7483 
7484  // initialize stringstream with token
7485  sToken.clear();
7486  sToken.seekp(0, std::ios_base::beg);
7487  sToken.str(leafData.Data());
7488  sToken.seekg(0, std::ios_base::beg);
7489  leaf->ReadValue(sToken, 0 /* 0 = "all" */);
7490  if (gDebug > 3) {
7491  Info("ReadStream", "%5lld:%3d:%d%d%d%d:%d%d%d%d:%s",
7492  nlines, iBranch,
7493  (int)sToken.good(), (int)sToken.fail(),
7494  (int)sToken.bad(), (int)sToken.eof(),
7495  (int)in.good(), (int)in.fail(),
7496  (int)in.bad(), (int)in.eof(),
7497  sToken.str().c_str());
7498  }
7499 
7500  // Error handling
7501  if (sToken.bad()) {
7502  // How could that happen for a stringstream?
7503  Warning("ReadStream",
7504  "Buffer error while reading data for branch %s on line %lld",
7505  branch->GetName(), nlines);
7506  } else if (!sToken.eof()) {
7507  if (sToken.fail()) {
7508  Warning("ReadStream",
7509  "Couldn't read formatted data in \"%s\" for branch %s on line %lld; ignoring line",
7510  tok.Data(), branch->GetName(), nlines);
7511  goodLine = kFALSE;
7512  } else {
7513  std::string remainder;
7514  std::getline(sToken, remainder, newline);
7515  if (!remainder.empty()) {
7516  Warning("ReadStream",
7517  "Ignoring trailing \"%s\" while reading data for branch %s on line %lld",
7518  remainder.c_str(), branch->GetName(), nlines);
7519  }
7520  }
7521  }
7522  } // tokenizer loop
7523 
7524  if (iBranch < nbranches) {
7525  Warning("ReadStream",
7526  "Read too few columns (%d < %d) in line %lld; ignoring line",
7527  iBranch, nbranches, nlines);
7528  goodLine = kFALSE;
7529  } else if (pos != kNPOS) {
7530  sLine = sLine.Strip(TString::kTrailing);
7531  if (pos < sLine.Length()) {
7532  Warning("ReadStream",
7533  "Ignoring trailing \"%s\" while reading line %lld",
7534  sLine.Data() + pos - 1 /* also print delimiter */,
7535  nlines);
7536  }
7537  }
7538 
7539  //we are now ready to fill the tree
7540  if (goodLine) {
7541  Fill();
7542  ++nGoodLines;
7543  }
7544  }
7545 
7546  return nGoodLines;
7547 }
7548 
7549 ////////////////////////////////////////////////////////////////////////////////
7550 /// Make sure that obj (which is being deleted or will soon be) is no
7551 /// longer referenced by this TTree.
7552 
7555  if (obj == fEventList) {
7556  fEventList = 0;
7557  }
7558  if (obj == fEntryList) {
7559  fEntryList = 0;
7560  }
7561  if (fUserInfo) {
7562  fUserInfo->RecursiveRemove(obj);
7563  }
7564  if (fPlayer == obj) {
7565  fPlayer = 0;
7566  }
7567  if (fTreeIndex == obj) {
7568  fTreeIndex = 0;
7569  }
7570  if (fAliases) {
7571  fAliases->RecursiveRemove(obj);
7572  }
7573  if (fFriends) {
7574  fFriends->RecursiveRemove(obj);
7575  }
7576 }
7577 
7578 ////////////////////////////////////////////////////////////////////////////////
7579 /// Refresh contents of this tree and its branches from the current status on disk.
7580 ///
7581 /// One can call this function in case the tree file is being
7582 /// updated by another process.
7583 
7584 void TTree::Refresh()
7586  if (!fDirectory->GetFile()) {
7587  return;
7588  }
7589  fDirectory->ReadKeys();
7590  fDirectory->Remove(this);
7592  if (!tree) {
7593  return;
7594  }
7595  //copy info from tree header into this Tree
7596  fEntries = 0;
7597  fNClusterRange = 0;
7599 
7600  fAutoSave = tree->fAutoSave;
7601  fEntries = tree->fEntries;
7602  fTotBytes = tree->GetTotBytes();
7603  fZipBytes = tree->GetZipBytes();
7604  fSavedBytes = tree->fSavedBytes;
7605  fTotalBuffers = tree->fTotalBuffers.load();
7606 
7607  //loop on all branches and update them
7608  Int_t nleaves = fLeaves.GetEntriesFast();
7609  for (Int_t i = 0; i < nleaves; i++) {
7610  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7611  TBranch* branch = (TBranch*) leaf->GetBranch();
7612  branch->Refresh(tree->GetBranch(branch->GetName()));
7613  }
7615  fDirectory->Append(this);
7616  delete tree;
7617  tree = 0;
7618 }
7619 
7620 ////////////////////////////////////////////////////////////////////////////////
7621 /// Remove a friend from the list of friends.
7622 
7623 void TTree::RemoveFriend(TTree* oldFriend)
7625  // We already have been visited while recursively looking
7626  // through the friends tree, let return
7628  return;
7629  }
7630  if (!fFriends) {
7631  return;
7632  }
7633  TFriendLock lock(this, kRemoveFriend);
7634  TIter nextf(fFriends);
7635  TFriendElement* fe = 0;
7636  while ((fe = (TFriendElement*) nextf())) {
7637  TTree* friend_t = fe->GetTree();
7638  if (friend_t == oldFriend) {
7639  fFriends->Remove(fe);
7640  delete fe;
7641  fe = 0;
7642  }
7643  }
7644 }
7645 
7646 ////////////////////////////////////////////////////////////////////////////////
7647 /// Reset baskets, buffers and entries count in all branches and leaves.
7648 
7649 void TTree::Reset(Option_t* option)
7651  fNotify = 0;
7652  fEntries = 0;
7653  fNClusterRange = 0;
7654  fTotBytes = 0;
7655  fZipBytes = 0;
7656  fFlushedBytes = 0;
7657  fSavedBytes = 0;
7658  fTotalBuffers = 0;
7659  fChainOffset = 0;
7660  fReadEntry = -1;
7661 
7662  delete fTreeIndex;
7663  fTreeIndex = 0;
7664 
7666  for (Int_t i = 0; i < nb; ++i) {
7667  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7668  branch->Reset(option);
7669  }
7670 
7671  if (fBranchRef) {
7672  fBranchRef->Reset();
7673  }
7674 }
7675 
7676 ////////////////////////////////////////////////////////////////////////////////
7677 /// Resets the state of this TTree after a merge (keep the customization but
7678 /// forget the data).
7679 
7682  fEntries = 0;
7683  fNClusterRange = 0;
7684  fTotBytes = 0;
7685  fZipBytes = 0;
7686  fSavedBytes = 0;
7687  fFlushedBytes = 0;
7688  fTotalBuffers = 0;
7689  fChainOffset = 0;
7690  fReadEntry = -1;
7691 
7692  delete fTreeIndex;
7693  fTreeIndex = 0;
7694 
7696  for (Int_t i = 0; i < nb; ++i) {
7697  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
7698  branch->ResetAfterMerge(info);
7699  }
7700 
7701  if (fBranchRef) {
7702  fBranchRef->ResetAfterMerge(info);
7703  }
7704 }
7705 
7706 ////////////////////////////////////////////////////////////////////////////////
7707 /// Tell all of our branches to set their addresses to zero.
7708 ///
7709 /// Note: If any of our branches own any objects, they are deleted.
7710 
7713  if (br && br->GetTree()) {
7714  br->ResetAddress();
7715  }
7716 }
7717 
7718 ////////////////////////////////////////////////////////////////////////////////
7719 /// Tell all of our branches to drop their current objects and allocate new ones.
7720 
7724  Int_t nbranches = branches->GetEntriesFast();
7725  for (Int_t i = 0; i < nbranches; ++i) {
7726  TBranch* branch = (TBranch*) branches->UncheckedAt(i);
7727  branch->ResetAddress();
7728  }
7729 }
7730 
7731 ////////////////////////////////////////////////////////////////////////////////
7732 /// Loop over tree entries and print entries passing selection.
7733 ///
7734 /// - If varexp is 0 (or "") then print only first 8 columns.
7735 /// - If varexp = "*" print all columns.
7736 ///
7737 /// Otherwise a columns selection can be made using "var1:var2:var3".
7738 /// See TTreePlayer::Scan for more information
7739 
7740 Long64_t TTree::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
7742  GetPlayer();
7743  if (fPlayer) {
7744  return fPlayer->Scan(varexp, selection, option, nentries, firstentry);
7745  }
7746  return -1;
7747 }
7748 
7749 ////////////////////////////////////////////////////////////////////////////////
7750 /// Set a tree variable alias.
7751 ///
7752 /// Set an alias for an expression/formula based on the tree 'variables'.
7753 ///
7754 /// The content of 'aliasName' can be used in TTreeFormula (i.e. TTree::Draw,
7755 /// TTree::Scan, TTreeViewer) and will be evaluated as the content of
7756 /// 'aliasFormula'.
7757 ///
7758 /// If the content of 'aliasFormula' only contains symbol names, periods and
7759 /// array index specification (for example event.fTracks[3]), then
7760 /// the content of 'aliasName' can be used as the start of symbol.
7761 ///
7762 /// If the alias 'aliasName' already existed, it is replaced by the new
7763 /// value.
7764 ///
7765 /// When being used, the alias can be preceded by an eventual 'Friend Alias'
7766 /// (see TTree::GetFriendAlias)
7767 ///
7768 /// Return true if it was added properly.
7769 ///
7770 /// For example:
7771 /// ~~~ {.cpp}
7772 /// tree->SetAlias("x1","(tdc1[1]-tdc1[0])/49");
7773 /// tree->SetAlias("y1","(tdc1[3]-tdc1[2])/47");
7774 /// tree->SetAlias("x2","(tdc2[1]-tdc2[0])/49");
7775 /// tree->SetAlias("y2","(tdc2[3]-tdc2[2])/47");
7776 /// tree->Draw("y2-y1:x2-x1");
7777 ///
7778 /// tree->SetAlias("theGoodTrack","event.fTracks[3]");
7779 /// tree->Draw("theGoodTrack.fPx"); // same as "event.fTracks[3].fPx"
7780 /// ~~~
7781 
7782 Bool_t TTree::SetAlias(const char* aliasName, const char* aliasFormula)
7784  if (!aliasName || !aliasFormula) {
7785  return kFALSE;
7786  }
7787  if (!aliasName[0] || !aliasFormula[0]) {
7788  return kFALSE;
7789  }
7790  if (!fAliases) {
7791  fAliases = new TList;
7792  } else {
7793  TNamed* oldHolder = (TNamed*) fAliases->FindObject(aliasName);
7794  if (oldHolder) {
7795  oldHolder->SetTitle(aliasFormula);
7796  return kTRUE;
7797  }
7798  }
7799  TNamed* holder = new TNamed(aliasName, aliasFormula);
7800  fAliases->Add(holder);
7801  return kTRUE;
7802 }
7803 
7804 ////////////////////////////////////////////////////////////////////////////////
7805 /// This function may be called at the start of a program to change
7806 /// the default value for fAutoFlush.
7807 ///
7808 /// ### CASE 1 : autof > 0
7809 ///
7810 /// autof is the number of consecutive entries after which TTree::Fill will
7811 /// flush all branch buffers to disk.
7812 ///
7813 /// ### CASE 2 : autof < 0
7814 ///
7815 /// When filling the Tree the branch buffers will be flushed to disk when
7816 /// more than autof bytes have been written to the file. At the first FlushBaskets
7817 /// TTree::Fill will replace fAutoFlush by the current value of fEntries.
7818 ///
7819 /// Calling this function with autof<0 is interesting when it is hard to estimate
7820 /// the size of one entry. This value is also independent of the Tree.
7821 ///
7822 /// The Tree is initialized with fAutoFlush=-30000000, ie that, by default,
7823 /// the first AutoFlush will be done when 30 MBytes of data are written to the file.
7824 ///
7825 /// ### CASE 3 : autof = 0
7826 ///
7827 /// The AutoFlush mechanism is disabled.
7828 ///
7829 /// Flushing the buffers at regular intervals optimize the location of
7830 /// consecutive entries on the disk by creating clusters of baskets.
7831 ///
7832 /// A cluster of baskets is a set of baskets that contains all
7833 /// the data for a (consecutive) set of entries and that is stored
7834 /// consecutively on the disk. When reading all the branches, this
7835 /// is the minimum set of baskets that the TTreeCache will read.
7836 
7837 void TTree::SetAutoFlush(Long64_t autof /* = -30000000 */ )
7839  // Implementation note:
7840  //
7841  // A positive value of autoflush determines the size (in number of entries) of
7842  // a cluster of baskets.
7843  //
7844  // If the value of autoflush is changed over time (this happens in
7845  // particular when the TTree results from fast merging many trees),
7846  // we record the values of fAutoFlush in the data members:
7847  // fClusterRangeEnd and fClusterSize.
7848  // In the code we refer to a range of entries where the size of the
7849  // cluster of baskets is the same (i.e the value of AutoFlush was
7850  // constant) is called a ClusterRange.
7851  //
7852  // The 2 arrays (fClusterRangeEnd and fClusterSize) have fNClusterRange
7853  // active (used) values and have fMaxClusterRange allocated entries.
7854  //
7855  // fClusterRangeEnd contains the last entries number of a cluster range.
7856  // In particular this means that the 'next' cluster starts at fClusterRangeEnd[]+1
7857  // fClusterSize contains the size in number of entries of all the cluster
7858  // within the given range.
7859  // The last range (and the only one if fNClusterRange is zero) start at
7860  // fNClusterRange[fNClusterRange-1]+1 and ends at the end of the TTree. The
7861  // size of the cluster in this range is given by the value of fAutoFlush.
7862  //
7863  // For example printing the beginning and end of each the ranges can be done by:
7864  //
7865  // Printf("%-16s %-16s %-16s %5s",
7866  // "Cluster Range #", "Entry Start", "Last Entry", "Size");
7867  // Int_t index= 0;
7868  // Long64_t clusterRangeStart = 0;
7869  // if (fNClusterRange) {
7870  // for( ; index < fNClusterRange; ++index) {
7871  // Printf("%-16d %-16lld %-16lld %5lld",
7872  // index, clusterRangeStart, fClusterRangeEnd[index], fClusterSize[index]);
7873  // clusterRangeStart = fClusterRangeEnd[index] + 1;
7874  // }
7875  // }
7876  // Printf("%-16d %-16lld %-16lld %5lld",
7877  // index, prevEntry, fEntries - 1, fAutoFlush);
7878  //
7879 
7880  // Note: We store the entry number corresponding to the end of the cluster
7881  // rather than its start in order to avoid using the array if the cluster
7882  // size never varies (If there is only one value of AutoFlush for the whole TTree).
7883 
7884  if (fAutoFlush > 0 || autof > 0) {
7885  // The mechanism was already enabled, let's record the previous
7886  // cluster if needed.
7887  if (fFlushedBytes) {
7888  if ( (fNClusterRange+1) > fMaxClusterRange ) {
7889  if (fMaxClusterRange) {
7890  Int_t newsize = TMath::Max(10,Int_t(2*fMaxClusterRange));
7892  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7894  newsize*sizeof(Long64_t),fMaxClusterRange*sizeof(Long64_t));
7895  fMaxClusterRange = newsize;
7896  } else {
7897  fMaxClusterRange = 2;
7900  }
7901  }
7904  ++fNClusterRange;
7905  }
7906  }
7907  fAutoFlush = autof;
7908 }
7909 
7910 ////////////////////////////////////////////////////////////////////////////////
7911 /// This function may be called at the start of a program to change
7912 /// the default value for fAutoSave (and for SetAutoSave) is -300000000, ie 300 MBytes.
7913 /// When filling the Tree the branch buffers as well as the Tree header
7914 /// will be flushed to disk when the watermark is reached.
7915 /// If fAutoSave is positive the watermark is reached when a multiple of fAutoSave
7916 /// entries have been written.
7917 /// If fAutoSave is negative the watermark is reached when -fAutoSave bytes
7918 /// have been written to the file.
7919 /// In case of a program crash, it will be possible to recover the data in the Tree
7920 /// up to the last AutoSave point.
7921 
7922 void TTree::SetAutoSave(Long64_t autos)
7924  fAutoSave = autos;
7925 }
7926 
7927 ////////////////////////////////////////////////////////////////////////////////
7928 /// Set a branch's basket size.
7929 ///
7930 /// bname is the name of a branch.
7931 ///
7932 /// - if bname="*", apply to all branches.
7933 /// - if bname="xxx*", apply to all branches with name starting with xxx
7934 ///
7935 /// see TRegexp for wildcarding options
7936 /// buffsize = branc basket size
7937 
7938 void TTree::SetBasketSize(const char* bname, Int_t buffsize)
7940  Int_t nleaves = fLeaves.GetEntriesFast();
7941  TRegexp re(bname, kTRUE);
7942  Int_t nb = 0;
7943  for (Int_t i = 0; i < nleaves; i++) {
7944  TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(i);
7945  TBranch* branch = (TBranch*) leaf->GetBranch();
7946  TString s = branch->GetName();
7947  if (strcmp(bname, branch->GetName()) && (s.Index(re) == kNPOS)) {
7948  continue;
7949  }
7950  nb++;
7951  branch->SetBasketSize(buffsize);
7952  }
7953  if (!nb) {
7954  Error("SetBasketSize", "unknown branch -> '%s'", bname);
7955  }
7956 }
7957 
7958 ////////////////////////////////////////////////////////////////////////////////
7959 /// Change branch address, dealing with clone trees properly.
7960 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7961 ///
7962 /// Note: See the comments in TBranchElement::SetAddress() for the
7963 /// meaning of the addr parameter and the object ownership policy.
7964 
7965 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr)
7967  TBranch* branch = GetBranch(bname);
7968  if (!branch) {
7969  if (ptr) *ptr = 0;
7970  Error("SetBranchAddress", "unknown branch -> %s", bname);
7971  return kMissingBranch;
7972  }
7973  return SetBranchAddressImp(branch,addr,ptr);
7974 }
7975 
7976 ////////////////////////////////////////////////////////////////////////////////
7977 /// Verify the validity of the type of addr before calling SetBranchAddress.
7978 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7979 ///
7980 /// Note: See the comments in TBranchElement::SetAddress() for the
7981 /// meaning of the addr parameter and the object ownership policy.
7982 
7983 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
7985  return SetBranchAddress(bname, addr, 0, ptrClass, datatype, isptr);
7986 }
7987 
7988 ////////////////////////////////////////////////////////////////////////////////
7989 /// Verify the validity of the type of addr before calling SetBranchAddress.
7990 /// See TTree::CheckBranchAddressType for the semantic of the return value.
7991 ///
7992 /// Note: See the comments in TBranchElement::SetAddress() for the
7993 /// meaning of the addr parameter and the object ownership policy.
7994 
7995 Int_t TTree::SetBranchAddress(const char* bname, void* addr, TBranch** ptr, TClass* ptrClass, EDataType datatype, Bool_t isptr)
7997  TBranch* branch = GetBranch(bname);
7998  if (!branch) {
7999  if (ptr) *ptr = 0;
8000  Error("SetBranchAddress", "unknown branch -> %s", bname);
8001  return kMissingBranch;
8002  }
8003 
8004  Int_t res = CheckBranchAddressType(branch, ptrClass, datatype, isptr);
8005  // This will set the value of *ptr to branch.
8006  if (res >= 0) {
8007  // The check succeeded.
8008  SetBranchAddressImp(branch,addr,ptr);
8009  } else {
8010  if (ptr) *ptr = 0;
8011  }
8012  return res;
8013 }
8014 
8015 ////////////////////////////////////////////////////////////////////////////////
8016 /// Change branch address, dealing with clone trees properly.
8017 /// See TTree::CheckBranchAddressType for the semantic of the return value.
8018 ///
8019 /// Note: See the comments in TBranchElement::SetAddress() for the
8020 /// meaning of the addr parameter and the object ownership policy.
8021 
8022 Int_t TTree::SetBranchAddressImp(TBranch *branch, void* addr, TBranch** ptr)
8024  if (ptr) {
8025  *ptr = branch;
8026  }
8027  if (fClones) {
8028  void* oldAddr = branch->GetAddress();
8029  TIter next(fClones);
8030  TTree* clone = 0;
8031  const char *bname = branch->GetName();
8032  while ((clone = (TTree*) next())) {
8033  TBranch* cloneBr = clone->GetBranch(bname);
8034  if (cloneBr && (cloneBr->GetAddress() == oldAddr)) {
8035  cloneBr->SetAddress(addr);
8036  }
8037  }
8038  }
8039  branch->SetAddress(addr);
8040  return kVoidPtr;
8041 }
8042 
8043 ////////////////////////////////////////////////////////////////////////////////
8044 /// Set branch status to Process or DoNotProcess.
8045 ///
8046 /// When reading a Tree, by default, all branches are read.
8047 /// One can speed up considerably the analysis phase by activating
8048 /// only the branches that hold variables involved in a query.
8049 ///
8050 /// bname is the name of a branch.
8051 ///
8052 /// - if bname="*", apply to all branches.
8053 /// - if bname="xxx*", apply to all branches with name starting with xxx
8054 ///
8055 /// see TRegexp for wildcarding options
8056 ///
8057 /// - status = 1 branch will be processed
8058 /// - = 0 branch will not be processed
8059 ///
8060 /// Example:
8061 ///
8062 /// Assume a tree T with sub-branches a,b,c,d,e,f,g,etc..
8063 /// when doing T.GetEntry(i) all branches are read for entry i.
8064 /// to read only the branches c and e, one can do
8065 /// ~~~ {.cpp}
8066 /// T.SetBranchStatus("*",0); //disable all branches
8067 /// T.SetBranchStatus("c",1);
8068 /// T.setBranchStatus("e",1);
8069 /// T.GetEntry(i);
8070 /// ~~~
8071 /// bname is interpreted as a wildcarded TRegexp (see TRegexp::MakeWildcard).
8072 /// Thus, "a*b" or "a.*b" matches branches starting with "a" and ending with
8073 /// "b", but not any other branch with an "a" followed at some point by a
8074 /// "b". For this second behavior, use "*a*b*". Note that TRegExp does not
8075 /// support '|', and so you cannot select, e.g. track and shower branches
8076 /// with "track|shower".
8077 ///
8078 /// __WARNING! WARNING! WARNING!__
8079 ///
8080 /// SetBranchStatus is matching the branch based on match of the branch
8081 /// 'name' and not on the branch hierarchy! In order to be able to
8082 /// selectively enable a top level object that is 'split' you need to make
8083 /// sure the name of the top level branch is prefixed to the sub-branches'
8084 /// name (by adding a dot ('.') at the end of the Branch creation and use the
8085 /// corresponding bname.
8086 ///
8087 /// I.e If your Tree has been created in split mode with a parent branch "parent."
8088 /// (note the trailing dot).
8089 /// ~~~ {.cpp}
8090 /// T.SetBranchStatus("parent",1);
8091 /// ~~~
8092 /// will not activate the sub-branches of "parent". You should do:
8093 /// ~~~ {.cpp}
8094 /// T.SetBranchStatus("parent*",1);
8095 /// ~~~
8096 /// Without the trailing dot in the branch creation you have no choice but to
8097 /// call SetBranchStatus explicitly for each of the sub branches.
8098 ///
8099 /// An alternative to this function is to read directly and only
8100 /// the interesting branches. Example:
8101 /// ~~~ {.cpp}
8102 /// TBranch *brc = T.GetBranch("c");
8103 /// TBranch *bre = T.GetBranch("e");
8104 /// brc->GetEntry(i);
8105 /// bre->GetEntry(i);
8106 /// ~~~
8107 /// If found is not 0, the number of branch(es) found matching the regular
8108 /// expression is returned in *found AND the error message 'unknown branch'
8109 /// is suppressed.
8110 
8111 void TTree::SetBranchStatus(const char* bname, Bool_t status, UInt_t* found)
8113  // We already have been visited while recursively looking
8114  // through the friends tree, let return
8116  return;
8117  }
8118 
8119  TBranch *branch, *bcount, *bson;
8120  TLeaf *leaf, *leafcount;
8121 
8122  Int_t i,j;
8123  Int_t nleaves = fLeaves.GetEntriesFast();
8124  TRegexp re(bname,kTRUE);
8125  Int_t nb = 0;
8126 
8127  // first pass, loop on all branches
8128  // for leafcount branches activate/deactivate in function of status
8129  for (i=0;i<nleaves;i++) {
8130  leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8131  branch = (TBranch*)leaf->GetBranch();
8132  TString s = branch->GetName();
8133  if (strcmp(bname,"*")) { //Regexp gives wrong result for [] in name
8134  TString longname;
8135  longname.Form("%s.%s",GetName(),branch->GetName());
8136  if (strcmp(bname,branch->GetName())
8137  && longname != bname
8138  && s.Index(re) == kNPOS) continue;
8139  }
8140  nb++;
8141  if (status) branch->ResetBit(kDoNotProcess);
8142  else branch->SetBit(kDoNotProcess);
8143  leafcount = leaf->GetLeafCount();
8144  if (leafcount) {
8145  bcount = leafcount->GetBranch();
8146  if (status) bcount->ResetBit(kDoNotProcess);
8147  else bcount->SetBit(kDoNotProcess);
8148  }
8149  }
8150  if (nb==0 && strchr(bname,'*')==0) {
8151  branch = GetBranch(bname);
8152  if (branch) {
8153  if (status) branch->ResetBit(kDoNotProcess);
8154  else branch->SetBit(kDoNotProcess);
8155  ++nb;
8156  }
8157  }
8158 
8159  //search in list of friends
8160  UInt_t foundInFriend = 0;
8161  if (fFriends) {
8162  TFriendLock lock(this,kSetBranchStatus);
8163  TIter nextf(fFriends);
8164  TFriendElement *fe;
8165  TString name;
8166  while ((fe = (TFriendElement*)nextf())) {
8167  TTree *t = fe->GetTree();
8168  if (t==0) continue;
8169 
8170  // If the alias is present replace it with the real name.
8171  char *subbranch = (char*)strstr(bname,fe->GetName());
8172  if (subbranch!=bname) subbranch = 0;
8173  if (subbranch) {
8174  subbranch += strlen(fe->GetName());
8175  if ( *subbranch != '.' ) subbranch = 0;
8176  else subbranch ++;
8177  }
8178  if (subbranch) {
8179  name.Form("%s.%s",t->GetName(),subbranch);
8180  } else {
8181  name = bname;
8182  }
8183  t->SetBranchStatus(name,status, &foundInFriend);
8184  }
8185  }
8186  if (!nb && !foundInFriend) {
8187  if (found==0) {
8188  if (status) {
8189  if (strchr(bname,'*') != 0)
8190  Error("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8191  else
8192  Error("SetBranchStatus", "unknown branch -> %s", bname);
8193  } else {
8194  if (strchr(bname,'*') != 0)
8195  Warning("SetBranchStatus", "No branch name is matching wildcard -> %s", bname);
8196  else
8197  Warning("SetBranchStatus", "unknown branch -> %s", bname);
8198  }
8199  }
8200  return;
8201  }
8202  if (found) *found = nb + foundInFriend;
8203 
8204  // second pass, loop again on all branches
8205  // activate leafcount branches for active branches only
8206  for (i = 0; i < nleaves; i++) {
8207  leaf = (TLeaf*)fLeaves.UncheckedAt(i);
8208  branch = (TBranch*)leaf->GetBranch();
8209  if (!branch->TestBit(kDoNotProcess)) {
8210  leafcount = leaf->GetLeafCount();
8211  if (leafcount) {
8212  bcount = leafcount->GetBranch();
8213  bcount->ResetBit(kDoNotProcess);
8214  }
8215  } else {
8216  //Int_t nbranches = branch->GetListOfBranches()->GetEntriesFast();
8217  Int_t nbranches = branch->GetListOfBranches()->GetEntries();
8218  for (j=0;j<nbranches;j++) {
8219  bson = (TBranch*)branch->GetListOfBranches()->UncheckedAt(j);
8220  if (!bson) continue;
8221  if (!bson->TestBit(kDoNotProcess)) {
8222  if (bson->GetNleaves() <= 0) continue;
8223  branch->ResetBit(kDoNotProcess);
8224  break;
8225  }
8226  }
8227  }
8228  }
8229 }
8230 
8231 ////////////////////////////////////////////////////////////////////////////////
8232 /// Set the current branch style. (static function)
8233 ///
8234 /// - style = 0 old Branch
8235 /// - style = 1 new Bronch
8236 
8239  fgBranchStyle = style;
8240 }
8241 
8242 ////////////////////////////////////////////////////////////////////////////////
8243 /// Set maximum size of the file cache .
8244 //
8245 /// - if cachesize = 0 the existing cache (if any) is deleted.
8246 /// - if cachesize = -1 (default) it is set to the AutoFlush value when writing
8247 /// the Tree (default is 30 MBytes).
8248 ///
8249 /// Returns:
8250 /// - 0 size set, cache was created if possible
8251 /// - -1 on error
8252 
8255  // remember that the user has requested an explicit cache setup
8256  fCacheUserSet = kTRUE;
8257 
8258  return SetCacheSizeAux(kFALSE, cacheSize);
8259 }
8260 
8261 ////////////////////////////////////////////////////////////////////////////////
8262 /// Set the size of the file cache and create it if possible.
8263 ///
8264 /// If autocache is true:
8265 /// this may be an autocreated cache, possibly enlarging an existing
8266 /// autocreated cache. The size is calculated. The value passed in cacheSize:
8267 /// - cacheSize = 0 make cache if default cache creation is enabled
8268 /// - cacheSize = -1 make a default sized cache in any case
8269 ///
8270 /// If autocache is false:
8271 /// this is a user requested cache. cacheSize is used to size the cache.
8272 /// This cache should never be automatically adjusted.
8273 ///
8274 /// Returns:
8275 /// - 0 size set, or existing autosized cache almost large enough.
8276 /// (cache was created if possible)
8277 /// - -1 on error
8278 
8279 Int_t TTree::SetCacheSizeAux(Bool_t autocache /* = kTRUE */, Long64_t cacheSize /* = 0 */ )
8281  if (autocache) {
8282  // used as a once only control for automatic cache setup
8284  }
8285 
8286  if (!autocache) {
8287  // negative size means the user requests the default
8288  if (cacheSize < 0) {
8289  cacheSize = GetCacheAutoSize(kTRUE);
8290  }
8291  } else {
8292  if (cacheSize == 0) {
8293  cacheSize = GetCacheAutoSize();
8294  } else if (cacheSize < 0) {
8295  cacheSize = GetCacheAutoSize(kTRUE);
8296  }
8297  }
8298 
8299  TFile* file = GetCurrentFile();
8300  if (!file || GetTree() != this) {
8301  // if there's no file or we are not a plain tree (e.g. if we're a TChain)
8302  // do not create a cache, only record the size if one was given
8303  if (!autocache) {
8304  fCacheSize = cacheSize;
8305  }
8306  if (GetTree() != this) {
8307  return 0;
8308  }
8309  if (!autocache && cacheSize>0) {
8310  Warning("SetCacheSizeAux", "A TTreeCache could not be created because the TTree has no file");
8311  }
8312  return 0;
8313  }
8314 
8315  // Check for an existing cache
8316  TTreeCache* pf = GetReadCache(file);
8317  if (pf) {
8318  if (autocache) {
8319  // reset our cache status tracking in case existing cache was added
8320  // by the user without using one of the TTree methods
8321  fCacheSize = pf->GetBufferSize();
8322  fCacheUserSet = !pf->IsAutoCreated();
8323 
8324  if (fCacheUserSet) {
8325  // existing cache was created by the user, don't change it
8326  return 0;
8327  }
8328  } else {
8329  // update the cache to ensure it records the user has explicitly
8330  // requested it
8331  pf->SetAutoCreated(kFALSE);
8332  }
8333 
8334  // if we're using an automatically calculated size and the existing
8335  // cache is already almost large enough don't resize
8336  if (autocache && Long64_t(0.80*cacheSize) < fCacheSize) {
8337  // already large enough
8338  return 0;
8339  }
8340 
8341  if (cacheSize == fCacheSize) {
8342  return 0;
8343  }
8344 
8345  if (cacheSize == 0) {
8346  // delete existing cache
8347  pf->WaitFinishPrefetch();
8348  file->SetCacheRead(0,this);
8349  delete pf;
8350  pf = 0;
8351  } else {
8352  // resize
8353  Int_t res = pf->SetBufferSize(cacheSize);
8354  if (res < 0) {
8355  return -1;
8356  }
8357  }
8358  } else {
8359  // no existing cache
8360  if (autocache) {
8361  if (fCacheUserSet) {
8362  // value was already set manually.
8363  if (fCacheSize == 0) return 0;
8364  // Expected a cache should exist; perhaps the user moved it
8365  // Do nothing more here.
8366  if (cacheSize) {
8367  Error("SetCacheSizeAux", "Not setting up an automatically sized TTreeCache because of missing cache previously set");
8368  }
8369  return -1;
8370  }
8371  }
8372  }
8373 
8374  fCacheSize = cacheSize;
8375  if (cacheSize == 0 || pf) {
8376  return 0;
8377  }
8378 
8379  if(TTreeCacheUnzip::IsParallelUnzip() && file->GetCompressionLevel() > 0)
8380  pf = new TTreeCacheUnzip(this, cacheSize);
8381  else
8382  pf = new TTreeCache(this, cacheSize);
8383 
8384  pf->SetAutoCreated(autocache);
8385 
8386  return 0;
8387 }
8388 
8389 ////////////////////////////////////////////////////////////////////////////////
8390 ///interface to TTreeCache to set the cache entry range
8391 ///
8392 /// Returns:
8393 /// - 0 entry range set
8394 /// - -1 on error
8395 
8398  if (!GetTree()) {
8399  if (LoadTree(0)<0) {
8400  Error("SetCacheEntryRange","Could not load a tree");
8401  return -1;
8402  }
8403  }
8404  if (GetTree()) {
8405  if (GetTree() != this) {
8406  return GetTree()->SetCacheEntryRange(first, last);
8407  }
8408  } else {
8409  Error("SetCacheEntryRange", "No tree is available. Could not set cache entry range");
8410  return -1;
8411  }
8412 
8413  TFile *f = GetCurrentFile();
8414  if (!f) {
8415  Error("SetCacheEntryRange", "No file is available. Could not set cache entry range");
8416  return -1;
8417  }
8418  TTreeCache *tc = GetReadCache(f,kTRUE);
8419  if (!tc) {
8420  Error("SetCacheEntryRange", "No cache is available. Could not set entry range");
8421  return -1;
8422  }
8423  tc->SetEntryRange(first,last);
8424  return 0;
8425 }
8426 
8427 ////////////////////////////////////////////////////////////////////////////////
8428 /// Interface to TTreeCache to set the number of entries for the learning phase
8429 
8433 }
8434 
8435 ////////////////////////////////////////////////////////////////////////////////
8436 /// Enable/Disable circularity for this tree.
8437 ///
8438 /// if maxEntries > 0 a maximum of maxEntries is kept in one buffer/basket
8439 /// per branch in memory.
8440 /// Note that when this function is called (maxEntries>0) the Tree
8441 /// must be empty or having only one basket per branch.
8442 /// if maxEntries <= 0 the tree circularity is disabled.
8443 ///
8444 /// #### NOTE 1:
8445 /// Circular Trees are interesting in online real time environments
8446 /// to store the results of the last maxEntries events.
8447 /// #### NOTE 2:
8448 /// Calling SetCircular with maxEntries <= 0 is necessary before
8449 /// merging circular Trees that have been saved on files.
8450 /// #### NOTE 3:
8451 /// SetCircular with maxEntries <= 0 is automatically called
8452 /// by TChain::Merge
8453 /// #### NOTE 4:
8454 /// A circular Tree can still be saved in a file. When read back,
8455 /// it is still a circular Tree and can be filled again.
8456 
8457 void TTree::SetCircular(Long64_t maxEntries)
8459  if (maxEntries <= 0) {
8460  // Disable circularity.
8461  fMaxEntries = 1000000000;
8462  fMaxEntries *= 1000;
8464  //in case the Tree was originally created in gROOT, the branch
8465  //compression level was set to -1. If the Tree is now associated to
8466  //a file, reset the compression level to the file compression level
8467  if (fDirectory) {
8468  TFile* bfile = fDirectory->GetFile();
8469  Int_t compress = 1;
8470  if (bfile) {
8471  compress = bfile->GetCompressionSettings();
8472  }
8474  for (Int_t i = 0; i < nb; i++) {
8475  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8476  branch->SetCompressionSettings(compress);
8477  }
8478  }
8479  } else {
8480  // Enable circularity.
8481  fMaxEntries = maxEntries;
8482  SetBit(kCircular);
8483  }
8484 }
8485 
8486 ////////////////////////////////////////////////////////////////////////////////
8487 /// Set the debug level and the debug range.
8488 ///
8489 /// For entries in the debug range, the functions TBranchElement::Fill
8490 /// and TBranchElement::GetEntry will print the number of bytes filled
8491 /// or read for each branch.
8492 
8493 void TTree::SetDebug(Int_t level, Long64_t min, Long64_t max)
8495  fDebug = level;
8496  fDebugMin = min;
8497  fDebugMax = max;
8498 }
8499 
8500 ////////////////////////////////////////////////////////////////////////////////
8501 /// Update the default value for the branch's fEntryOffsetLen.
8502 /// If updateExisting is true, also update all the existing branches.
8503 /// If newdefault is less than 10, the new default value will be 10.
8504 
8505 void TTree::SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting)
8507  if (newdefault < 10) {
8508  newdefault = 10;
8509  }
8510  fDefaultEntryOffsetLen = newdefault;
8511  if (updateExisting) {
8512  TIter next( GetListOfBranches() );
8513  TBranch *b;
8514  while ( ( b = (TBranch*)next() ) ) {
8515  b->SetEntryOffsetLen( newdefault, kTRUE );
8516  }
8517  if (fBranchRef) {
8518  fBranchRef->SetEntryOffsetLen( newdefault, kTRUE );
8519  }
8520  }
8521 }
8522 
8523 ////////////////////////////////////////////////////////////////////////////////
8524 /// Change the tree's directory.
8525 ///
8526 /// Remove reference to this tree from current directory and
8527 /// add reference to new directory dir. The dir parameter can
8528 /// be 0 in which case the tree does not belong to any directory.
8529 ///
8530 
8533  if (fDirectory == dir) {
8534  return;
8535  }
8536  if (fDirectory) {
8537  fDirectory->Remove(this);
8538 
8539  // Delete or move the file cache if it points to this Tree
8540  TFile *file = fDirectory->GetFile();
8541  MoveReadCache(file,dir);
8542  }
8543  fDirectory = dir;
8544  if (fDirectory) {
8545  fDirectory->Append(this);
8546  }
8547  TFile* file = 0;
8548  if (fDirectory) {
8549  file = fDirectory->GetFile();
8550  }
8551  if (fBranchRef) {
8553  }
8554  TBranch* b = 0;
8555  TIter next(GetListOfBranches());
8556  while((b = (TBranch*) next())) {
8557  b->SetFile(file);
8558  }
8559 }
8560 
8561 ////////////////////////////////////////////////////////////////////////////////
8562 /// Change number of entries in the tree.
8563 ///
8564 /// If n >= 0, set number of entries in the tree = n.
8565 ///
8566 /// If n < 0, set number of entries in the tree to match the
8567 /// number of entries in each branch. (default for n is -1)
8568 ///
8569 /// This function should be called only when one fills each branch
8570 /// independently via TBranch::Fill without calling TTree::Fill.
8571 /// Calling TTree::SetEntries() make sense only if the number of entries
8572 /// in each branch is identical, a warning is issued otherwise.
8573 /// The function returns the number of entries.
8574 ///
8575 
8578  // case 1 : force number of entries to n
8579  if (n >= 0) {
8580  fEntries = n;
8581  return n;
8582  }
8583 
8584  // case 2; compute the number of entries from the number of entries in the branches
8585  TBranch* b(nullptr), *bMin(nullptr), *bMax(nullptr);
8586  Long64_t nMin = kMaxEntries;
8587  Long64_t nMax = 0;
8588  TIter next(GetListOfBranches());
8589  while((b = (TBranch*) next())){
8590  Long64_t n2 = b->GetEntries();
8591  if (!bMin || n2 < nMin) {
8592  nMin = n2;
8593  bMin = b;
8594  }
8595  if (!bMax || n2 > nMax) {
8596  nMax = n2;
8597  bMax = b;
8598  }
8599  }
8600  if (bMin && nMin != nMax) {
8601  Warning("SetEntries", "Tree branches have different numbers of entries, eg %s has %lld entries while %s has %lld entries.",
8602  bMin->GetName(), nMin, bMax->GetName(), nMax);
8603  }
8604  fEntries = nMax;
8605  return fEntries;
8606 }
8607 
8608 ////////////////////////////////////////////////////////////////////////////////
8609 /// Set an EntryList
8610 
8611 void TTree::SetEntryList(TEntryList *enlist, Option_t * /*opt*/)
8613  if (fEntryList) {
8614  //check if the previous entry list is owned by the tree
8615  if (fEntryList->TestBit(kCanDelete)){
8616  delete fEntryList;
8617  }
8618  }
8619  fEventList = 0;
8620  if (!enlist) {
8621  fEntryList = 0;
8622  return;
8623  }
8624  fEntryList = enlist;
8625  fEntryList->SetTree(this);
8626 
8627 }
8628 
8629 ////////////////////////////////////////////////////////////////////////////////
8630 /// This function transfroms the given TEventList into a TEntryList
8631 /// The new TEntryList is owned by the TTree and gets deleted when the tree
8632 /// is deleted. This TEntryList can be returned by GetEntryList() function.
8633 
8634 void TTree::SetEventList(TEventList *evlist)
8636  fEventList = evlist;
8637  if (fEntryList){
8638  if (fEntryList->TestBit(kCanDelete)) {
8639  TEntryList *tmp = fEntryList;
8640  fEntryList = 0; // Avoid problem with RecursiveRemove.
8641  delete tmp;
8642  } else {
8643  fEntryList = 0;
8644  }
8645  }
8646 
8647  if (!evlist) {
8648  fEntryList = 0;
8649  fEventList = 0;
8650  return;
8651  }
8652 
8653  fEventList = evlist;
8654  char enlistname[100];
8655  snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
8656  fEntryList = new TEntryList(enlistname, evlist->GetTitle());
8657  fEntryList->SetDirectory(0); // We own this.
8658  Int_t nsel = evlist->GetN();
8659  fEntryList->SetTree(this);
8660  Long64_t entry;
8661  for (Int_t i=0; i<nsel; i++){
8662  entry = evlist->GetEntry(i);
8663  fEntryList->Enter(entry);
8664  }
8667 }
8668 
8669 ////////////////////////////////////////////////////////////////////////////////
8670 /// Set number of entries to estimate variable limits.
8671 /// If n is -1, the estimate is set to be the current maximum
8672 /// for the tree (i.e. GetEntries() + 1)
8673 /// If n is less than -1, the behavior is undefined.
8674 
8675 void TTree::SetEstimate(Long64_t n /* = 1000000 */)
8677  if (n == 0) {
8678  n = 10000;
8679  } else if (n < 0) {
8680  n = fEntries - n;
8681  }
8682  fEstimate = n;
8683  GetPlayer();
8684  if (fPlayer) {
8685  fPlayer->SetEstimate(n);
8686  }
8687 }
8688 
8689 ////////////////////////////////////////////////////////////////////////////////
8690 /// Provide the end-user with the ability to enable/disable various experimental
8691 /// IO features for this TTree.
8692 ///
8693 /// Returns all the newly-set IO settings.
8694 
8697  // Purposely ignore all unsupported bits; TIOFeatures implementation already warned the user about the
8698  // error of their ways; this is just a safety check.
8699  UChar_t featuresRequested = features.GetFeatures() & static_cast<UChar_t>(TBasket::EIOBits::kSupported);
8700 
8701  UChar_t curFeatures = fIOFeatures.GetFeatures();
8702  UChar_t newFeatures = ~curFeatures & featuresRequested;
8703  curFeatures |= newFeatures;
8704  fIOFeatures.Set(curFeatures);
8705 
8706  ROOT::TIOFeatures newSettings(newFeatures);
8707  return newSettings;
8708 }
8709 
8710 ////////////////////////////////////////////////////////////////////////////////
8711 /// Set fFileNumber to number.
8712 /// fFileNumber is used by TTree::Fill to set the file name
8713 /// for a new file to be created when the current file exceeds fgTreeMaxSize.
8714 /// (see TTree::ChangeFile)
8715 /// if fFileNumber=10, the new file name will have a suffix "_11",
8716 /// ie, fFileNumber is incremented before setting the file name
8717 
8718 void TTree::SetFileNumber(Int_t number)
8720  if (fFileNumber < 0) {
8721  Warning("SetFileNumber", "file number must be positive. Set to 0");
8722  fFileNumber = 0;
8723  return;
8724  }
8725  fFileNumber = number;
8726 }
8727 
8728 ////////////////////////////////////////////////////////////////////////////////
8729 /// Set all the branches in this TTree to be in decomposed object mode
8730 /// (also known as MakeClass mode).
8731 
8734  fMakeClass = make;
8735 
8737  for (Int_t i = 0; i < nb; ++i) {
8738  TBranch* branch = (TBranch*) fBranches.UncheckedAt(i);
8739  branch->SetMakeClass(make);
8740  }
8741 }
8742 
8743 ////////////////////////////////////////////////////////////////////////////////
8744 /// Set the maximum size in bytes of a Tree file (static function).
8745 /// The default size is 100000000000LL, ie 100 Gigabytes.
8746 ///
8747 /// In TTree::Fill, when the file has a size > fgMaxTreeSize,
8748 /// the function closes the current file and starts writing into
8749 /// a new file with a name of the style "file_1.root" if the original
8750 /// requested file name was "file.root".
8751 
8752 void TTree::SetMaxTreeSize(Long64_t maxsize)
8754  fgMaxTreeSize = maxsize;
8755 }
8756 
8757 ////////////////////////////////////////////////////////////////////////////////
8758 /// Change the name of this tree.
8759 
8760 void TTree::SetName(const char* name)
8762  if (gPad) {
8763  gPad->Modified();
8764  }
8765  // Trees are named objects in a THashList.
8766  // We must update hashlists if we change the name.
8767  TFile *file = 0;
8768  TTreeCache *pf = 0;
8769  if (fDirectory) {
8770  fDirectory->Remove(this);
8771  if ((file = GetCurrentFile())) {
8772  pf = GetReadCache(file);
8773  file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8774  }
8775  }
8776  // This changes our hash value.
8777  fName = name;
8778  if (fDirectory) {
8779  fDirectory->Append(this);
8780  if (pf) {
8781  file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8782  }
8783  }
8784 }
8785 
8786 ////////////////////////////////////////////////////////////////////////////////
8787 /// Change the name and title of this tree.
8788 
8789 void TTree::SetObject(const char* name, const char* title)
8791  if (gPad) {
8792  gPad->Modified();
8793  }
8794 
8795  // Trees are named objects in a THashList.
8796  // We must update hashlists if we change the name
8797  TFile *file = 0;
8798  TTreeCache *pf = 0;
8799  if (fDirectory) {
8800  fDirectory->Remove(this);
8801  if ((file = GetCurrentFile())) {
8802  pf = GetReadCache(file);
8803  file->SetCacheRead(0,this,TFile::kDoNotDisconnect);
8804  }
8805  }
8806  // This changes our hash value.
8807  fName = name;
8808  fTitle = title;
8809  if (fDirectory) {
8810  fDirectory->Append(this);
8811  if (pf) {
8812  file->SetCacheRead(pf,this,TFile::kDoNotDisconnect);
8813  }
8814  }
8815 }
8816 
8817 ////////////////////////////////////////////////////////////////////////////////
8818 /// Enable or disable parallel unzipping of Tree buffers.
8819 
8820 void TTree::SetParallelUnzip(Bool_t opt, Float_t RelSize)
8824 
8825  if (RelSize > 0) {
8827  }
8828 
8829 }
8830 
8831 ////////////////////////////////////////////////////////////////////////////////
8832 /// Set perf stats
8833 
8836  fPerfStats = perf;
8837 }
8838 
8839 ////////////////////////////////////////////////////////////////////////////////
8840 /// The current TreeIndex is replaced by the new index.
8841 /// Note that this function does not delete the previous index.
8842 /// This gives the possibility to play with more than one index, e.g.,
8843 /// ~~~ {.cpp}
8844 /// TVirtualIndex* oldIndex = tree.GetTreeIndex();
8845 /// tree.SetTreeIndex(newIndex);
8846 /// tree.Draw();
8847 /// tree.SetTreeIndex(oldIndex);
8848 /// tree.Draw(); etc
8849 /// ~~~
8850 
8853  if (fTreeIndex) {
8854  fTreeIndex->SetTree(0);
8855  }
8856  fTreeIndex = index;
8857 }
8858 
8859 ////////////////////////////////////////////////////////////////////////////////
8860 /// Set tree weight.
8861 ///
8862 /// The weight is used by TTree::Draw to automatically weight each
8863 /// selected entry in the resulting histogram.
8864 ///
8865 /// For example the equivalent of:
8866 /// ~~~ {.cpp}
8867 /// T.Draw("x", "w")
8868 /// ~~~
8869 /// is:
8870 /// ~~~ {.cpp}
8871 /// T.SetWeight(w);
8872 /// T.Draw("x");
8873 /// ~~~
8874 /// This function is redefined by TChain::SetWeight. In case of a
8875 /// TChain, an option "global" may be specified to set the same weight
8876 /// for all trees in the TChain instead of the default behaviour
8877 /// using the weights of each tree in the chain (see TChain::SetWeight).
8878 
8881  fWeight = w;
8882 }
8883 
8884 ////////////////////////////////////////////////////////////////////////////////
8885 /// Print values of all active leaves for entry.
8886 ///
8887 /// - if entry==-1, print current entry (default)
8888 /// - if a leaf is an array, a maximum of lenmax elements is printed.
8889 
8890 void TTree::Show(Long64_t entry, Int_t lenmax)
8892  if (entry != -1) {
8893  Int_t ret = LoadTree(entry);
8894  if (ret == -2) {
8895  Error("Show()", "Cannot read entry %lld (entry does not exist)", entry);
8896  return;
8897  } else if (ret == -1) {
8898  Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8899  return;
8900  }
8901  ret = GetEntry(entry);
8902  if (ret == -1) {
8903  Error("Show()", "Cannot read entry %lld (I/O error)", entry);
8904  return;
8905  } else if (ret == 0) {
8906  Error("Show()", "Cannot read entry %lld (no data read)", entry);
8907  return;
8908  }
8909  }
8910  printf("======> EVENT:%lld\n", fReadEntry);
8911  TObjArray* leaves = GetListOfLeaves();
8912  Int_t nleaves = leaves->GetEntriesFast();
8913  Int_t ltype;
8914  for (Int_t i = 0; i < nleaves; i++) {
8915  TLeaf* leaf = (TLeaf*) leaves->UncheckedAt(i);
8916  TBranch* branch = leaf->GetBranch();
8917  if (branch->TestBit(kDoNotProcess)) {
8918  continue;
8919  }
8920  Int_t len = leaf->GetLen();
8921  if (len <= 0) {
8922  continue;
8923  }
8924  len = TMath::Min(len, lenmax);
8925  if (leaf->IsA() == TLeafElement::Class()) {
8926  leaf->PrintValue(lenmax);
8927  continue;
8928  }
8929  if (branch->GetListOfBranches()->GetEntriesFast() > 0) {
8930  continue;
8931  }
8932  ltype = 10;
8933  if (leaf->IsA() == TLeafF::Class()) {
8934  ltype = 5;
8935  }
8936  if (leaf->IsA() == TLeafD::Class()) {
8937  ltype = 5;
8938  }
8939  if (leaf->IsA() == TLeafC::Class()) {
8940  len = 1;
8941  ltype = 5;
8942  };
8943  printf(" %-15s = ", leaf->GetName());
8944  for (Int_t l = 0; l < len; l++) {
8945  leaf->PrintValue(l);
8946  if (l == (len - 1)) {
8947  printf("\n");
8948  continue;
8949  }
8950  printf(", ");
8951  if ((l % ltype) == 0) {
8952  printf("\n ");
8953  }
8954  }
8955  }
8956 }
8957 
8958 ////////////////////////////////////////////////////////////////////////////////
8959 /// Start the TTreeViewer on this tree.
8960 ///
8961 /// - ww is the width of the canvas in pixels
8962 /// - wh is the height of the canvas in pixels
8963 
8964 void TTree::StartViewer()
8966  GetPlayer();
8967  if (fPlayer) {
8968  fPlayer->StartViewer(600, 400);
8969  }
8970 }
8971 
8972 ////////////////////////////////////////////////////////////////////////////////
8973 /// Stop the cache learning phase
8974 ///
8975 /// Returns:
8976 /// - 0 learning phase stopped or not active
8977 /// - -1 on error
8978 
8981  if (!GetTree()) {
8982  if (LoadTree(0)<0) {
8983  Error("StopCacheLearningPhase","Could not load a tree");
8984  return -1;
8985  }
8986  }
8987  if (GetTree()) {
8988  if (GetTree() != this) {
8989  return GetTree()->StopCacheLearningPhase();
8990  }
8991  } else {
8992  Error("StopCacheLearningPhase", "No tree is available. Could not stop cache learning phase");
8993  return -1;
8994  }
8995 
8996  TFile *f = GetCurrentFile();
8997  if (!f) {
8998  Error("StopCacheLearningPhase", "No file is available. Could not stop cache learning phase");
8999  return -1;
9000  }
9001  TTreeCache *tc = GetReadCache(f,kTRUE);
9002  if (!tc) {
9003  Error("StopCacheLearningPhase", "No cache is available. Could not stop learning phase");
9004  return -1;
9005  }
9006  tc->StopLearningPhase();
9007  return 0;
9008 }
9009 
9010 ////////////////////////////////////////////////////////////////////////////////
9011 /// Set the fTree member for all branches and sub branches.
9012 
9015  Int_t nb = branches.GetEntriesFast();
9016  for (Int_t i = 0; i < nb; ++i) {
9017  TBranch* br = (TBranch*) branches.UncheckedAt(i);
9018  br->SetTree(tree);
9019 
9020  Int_t nBaskets = br->GetListOfBaskets()->GetEntries();
9021  Int_t writeBasket = br->GetWriteBasket();
9022  for (Int_t j=writeBasket,n=0;j>=0 && n<nBaskets;--j) {
9023  TBasket *bk = (TBasket*)br->GetListOfBaskets()->UncheckedAt(j);
9024  if (bk) {
9025  tree->IncrementTotalBuffers(bk->GetBufferSize());
9026  ++n;
9027  }
9028  }
9029 
9031  }
9032 }
9033 
9034 ////////////////////////////////////////////////////////////////////////////////
9035 /// Set the fTree member for all friend elements.
9036 
9037 void TFriendElement__SetTree(TTree *tree, TList *frlist)
9039  if (frlist) {
9040  TObjLink *lnk = frlist->FirstLink();
9041  while (lnk) {
9042  TFriendElement *elem = (TFriendElement*)lnk->GetObject();
9043  elem->fParentTree = tree;
9044  lnk = lnk->Next();
9045  }
9046  }
9047 }
9048 
9049 ////////////////////////////////////////////////////////////////////////////////
9050 /// Stream a class object.
9051 
9052 void TTree::Streamer(TBuffer& b)
9053 {
9054  if (b.IsReading()) {
9055  UInt_t R__s, R__c;
9056  if (fDirectory) {
9057  fDirectory->Remove(this);
9058  //delete the file cache if it points to this Tree
9059  TFile *file = fDirectory->GetFile();
9060  MoveReadCache(file,0);
9061  }
9062  fDirectory = 0;
9065  Version_t R__v = b.ReadVersion(&R__s, &R__c);
9066  if (R__v > 4) {
9067  b.ReadClassBuffer(TTree::Class(), this, R__v, R__s, R__c);
9068 
9069  fBranches.SetOwner(kTRUE); // True needed only for R__v < 19 and most R__v == 19
9070 
9071  if (fBranchRef) fBranchRef->SetTree(this);
9074 
9075  if (fTreeIndex) {
9076  fTreeIndex->SetTree(this);
9077  }
9078  if (fIndex.fN) {
9079  Warning("Streamer", "Old style index in this tree is deleted. Rebuild the index via TTree::BuildIndex");
9080  fIndex.Set(0);
9081  fIndexValues.Set(0);
9082  }
9083  if (fEstimate <= 10000) {
9084  fEstimate = 1000000;
9085  }
9086  if (GetCacheAutoSize() != 0) {
9087  // a cache will be automatically created.
9088  // No need for TTreePlayer::Process to enable the cache
9089  fCacheSize = 0;
9090  } else if (fAutoFlush < 0) {
9091  // If there is no autoflush set, let's keep the cache completely
9092  // disable by default for now.
9094  } else if (fAutoFlush != 0) {
9095  // Estimate the cluster size.
9096  // This will allow TTree::Process to enable the cache.
9097  Long64_t zipBytes = GetZipBytes();
9098  Long64_t totBytes = GetTotBytes();
9099  if (zipBytes != 0) {
9100  fCacheSize = fAutoFlush*(zipBytes/fEntries);
9101  } else if (totBytes != 0) {
9102  fCacheSize = fAutoFlush*(totBytes/fEntries);
9103  } else {
9104  fCacheSize = 30000000;
9105  }
9106  if (fCacheSize >= (INT_MAX / 4)) {
9107  fCacheSize = INT_MAX / 4;
9108  } else if (fCacheSize == 0) {
9109  fCacheSize = 30000000;
9110  }
9111  } else {
9112  fCacheSize = 0;
9113  }
9115  return;
9116  }
9117  //====process old versions before automatic schema evolution
9118  Stat_t djunk;
9119  Int_t ijunk;
9120  TNamed::Streamer(b);
9121  TAttLine::Streamer(b);
9122  TAttFill::Streamer(b);
9123  TAttMarker::Streamer(b);
9124  b >> fScanField;
9125  b >> ijunk; fMaxEntryLoop = (Long64_t)ijunk;
9126  b >> ijunk; fMaxVirtualSize = (Long64_t)ijunk;
9127  b >> djunk; fEntries = (Long64_t)djunk;
9128  b >> djunk; fTotBytes = (Long64_t)djunk;
9129  b >> djunk; fZipBytes = (Long64_t)djunk;
9130  b >> ijunk; fAutoSave = (Long64_t)ijunk;
9131  b >> ijunk; fEstimate = (Long64_t)ijunk;
9132  if (fEstimate <= 10000) fEstimate = 1000000;
9133  fBranches.Streamer(b);
9134  if (fBranchRef) fBranchRef->SetTree(this);
9136  fLeaves.Streamer(b);
9138  if (R__v > 1) fIndexValues.Streamer(b);
9139  if (R__v > 2) fIndex.Streamer(b);
9140  if (R__v > 3) {
9141  TList OldInfoList;
9142  OldInfoList.Streamer(b);
9143  OldInfoList.Delete();
9144  }
9145  fNClusterRange = 0;
9146  fDefaultEntryOffsetLen = 1000;
9148  b.CheckByteCount(R__s, R__c, TTree::IsA());
9149  //====end of old versions
9150  } else {
9151  if (fBranchRef) {
9152  fBranchRef->Clear();
9153  }
9154  TRefTable *table = TRefTable::GetRefTable();
9155  if (table) TRefTable::SetRefTable(0);
9156 
9157  b.WriteClassBuffer(TTree::Class(), this);
9158 
9159  if (table) TRefTable::SetRefTable(table);
9160  }
9161 }
9162 
9163 ////////////////////////////////////////////////////////////////////////////////
9164 /// Unbinned fit of one or more variable(s) from a tree.
9165 ///
9166 /// funcname is a TF1 function.
9167 ///
9168 /// See TTree::Draw for explanations of the other parameters.
9169 ///
9170 /// Fit the variable varexp using the function funcname using the
9171 /// selection cuts given by selection.
9172 ///
9173 /// The list of fit options is given in parameter option.
9174 ///
9175 /// - option = "Q" Quiet mode (minimum printing)
9176 /// - option = "V" Verbose mode (default is between Q and V)
9177 /// - option = "E" Perform better Errors estimation using Minos technique
9178 /// - option = "M" More. Improve fit results
9179 ///
9180 /// You can specify boundary limits for some or all parameters via
9181 /// ~~~ {.cpp}
9182 /// func->SetParLimits(p_number, parmin, parmax);
9183 /// ~~~
9184 /// if parmin>=parmax, the parameter is fixed
9185 ///
9186 /// Note that you are not forced to fix the limits for all parameters.
9187 /// For example, if you fit a function with 6 parameters, you can do:
9188 /// ~~~ {.cpp}
9189 /// func->SetParameters(0,3.1,1.e-6,0.1,-8,100);
9190 /// func->SetParLimits(4,-10,-4);
9191 /// func->SetParLimits(5, 1,1);
9192 /// ~~~
9193 /// With this setup:
9194 ///
9195 /// - Parameters 0->3 can vary freely
9196 /// - Parameter 4 has boundaries [-10,-4] with initial value -8
9197 /// - Parameter 5 is fixed to 100.
9198 ///
9199 /// For the fit to be meaningful, the function must be self-normalized.
9200 ///
9201 /// i.e. It must have the same integral regardless of the parameter
9202 /// settings. Otherwise the fit will effectively just maximize the
9203 /// area.
9204 ///
9205 /// It is mandatory to have a normalization variable
9206 /// which is fixed for the fit. e.g.
9207 /// ~~~ {.cpp}
9208 /// TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2*3.14159)/[2]", 0, 5);
9209 /// f1->SetParameters(1, 3.1, 0.01);
9210 /// f1->SetParLimits(0, 1, 1); // fix the normalization parameter to 1
9211 /// data->UnbinnedFit("f1", "jpsimass", "jpsipt>3.0");
9212 /// ~~~
9213 /// 1, 2 and 3 Dimensional fits are supported. See also TTree::Fit
9214 ///
9215 /// Return status:
9216 ///
9217 /// - The function return the status of the fit in the following form
9218 /// fitResult = migradResult + 10*minosResult + 100*hesseResult + 1000*improveResult
9219 /// - The fitResult is 0 is the fit is OK.
9220 /// - The fitResult is negative in case of an error not connected with the fit.
9221 /// - The number of entries used in the fit can be obtained via mytree.GetSelectedRows();
9222 /// - If the number of selected entries is null the function returns -1
9223 
9224 Int_t TTree::UnbinnedFit(const char* funcname, const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
9226  GetPlayer();
9227  if (fPlayer) {
9228  return fPlayer->UnbinnedFit(funcname, varexp, selection, option, nentries, firstentry);
9229  }
9230  return -1;
9231 }
9232 
9233 ////////////////////////////////////////////////////////////////////////////////
9234 /// Replace current attributes by current style.
9235 
9238  if (gStyle->IsReading()) {
9247  } else {
9256  }
9257 }
9258 
9259 ////////////////////////////////////////////////////////////////////////////////
9260 /// Write this object to the current directory. For more see TObject::Write
9261 /// Write calls TTree::FlushBaskets before writing the tree.
9262 
9263 Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) const
9265  FlushBaskets();
9266  return TObject::Write(name, option, bufsize);
9267 }
9268 
9269 ////////////////////////////////////////////////////////////////////////////////
9270 /// Write this object to the current directory. For more see TObject::Write
9271 /// If option & kFlushBasket, call FlushBasket before writing the tree.
9272 
9273 Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize)
9275  return ((const TTree*)this)->Write(name, option, bufsize);
9276 }
9277 
9278 ////////////////////////////////////////////////////////////////////////////////
9279 /// \class TTreeFriendLeafIter
9280 ///
9281 /// Iterator on all the leaves in a TTree and its friend
9282 
9284 
9285 ////////////////////////////////////////////////////////////////////////////////
9286 /// Create a new iterator. By default the iteration direction
9287 /// is kIterForward. To go backward use kIterBackward.
9288 
9290 : fTree(const_cast<TTree*>(tree))
9291 , fLeafIter(0)
9292 , fTreeIter(0)
9293 , fDirection(dir)
9294 {
9295 }
9296 
9297 ////////////////////////////////////////////////////////////////////////////////
9298 /// Copy constructor. Does NOT copy the 'cursor' location!
9299 
9301 : TIterator(iter)
9302 , fTree(iter.fTree)
9303 , fLeafIter(0)
9304 , fTreeIter(0)
9305 , fDirection(iter.fDirection)
9306 {
9307 }
9308 
9309 ////////////////////////////////////////////////////////////////////////////////
9310 /// Overridden assignment operator. Does NOT copy the 'cursor' location!
9311 
9314  if (this != &rhs && rhs.IsA() == TTreeFriendLeafIter::Class()) {
9315  const TTreeFriendLeafIter &rhs1 = (const TTreeFriendLeafIter &)rhs;
9316  fDirection = rhs1.fDirection;
9317  }
9318  return *this;
9319 }
9320 
9321 ////////////////////////////////////////////////////////////////////////////////
9322 /// Overridden assignment operator. Does NOT copy the 'cursor' location!
9323 
9326  if (this != &rhs) {
9327  fDirection = rhs.fDirection;
9328  }
9329  return *this;
9330 }
9331 
9332 ////////////////////////////////////////////////////////////////////////////////
9333 /// Go the next friend element
9334 
9337  if (!fTree) return 0;
9338 
9339  TObject * next;
9340  TTree * nextTree;
9341 
9342  if (!fLeafIter) {
9343  TObjArray *list = fTree->GetListOfLeaves();
9344  if (!list) return 0; // Can happen with an empty chain.
9346  if (!fLeafIter) return 0;
9347  }
9348 
9349  next = fLeafIter->Next();
9350  if (!next) {
9351  if (!fTreeIter) {
9352  TCollection * list = fTree->GetListOfFriends();
9353  if (!list) return next;
9355  if (!fTreeIter) return 0;
9356  }
9357  TFriendElement * nextFriend = (TFriendElement*) fTreeIter->Next();
9358  ///nextTree = (TTree*)fTreeIter->Next();
9359  if (nextFriend) {
9360  nextTree = const_cast<TTree*>(nextFriend->GetTree());
9361  if (!nextTree) return Next();
9364  if (!fLeafIter) return 0;
9365  next = fLeafIter->Next();
9366  }
9367  }
9368  return next;
9369 }
9370 
9371 ////////////////////////////////////////////////////////////////////////////////
9372 /// Returns the object option stored in the list.
9373 
9376  if (fLeafIter) return fLeafIter->GetOption();
9377  return "";
9378 }
A zero length substring is legal.
Definition: TString.h:71
Bool_t HasRuleWithSourceClass(const TString &source) const
Return True if we have any rule whose source class is &#39;source&#39;.
TString fTitle
Definition: TNamed.h:33
TTree * fParentTree
! pointer to the parent TTree
Describe Streamer information for one class version
Definition: TStreamerInfo.h:43
void Foreach(F func, unsigned nTimes)
Execute func (with no arguments) nTimes in parallel.
virtual Bool_t GetReapplyCut() const
Definition: TEventList.h:57
virtual 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:4672
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TObject.cxx:785
Double_t fWeight
Tree weight (see TTree::SetWeight)
Definition: TTree.h:81
virtual Int_t Occurence(const TObject *obj) const
Return occurence number of object in the list of objects of this folder.
Definition: TFolder.cxx:436
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1276
virtual Int_t MakeProxy(const char *classname, const char *macrofilename=0, const char *cutfilename=0, const char *option=0, Int_t maxUnrolling=3)=0
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:32
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition: TAttLine.h:43
Long64_t Previous()
Move on to the previous cluster and return the starting entry of this previous cluster.
Definition: TTree.cxx:647
virtual void AddTotBytes(Int_t tot)
Definition: TTree.h:295
TTreeCache * GetReadCache(TFile *file, Bool_t create=kFALSE)
Find and return the TTreeCache registered with the file and which may contain branches for us...
Definition: TTree.cxx:6072
A TFolder object is a collection of objects and folders.
Definition: TFolder.h:30
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch after a Merge operation (drop data but keep customizations) TRefTable is cleared...
Definition: TBranchRef.cxx:198
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2231
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3507
virtual TTree * CopyTree(const char *selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
ESTLType
Definition: ESTLType.h:28
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=0, Bool_t canOptimize=kTRUE)
Build StreamerInfo for class cl.
Definition: TTree.cxx:2601
An array of TObjects.
Definition: TObjArray.h:37
static TDataType * GetDataType(EDataType type)
Given a EDataType type, get the TDataType* that represents it.
Definition: TDataType.cxx:440
Long64_t fDebugMin
! First entry number to debug
Definition: TTree.h:103
Principal Components Analysis (PCA)
Definition: TPrincipal.h:20
TTree * fTree
tree being iterated
Definition: TTree.h:591
virtual Int_t FillImpl(ROOT::Internal::TBranchIMTHelper *)
Loop on all leaves of this branch to fill Basket buffer.
Definition: TBranch.cxx:758
virtual TDirectory * GetDirectory() const
Definition: TEntryList.h:74
virtual void Append(const TVirtualIndex *, Bool_t delaySort=kFALSE)=0
Bool_t fPrevious
Definition: TTree.h:170
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:150
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:467
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition: TBranch.cxx:2784
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
virtual Option_t * GetOption() const
Definition: TIterator.h:40
TString GetTypeName()
Get basic type of typedef, e,g.
Definition: TDataType.cxx:149
virtual TTree * GetTree()
Return pointer to friend TTree.
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket...
Definition: TBufferFile.h:47
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2170
virtual void OptimizeBaskets(ULong64_t maxMemory=10000000, Float_t minComp=1.1, Option_t *option="")
This function may be called after having filled some entries in a Tree.
Definition: TTree.cxx:6779
Bool_t MemoryFull(Int_t nbytes)
Check if adding nbytes to memory we are still below MaxVirtualsize.
Definition: TTree.cxx:6581
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:1521
virtual Int_t MakeCode(const char *filename=0)
Generate a skeleton function for this tree.
Definition: TTree.cxx:6384
long long Long64_t
Definition: RtypesCore.h:69
TIterator * fTreeIter
current tree sub-iterator.
Definition: TTree.h:593
Abstract interface for Tree Index.
Definition: TVirtualIndex.h:29
auto * m
Definition: textangle.C:8
virtual Int_t GetBasketSize() const
Definition: TBranch.h:166
virtual void SetReapplyCut(Bool_t apply=kFALSE)
Definition: TEntryList.h:105
virtual Int_t MakeReader(const char *classname, Option_t *option)=0
virtual Long64_t ReadStream(std::istream &inputStream, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from an input stream.
Definition: TTree.cxx:7288
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition: TTree.cxx:8980
virtual void SetBranchStatus(const char *bname, Bool_t status=1, UInt_t *found=0)
Set branch status to Process or DoNotProcess.
Definition: TTree.cxx:8112
short Version_t
Definition: RtypesCore.h:61
virtual void Delete(Option_t *option="")
Delete this tree from memory or/and disk.
Definition: TTree.cxx:3617
Bool_t EqualTo(const char *cs, ECaseCompare cmp=kExact) const
Definition: TString.h:579
A Branch for the case of an object.
Definition: TBranchObject.h:26
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
TObjArray * GetListOfBaskets()
Definition: TBranch.h:192
TLine * line
static Int_t fgBranchStyle
Old/New branch style.
Definition: TTree.h:134
virtual void AddZipBytes(Int_t zip)
Definition: TTree.h:296
virtual void SetTree(const TTree *T)=0
virtual Int_t LoadBaskets(Long64_t maxmemory=2000000000)
Read in memory all baskets from all branches up to the limit of maxmemory bytes.
Definition: TTree.cxx:6188
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:320
float Float_t
Definition: RtypesCore.h:53
virtual Int_t GetExpectedType(TClass *&clptr, EDataType &type)
Fill expectedClass and expectedType with information on the data type of the object/values contained ...
Definition: TBranch.cxx:1416
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:6845
static Long64_t GetMaxTreeSize()
Static function which returns the tree file size limit in bytes.
Definition: TTree.cxx:6019
virtual void SetParallelUnzip(Bool_t opt=kTRUE, Float_t RelSize=-1)
Enable or disable parallel unzipping of Tree buffers.
Definition: TTree.cxx:8821
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:6748
virtual Int_t MakeCode(const char *filename)=0
Provides the interface for the PROOF internal performance measurement and event tracing.
A cache when reading files over the network.
const char Option_t
Definition: RtypesCore.h:62
virtual Bool_t Notify()
Function called when loading a new class library.
Definition: TTree.cxx:6755
TTree()
Default constructor and I/O constructor.
Definition: TTree.cxx:691
virtual TTree * GetFriend(const char *) const
Return a pointer to the TTree friend whose name or alias is &#39;friendname.
Definition: TTree.cxx:5731
void GetObject(const char *namecycle, T *&ptr)
Definition: TDirectory.h:139
virtual TClass * GetValueClass() const =0
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:355
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
virtual Long64_t GetEntriesFast() const
Definition: TTree.h:384
const char * Size
Definition: TXMLSetup.cxx:55
TBuffer * fTransientBuffer
! Pointer to the current transient buffer.
Definition: TTree.h:125
virtual void Flush()
Synchronize a file&#39;s in-memory and on-disk states.
Definition: TFile.cxx:1098
virtual void Print(Option_t *option="") const
Print a summary of the tree contents.
Definition: TTree.cxx:6934
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=0, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition: TFile.cxx:2242
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:1748
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:4900
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
TIterator * fLeafIter
current leaf sub-iterator.
Definition: TTree.h:592
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:638
R__EXTERN TStyle * gStyle
Definition: TStyle.h:402
TList * fFriends
pointer to list of friend elements
Definition: TTree.h:118
void SetHistLineWidth(Width_t width=1)
Definition: TStyle.h:357
TPrincipal * Principal(const char *varexp="", const char *selection="", Option_t *option="np", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Interface to the Principal Components Analysis class.
Definition: TTree.cxx:6915
virtual Int_t Fill()
Fill all branches.
Definition: TTree.cxx:4441
Int_t GetMakeClass() const
Definition: TTree.h:414
virtual TEntryList * GetEntryList()
Returns the entry list, set to this tree.
Definition: TTree.cxx:5611
ROOT::TIOFeatures SetIOFeatures(const ROOT::TIOFeatures &)
Provide the end-user with the ability to enable/disable various experimental IO features for this TTr...
Definition: TTree.cxx:8696
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual void DropBaskets(Option_t *option="")
Loop on all branch baskets.
Definition: TBranch.cxx:659
static void SetBranchStyle(Int_t style=1)
Set the current branch style.
Definition: TTree.cxx:8238
A specialized TFileCacheRead object for a TTree.
Definition: TTreeCache.h:30
virtual TLeaf * GetLeaf(const char *branchname, const char *leafname)
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition: TTree.cxx:5944
TTree * fTree
Definition: TTree.h:168
const std::type_info * GetTypeInfo() const
Definition: TClass.h:461
static Int_t SetParallelUnzip(TTreeCacheUnzip::EParUnzipMode option=TTreeCacheUnzip::kEnable)
Static function that (de)activates multithreading unzipping.
static char DataTypeToChar(EDataType datatype)
Definition: TTree.cxx:430
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:4411
virtual void PrintValue(Int_t i=0) const
Definition: TLeaf.h:124
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:46
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
virtual Int_t GetEntries() const
Definition: TCollection.h:177
virtual TLeaf * GetLeafImpl(const char *branchname, const char *leafname)
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition: TTree.cxx:5854
virtual TList * GetListOfFriends() const
Definition: TTree.h:409
virtual Long64_t GetAutoFlush() const
Definition: TTree.h:366
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
bool Set(EIOFeatures bits)
Set a specific IO feature.
Regular expression class.
Definition: TRegexp.h:31
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition: TTree.h:109
constexpr Float_t kNEntriesResortInv
Definition: TTree.cxx:419
Int_t fMakeClass
! not zero when processing code generated by MakeClass
Definition: TTree.h:106
#define R__ASSERT(e)
Definition: TError.h:96
virtual TBasket * CreateBasket(TBranch *)
Create a basket for this tree and given branch.
Definition: TTree.cxx:3601
#define gROOT
Definition: TROOT.h:393
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3617
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:585
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
virtual Int_t WriteTObject(const TObject *obj, const char *name=0, Option_t *="", Int_t=0)
See TDirectoryFile::WriteTObject for details.
void ForceWriteInfo(TFile *file, Bool_t force=kFALSE)
Recursively mark streamer infos for writing to a file.
virtual TPrincipal * Principal(const char *varexp="", const char *selection="", Option_t *option="np", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual void SetAutoSave(Long64_t autos=-300000000)
This function may be called at the start of a program to change the default value for fAutoSave (and ...
Definition: TTree.cxx:7923
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:5404
virtual Int_t ReadKeys(Bool_t=kTRUE)
Definition: TDirectory.h:174
virtual Int_t GetOffset() const
Definition: TLeaf.h:80
Basic string class.
Definition: TString.h:125
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2816
virtual void SetAddress(void *addobj)
Point this branch at an object.
virtual Int_t MakeProxy(const char *classname, const char *macrofilename=0, const char *cutfilename=0, const char *option=0, Int_t maxUnrolling=3)
Generate a skeleton analysis class for this Tree using TBranchProxy.
Definition: TTree.cxx:6512
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor) const =0
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:168
virtual void SetTargetClass(const char *name)
Set the name of the class of the in-memory object into which the data will loaded.
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1099
static TBranch * R__FindBranchHelper(TObjArray *list, const char *branchname)
Search in the array for a branch matching the branch name, with the branch possibly expressed as a &#39;f...
Definition: TTree.cxx:4624
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:57
virtual void Browse(TBrowser *)
Browse content of the TTree.
Definition: TTree.cxx:2561
constexpr std::array< decltype(std::declval< F >)(std::declval< int >))), N > make(F f)
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition: TAttFill.h:39
virtual void StopLearningPhase()
This is the counterpart of StartLearningPhase() and can be used to stop the learning phase...
static void SetMaxTreeSize(Long64_t maxsize=100000000000LL)
Set the maximum size in bytes of a Tree file (static function).
Definition: TTree.cxx:8753
TIOFeatures provides the end-user with the ability to change the IO behavior of data written via a TT...
Definition: TIOFeatures.hxx:62
Int_t fScanField
Number of runs before prompting in Scan.
Definition: TTree.h:83
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition: TTree.cxx:3053
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
virtual TTree * CopyTree(const char *selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Copy a tree with selection.
Definition: TTree.cxx:3589
virtual void KeepCircular()
Keep a maximum of fMaxEntries in memory.
Definition: TTree.cxx:6152
TArrayD fIndexValues
Sorted index values.
Definition: TTree.h:115
void SetAutoCreated(Bool_t val)
Definition: TTreeCache.h:97
virtual EDataType GetType() const =0
constexpr Int_t kNEntriesResort
Definition: TTree.cxx:418
virtual Long64_t GetEntries(const char *)=0
Long64_t fMaxEntryLoop
Maximum number of entries to process.
Definition: TTree.h:89
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition: TTree.cxx:6058
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition: TTree.h:546
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:7191
Streamer around an arbitrary STL like container, which implements basic container functionality...
void ToHumanReadableSize(value_type bytes, Bool_t si, Double_t *coeff, const char **units)
Return the size expressed in &#39;human readable&#39; format.
Definition: StringConv.hxx:38
virtual Int_t AddBranch(TBranch *b, Bool_t subgbranches=kFALSE)
Add a branch to the list of branches to be stored in the cache this function is called by TBranch::Ge...
Definition: TTreeCache.cxx:332
virtual Int_t DeleteGlobal(void *obj)=0
virtual void SetupAddresses()
If the branch address is not set, we set all addresses starting with the top level parent branch...
Definition: TBranch.cxx:2774
virtual void SetTree(const TTree *tree)
If a list for a tree with such name and filename exists, sets it as the current sublist If not...
Iterator abstract base class.
Definition: TIterator.h:30
virtual Width_t GetLineWidth() const
Return the line width.
Definition: TAttLine.h:35
void Reset()
Definition: TCollection.h:250
void BypassStreamer(Bool_t bypass=kTRUE)
When the kBypassStreamer bit is set, the automatically generated Streamer can call directly TClass::W...
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual void Reset(Option_t *option="")
Definition: TBranchRef.cxx:187
virtual Int_t Fit(const char *formula, const char *varexp, const char *selection, Option_t *option, Option_t *goption, Long64_t nentries, Long64_t firstentry)=0
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
virtual void Refresh()
Refresh contents of this tree and its branches from the current status on disk.
Definition: TTree.cxx:7585
Width_t GetHistLineWidth() const
Definition: TStyle.h:221
if object in a list can be deleted
Definition: TObject.h:58
virtual void SetFileNumber(Int_t number=0)
Set fFileNumber to number.
Definition: TTree.cxx:8719
virtual Double_t GetMinimum(const char *columname)
Return minimum of column with name columname.
Definition: TTree.cxx:6029
virtual void Print(Option_t *option="") const
Print the TRefTable branch.
Definition: TBranchRef.cxx:159
virtual void DirectoryAutoAdd(TDirectory *)
Called by TKey and TObject::Clone to automatically add us to a directory when we are read from a file...
Definition: TTree.cxx:3689
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:3950
virtual void SetTree(TTree *tree)
Definition: TBranch.h:233
virtual void SetDirectory(TDirectory *dir)
Add reference to directory dir. dir can be 0.
static void SetRefTable(TRefTable *table)
Static function setting the current TRefTable.
Definition: TRefTable.cxx:383
Bool_t fIMTFlush
! True if we are doing a multithreaded flush.
Definition: TTree.h:139
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition: TAttMarker.h:32
virtual void StartViewer()
Start the TTreeViewer on this tree.
Definition: TTree.cxx:8965
virtual Long64_t Merge(TCollection *list, Option_t *option="")
Merge the trees in the TList into this tree.
Definition: TTree.cxx:6638
Marker Attributes class.
Definition: TAttMarker.h:19
static TVirtualTreePlayer * TreePlayer(TTree *obj)
Static function returning a pointer to a Tree player.
virtual void SetBranchFolder()
virtual Style_t GetLineStyle() const
Return the line style.
Definition: TAttLine.h:34
virtual Int_t GetEntryWithIndex(Int_t major, Int_t minor=0)
Read entry corresponding to major and minor number.
Definition: TTree.cxx:5684
TList * fAliases
List of aliases for expressions based on the tree branches.
Definition: TTree.h:112
EFromHumanReadableSize FromHumanReadableSize(std::string_view str, T &value)
Convert strings like the following into byte counts 5MB, 5 MB, 5M, 3.7GB, 123b, 456kB, 3.7GiB, 5MiB with some amount of forgiveness baked into the parsing.
Definition: StringConv.hxx:86
Long64_t GetTotBytes(Option_t *option="") const
Return total number of bytes in the branch (excluding current buffer) if option ="*" includes all sub...
Definition: TBranch.cxx:1730
virtual Long64_t DrawSelect(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual Int_t FlushBaskets() const
Write to disk all the basket that have not yet been individually written.
Definition: TTree.cxx:4947
TObject * Last() const
Return the object in the last filled slot. Returns 0 if no entries.
Definition: TObjArray.cxx:505
Bool_t fCacheDoClusterPrefetch
! true if cache is prefetching whole clusters
Definition: TTree.h:127
#define SafeDelete(p)
Definition: RConfig.h:509
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
virtual TObjArray * GetListOfBranches()
Definition: TTree.h:407
Helper class to iterate over cluster of baskets.
Definition: TTree.h:234
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition: TTree.h:121
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
Fill Area Attributes class.
Definition: TAttFill.h:19
void ImportClusterRanges(TTree *fromtree)
Appends the cluster range information stored in &#39;fromtree&#39; to this tree, including the value of fAuto...
Definition: TTree.cxx:6113
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:7838
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:2365
Bool_t IsAutoCreated() const
Definition: TTreeCache.h:85
void Class()
Definition: Class.C:29
virtual Long64_t CopyEntries(TTree *tree, Long64_t nentries=-1, Option_t *option="")
Copy nentries from given tree to this tree.
Definition: TTree.cxx:3420
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:7966
void SetHistFillColor(Color_t color=1)
Definition: TStyle.h:353
Int_t fNfill
! Local for EntryLoop
Definition: TTree.h:101
UChar_t GetFeatures() const
virtual Double_t GetValue(Int_t i=0) const
Definition: TLeaf.h:123
virtual void SetObject(const char *name, const char *title)
Change the name and title of this tree.
Definition: TTree.cxx:8790
virtual Bool_t IsWritable() const
Definition: TDirectory.h:163
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5647
virtual Bool_t Notify()
This method must be overridden to handle object notification.
Definition: TObject.cxx:506
virtual Long64_t GetReadEntry() const
Definition: TTree.h:426
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition: TTree.cxx:5021
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition: TBranch.cxx:1579
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition: TTree.cxx:6209
Bool_t fCacheUserSet
! true if the cache setting was explicitly given by user
Definition: TTree.h:128
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition: TTree.cxx:8852
virtual Long64_t GetEntry(Int_t index) const
Return value of entry at index in the list.
Definition: TEventList.cxx:222
Int_t fMaxClusterRange
! Memory allocated for the cluster range.
Definition: TTree.h:87
static Int_t GetBranchStyle()
Static function returning the current branch style.
Definition: TTree.cxx:5173
virtual Int_t BuildIndex(const char *majorname, const char *minorname="0")
Build a Tree Index (default is TTreeIndex).
Definition: TTree.cxx:2586
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:9225
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:2415
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:1934
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:5633
virtual void Show(Long64_t entry=-1, Int_t lenmax=20)
Print values of all active leaves for entry.
Definition: TTree.cxx:8891
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition: TBranch.cxx:929
TBranchRef * fBranchRef
Branch supporting the TRefTable (if any)
Definition: TTree.h:123
virtual Int_t MakeClass(const char *classname=0, Option_t *option="")
Generate a skeleton analysis class for this tree.
Definition: TTree.cxx:6351
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1638
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition: TTree.cxx:5235
TIOFeatures * fIOFeatures
virtual Int_t GetN() const
Definition: TEventList.h:56
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition: TAttMarker.h:38
Style_t GetHistFillStyle() const
Definition: TStyle.h:219
const Int_t kDoNotProcess
Definition: TBranch.h:47
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition: TTree.h:124
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Long_t GetThisOffset() const
Definition: TRealData.h:55
virtual Int_t MakeClass(const char *classname, const char *option)=0
Int_t fTimerInterval
Timer interval in milliseconds.
Definition: TTree.h:82
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition: TAttMarker.h:33
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition: TTree.cxx:1234
TDataType * GetDataType() const
Definition: TDataMember.h:74
virtual Long64_t Scan(const char *varexp="", const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)
Loop over tree entries and print entries passing selection.
Definition: TTree.cxx:7741
Long64_t fFlushedBytes
Number of auto-flushed bytes.
Definition: TTree.h:80
virtual Int_t GetLenType() const
Definition: TLeaf.h:76
TObjArray * GetListOfBranches()
Definition: TBranch.h:193
UInt_t fNEntriesSinceSorting
! Number of entries processed since the last re-sorting of branches
Definition: TTree.h:130
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:477
Specialization of TTreeCache for parallel Unzipping.
virtual TList * GetList() const
Definition: TDirectory.h:149
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:24
XFontStruct * id
Definition: TGX11.cxx:108
virtual void Delete(Option_t *option="")
Delete an object from the file.
Definition: TKey.cxx:534
virtual Double_t GetMaximum(const char *columname)
Return maximum of column with name columname.
Definition: TTree.cxx:5990
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:7624
virtual void SetAddress(void *add=0)
Definition: TLeaf.h:125
TCollection * GetListOfFolders() const
Definition: TFolder.h:55
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition: TTree.cxx:6097
std::atomic< Long64_t > fIMTZipBytes
! Zip bytes for the IMT flush baskets.
Definition: TTree.h:141
virtual void SetCacheLearnEntries(Int_t n=10)
Interface to TTreeCache to set the number of entries for the learning phase.
Definition: TTree.cxx:8431
A branch containing and managing a TRefTable for TRef autoloading.
Definition: TBranchRef.h:29
Long64_t fZipBytes
Total number of bytes in all branches after compression.
Definition: TTree.h:78
virtual TFile * GetFile() const
Definition: TDirectory.h:147
Long64_t fDebugMax
! Last entry number to debug
Definition: TTree.h:104
virtual TBranch * BranchImp(const char *branchname, const char *classname, TClass *ptrClass, void *addobj, Int_t bufsize, Int_t splitlevel)
Same as TTree::Branch() with added check that addobj matches className.
Definition: TTree.cxx:1440
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition: TObject.h:134
virtual TTree * GetTree() const
Definition: TTree.h:434
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:8635
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition: TBuffer.cxx:211
virtual Int_t GetTreeNumber() const
Definition: TTree.h:436
void UseCurrentStyle()
Replace current attributes by current style.
Definition: TTree.cxx:9237
A specialized string object used for TTree selections.
Definition: TCut.h:25
A doubly linked list.
Definition: TList.h:44
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch.
Definition: TBranch.cxx:2086
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:5062
Bool_t fCacheDoAutoInit
! true if cache auto creation or resize check is needed
Definition: TTree.h:126
Int_t GetRecordHeader(char *buf, Long64_t first, Int_t maxbytes, Int_t &nbytes, Int_t &objlen, Int_t &keylen)
Read the logical record header starting at a certain postion.
Definition: TFile.cxx:1251
Int_t GetType() const
Definition: TDataType.h:68
Int_t Fill()
Definition: TBranch.h:154
TObjArray fLeaves
Direct pointers to individual branch leaves.
Definition: TTree.h:111
Long64_t * fClusterRangeEnd
[fNClusterRange] Last entry of a cluster range.
Definition: TTree.h:94
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition: TAttLine.h:40
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1942
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
This class provides a simple interface to execute the same task multiple times in parallel...
Int_t fNClusterRange
Number of Cluster range in addition to the one defined by &#39;AutoFlush&#39;.
Definition: TTree.h:86
virtual Long64_t GetEntryNumber(Long64_t entry) const
Return entry number corresponding to entry.
Definition: TTree.cxx:5622
Int_t fN
Definition: TArray.h:38
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition: TTree.h:114
virtual Int_t GetLen() const
Return the number of effective elements of this leaf.
Definition: TLeaf.cxx:307
virtual Long64_t GetAutoSave() const
Definition: TTree.h:367
void SetParentClass(TClass *clparent)
virtual void SetEntryRange(Long64_t emin, Long64_t emax)
Set the minimum and maximum entry number to be processed this information helps to optimize the numbe...
Int_t GetReadBasket() const
Definition: TBranch.h:183
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:9274
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition: TTree.cxx:8676
virtual void SetOffset(Int_t offset=0)
Definition: TBranch.h:231
virtual Long64_t Process(const char *filename, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0)=0
virtual void UpdateFormulaLeaves()=0
virtual Int_t DropBranch(TBranch *b, Bool_t subbranches=kFALSE)
Remove a branch to the list of branches to be stored in the cache this function is called by TBranch:...
Definition: TTreeCache.cxx:484
void SetHistFillStyle(Style_t styl=0)
Definition: TStyle.h:355
void SetCompressionSettings(Int_t settings=1)
Set compression settings.
Definition: TBranch.cxx:2293
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
Long64_t fChainOffset
! Offset of 1st entry of this Tree in a TChain
Definition: TTree.h:97
~TFriendLock()
Restore the state of tree the same as before we set the lock.
Definition: TTree.cxx:511
Long64_t * fClusterSize
[fNClusterRange] Number of entries in each cluster for a given range.
Definition: TTree.h:95
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition: TAttFill.h:37
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
void TFriendElement__SetTree(TTree *tree, TList *frlist)
Set the fTree member for all friend elements.
Definition: TTree.cxx:9038
auto * a
Definition: textangle.C:12
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition: TTree.cxx:5667
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition: TTree.h:119
TClass * GetActualClass(const void *object) const
Return a pointer the the real class of the object.
Definition: TClass.cxx:2527
virtual TIterator * MakeIterator(Bool_t dir=kIterForward) const =0
TTree * GetTree() const
Definition: TTreeCache.h:84
virtual TObject * RemoveAt(Int_t idx)
Remove object at index idx.
Definition: TObjArray.cxx:678
virtual Int_t ReadTObject(TObject *, const char *)
Definition: TDirectory.h:175
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:818
Long64_t fReadEntry
! Number of the entry being processed
Definition: TTree.h:98
virtual TVirtualIndex * GetTreeIndex() const
Definition: TTree.h:435
virtual Bool_t HasPointers() const =0
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
Int_t GetWriteBasket() const
Definition: TBranch.h:185
virtual ~TTree()
Destructor.
Definition: TTree.cxx:872
TDataMember * GetDataMember() const
Definition: TRealData.h:53
Collection abstract base class.
Definition: TCollection.h:63
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition: TClass.cxx:5140
TList * fUserInfo
pointer to a list of user objects associated to this Tree
Definition: TTree.h:120
TObjArray fBranches
List of Branches.
Definition: TTree.h:110
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2343
unsigned int UInt_t
Definition: RtypesCore.h:42
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition: TTree.cxx:5246
virtual Long64_t GetN() const =0
virtual Long64_t GetEntry(Int_t index)
Return the number of the entry #index of this TEntryList in the TTree or TChain See also Next()...
Definition: TEntryList.cxx:657
Ssiz_t Length() const
Definition: TString.h:386
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition: TFile.cxx:1410
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition: TDirectory.cxx:190
virtual TLeaf * GetLeafCount() const
Definition: TLeaf.h:72
Manages buffers for branches of a Tree.
Definition: TBasket.h:34
virtual void * GetValuePointer() const
Definition: TLeaf.h:81
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1080
Int_t GetMaxBaskets() const
Definition: TBranch.h:195
A TEventList object is a list of selected events (entries) in a TTree.
Definition: TEventList.h:31
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition: TTree.cxx:4744
The TRealData class manages the effective list of all data members for a given class.
Definition: TRealData.h:30
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all leaves of entry and return total number of bytes read.
Definition: TBranch.cxx:1244
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:365
TArrayI fIndex
Index of sorted values.
Definition: TTree.h:116
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition: TAttMarker.h:40
static void SetLearnEntries(Int_t n=10)
Static function to set the number of entries to be used in learning mode The default value for n is 1...
ROOT::ESTLType GetCollectionType() const
Return the &#39;type&#39; of the STL the TClass is representing.
Definition: TClass.cxx:2805
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:354
Bool_t fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition: TTree.h:129
Option_t * GetOption() const
Returns the object option stored in the list.
Definition: TTree.cxx:9375
virtual TBranchRef * GetBranchRef() const
Definition: TTree.h:369
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4679
void SetName(const char *name)
Definition: TCollection.h:202
virtual void ResetBranchAddress(TBranch *)
Tell all of our branches to set their addresses to zero.
Definition: TTree.cxx:7712
ROOT::TIOFeatures GetIOFeatures() const
Returns the current set of IO settings.
Definition: TTree.cxx:5830
Bool_t fDirection
iteration direction
Definition: TTree.h:594
TEventList * fEventList
! Pointer to event selection list (if one)
Definition: TTree.h:113
TString fName
Definition: TNamed.h:32
virtual TBranch * Bronch(const char *name, const char *classname, void *addobj, Int_t bufsize=32000, Int_t splitlevel=99)
Create a new TTree BranchElement.
Definition: TTree.cxx:2264
virtual const char * GetTreeName() const
virtual Bool_t GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition: TTree.cxx:5158
if object destructor must call RecursiveRemove()
Definition: TObject.h:60
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition: TAttMarker.h:41
Long64_t fMaxEntries
Maximum number of entries in case of circular buffers.
Definition: TTree.h:88
void AddClone(TTree *)
Add a cloned tree to our list of trees to be notified whenever we change our branch addresses or when...
Definition: TTree.cxx:1146
void SetIOFeatures(TIOFeatures &features)
Definition: TBranch.h:229
virtual void KeepCircular(Long64_t maxEntries)
keep a maximum of fMaxEntries in memory
Definition: TBranch.cxx:1793
Each class (see TClass) has a linked list of its base class(es).
Definition: TBaseClass.h:33
char GetNewlineValue(std::istream &inputStream)
Determine which newline this file is using.
Definition: TTree.cxx:7261
virtual TObjLink * FirstLink() const
Definition: TList.h:108
A Branch for the case of an object.
virtual Long64_t GetBasketSeek(Int_t basket) const
Return address of basket in the file.
Definition: TBranch.cxx:1187
#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:1069
void InitializeBranchLists(bool checkLeafCount)
Divides the top-level branches into two vectors: (i) branches to be processed sequentially and (ii) b...
Definition: TTree.cxx:5543
Long64_t fAutoSave
Autosave tree when fAutoSave entries written or -fAutoSave (compressed) bytes produced.
Definition: TTree.h:91
const Bool_t kFALSE
Definition: RtypesCore.h:88
virtual void SaveSelf(Bool_t=kFALSE)
Definition: TDirectory.h:181
virtual void SetBasketSize(Int_t buffsize)
Set the basket size The function makes sure that the basket size is greater than fEntryOffsetlen.
Definition: TBranch.cxx:2217
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:2789
virtual Color_t GetLineColor() const
Return the line color.
Definition: TAttLine.h:33
virtual void SetDebug(Int_t level=1, Long64_t min=0, Long64_t max=9999999)
Set the debug level and the debug range.
Definition: TTree.cxx:8494
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:7128
static unsigned int total
static const Ssiz_t kNPOS
Definition: TString.h:246
TString & Remove(Ssiz_t pos)
Definition: TString.h:619
long Long_t
Definition: RtypesCore.h:50
int Ssiz_t
Definition: RtypesCore.h:63
virtual void DropBuffers(Int_t nbytes)
Drop branch buffers to accommodate nbytes below MaxVirtualsize.
Definition: TTree.cxx:4373
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:8733
virtual void SetWeight(Double_t w=1, Option_t *option="")
Set tree weight.
Definition: TTree.cxx:8880
Color_t GetHistFillColor() const
Definition: TStyle.h:217
Version_t GetClassVersion() const
Definition: TClass.h:391
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2251
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition: TTree.cxx:602
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns an array iterator.
Definition: TObjArray.cxx:633
virtual void SetDirectory(TDirectory *dir)
Change the tree&#39;s directory.
Definition: TTree.cxx:8532
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:6301
virtual void SetEstimate(Long64_t n)=0
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
virtual void Print(Option_t *option="") const
Print cache statistics.
Definition: TTreeCache.cxx:996
Long64_t fMaxVirtualSize
Maximum total size of buffers kept in memory.
Definition: TTree.h:90
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
virtual Int_t GetMaximum() const
Definition: TLeaf.h:77
#define ClassImp(name)
Definition: Rtypes.h:359
virtual void StartViewer(Int_t ww, Int_t wh)=0
virtual void SetEntryList(TEntryList *list, Option_t *opt="")
Set an EntryList.
Definition: TTree.cxx:8612
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator. Does NOT copy the &#39;cursor&#39; location!
Definition: TTree.cxx:9313
virtual void ResetAddress()
Reset the address of the branch.
Definition: TBranch.cxx:2139
virtual TKey * GetKey(const char *, Short_t=9999) const
Definition: TDirectory.h:148
double Double_t
Definition: RtypesCore.h:55
virtual void Clear(Option_t *option="")
Clear entries in the TRefTable.
Definition: TBranchRef.cxx:95
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:875
static TRefTable * GetRefTable()
Static function returning the current TRefTable.
Definition: TRefTable.cxx:287
Long64_t GetCacheAutoSize(Bool_t withDefault=kFALSE) const
Used for automatic sizing of the cache.
Definition: TTree.cxx:5185
void SetHistLineStyle(Style_t styl=0)
Definition: TStyle.h:356
Long64_t fTotBytes
Total number of bytes in all branches before compression.
Definition: TTree.h:77
virtual void WaitFinishPrefetch()
Data member is a pointer to an array of basic types.
Definition: TLeaf.h:58
Color_t GetHistLineColor() const
Definition: TStyle.h:218
std::vector< TBranch * > fSeqBranches
! Branches to be processed sequentially when IMT is on
Definition: TTree.h:132
Describe directory structure in memory.
Definition: TDirectory.h:34
virtual void SetPerfStats(TVirtualPerfStats *perf)
Set perf stats.
Definition: TTree.cxx:8835
std::vector< std::pair< Long64_t, TBranch * > > fSortedBranches
! Branches to be processed in parallel when IMT is on, sorted by average task time ...
Definition: TTree.h:131
TDirectory * GetDirectory() const
Definition: TTree.h:381
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any. ...
static void TBranch__SetTree(TTree *tree, TObjArray &branches)
Set the fTree member for all branches and sub branches.
Definition: TTree.cxx:9014
void SortBranchesByTime()
Sorts top-level branches by the last average task time recorded per branch.
Definition: TTree.cxx:5591
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
virtual Int_t GetBufferSize() const
unsigned long long ULong64_t
Definition: RtypesCore.h:70
virtual Long64_t ReadFile(const char *filename, const char *branchDescriptor="", char delimiter=' ')
Create or simply read branches from filename.
Definition: TTree.cxx:7242
TList * GetListOfRealData() const
Definition: TClass.h:418
Bool_t HasDataMemberInfo() const
Definition: TClass.h:378
TNamed()
Definition: TNamed.h:36
Long64_t fAutoFlush
Auto-flush tree when fAutoFlush entries written or -fAutoFlush (compressed) bytes produced...
Definition: TTree.h:92
Int_t GetNbytes() const
Definition: TKey.h:82
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition: TTree.cxx:7722
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:355
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
TCanvas * style()
Definition: style.C:1
int nentries
Definition: THbookFile.cxx:89
A TRefTable maintains the association between a referenced object and the parent object supporting th...
Definition: TRefTable.h:35
EDataType
Definition: TDataType.h:28
virtual Color_t GetFillColor() const
Return the fill area color.
Definition: TAttFill.h:30
Int_t fDefaultEntryOffsetLen
Initial Length of fEntryOffset table in the basket buffers.
Definition: TTree.h:85
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:570
static constexpr double s
#define R__LOCKGUARD(mutex)
void Browse(TBrowser *b)
Browse this collection (called by TBrowser).
TObjArray * GetListOfLeaves()
Definition: TBranch.h:194
Long64_t fEstimate
Number of entries to estimate histogram limits.
Definition: TTree.h:93
Int_t BufferSize() const
Definition: TBuffer.h:94
static void SetUnzipRelBufferSize(Float_t relbufferSize)
static function: Sets the unzip relatibe buffer size
UInt_t fMethodBit
Definition: TTree.h:169
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition: TTree.h:165
virtual Bool_t Enter(Long64_t entry, TTree *tree=0)
Add entry #entry to the list.
Definition: TEntryList.cxx:562
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2887
virtual Int_t SetBufferSize(Int_t buffersize)
Change the underlying buffer size of the cache.
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache .
Definition: TTree.cxx:8254
Int_t fDebug
! Debug level
Definition: TTree.h:102
EOnIndexError
Definition: TTree.cxx:3317
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:8280
double Stat_t
Definition: RtypesCore.h:73
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition: TAttLine.h:42
virtual Long64_t GetEntries() const
Definition: TTree.h:382
Int_t GetKeylen() const
Definition: TKey.h:80
Bool_t IsPersistent() const
Definition: TDataMember.h:89
Bool_t IsNull() const
Definition: TString.h:383
TClass * GetClass() const
Definition: TClonesArray.h:56
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition: TNamed.cxx:74
virtual void SetBasketSize(const char *bname, Int_t buffsize=16000)
Set a branch&#39;s basket size.
Definition: TTree.cxx:7939
virtual TFile * GetFile()
Return pointer to TFile containing this friend TTree.
virtual TBranch * BranchRef()
Build the optional branch supporting the TRefTable.
Definition: TTree.cxx:2188
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data)...
Definition: TTree.cxx:7681
virtual Bool_t SetAlias(const char *aliasName, const char *aliasFormula)
Set a tree variable alias.
Definition: TTree.cxx:7783
Int_t fFileNumber
! current file number (if file extensions)
Definition: TTree.h:107
Mother of all ROOT objects.
Definition: TObject.h:37
TObjArray * GetElements() const
Int_t fUpdate
Update frequency for EntryLoop.
Definition: TTree.h:84
virtual void ReadValue(std::istream &, Char_t=' ')
Definition: TLeaf.h:96
Bool_t IsReading() const
Definition: TStyle.h:274
virtual Long64_t GetEND() const
Definition: TFile.h:202
A Branch handling STL collection of pointers (vectors, lists, queues, sets and multisets) while stori...
Definition: TBranchSTL.h:22
static void * ReAlloc(void *vp, size_t size)
Reallocate (i.e.
Definition: TStorage.cxx:183
virtual Int_t Branch(TCollection *list, Int_t bufsize=32000, Int_t splitlevel=99, const char *name="")
Create one branch for each element in the collection.
Definition: TTree.cxx:1701
TDirectory * fOutputDirectory
virtual void SetEntryOffsetLen(Int_t len, Bool_t updateSubBranches=kFALSE)
Update the default value for the branch&#39;s fEntryOffsetLen if and only if it was already non zero (and...
Definition: TBranch.cxx:2309
virtual Long64_t Scan(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)=0
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:401
virtual void SetFile(TFile *file=0)
Set file where this branch writes/reads its buffers.
Definition: TBranch.cxx:2351
Long64_t fEntries
Number of entries.
Definition: TTree.h:75
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5659
TList * fClones
! List of cloned trees which share our addresses
Definition: TTree.h:122
virtual void Refresh(TBranch *b)
Refresh this branch using new information in b This function is called by TTree::Refresh.
Definition: TBranch.cxx:1996
Long64_t GetEntries() const
Definition: TBranch.h:198
Style_t GetHistLineStyle() const
Definition: TStyle.h:220
virtual Int_t MakeSelector(const char *selector=0, Option_t *option="")
Generate skeleton selector class for this tree.
Definition: TTree.cxx:6566
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:964
virtual Long64_t GetTotBytes() const
Definition: TTree.h:433
Class implementing or helping the various TTree cloning method.
Definition: TTreeCloner.h:38
virtual Bool_t cd(const char *path=0)
Change current directory to "this" directory.
Definition: TDirectory.cxx:497
virtual Int_t DropBuffers()
Drop buffers of this basket if it is not the current basket.
Definition: TBasket.cxx:163
ROOT::ESTLType IsSTLContainer()
Return which type (if any) of STL container the data member is.
Definition: TBaseClass.cxx:101
Abstract base class defining the interface for the plugins that implement Draw, Scan, Process, MakeProxy, etc.
A Branch for the case of an array of clone objects.
Definition: TBranchClones.h:29
virtual void Add(TObject *obj)
Definition: TList.h:87
auto * l
Definition: textangle.C:4
#define R__unlikely(expr)
Definition: RConfig.h:554
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition: TROOT.cxx:584
TClusterIterator(TTree *tree, Long64_t firstEntry)
Regular constructor.
Definition: TTree.cxx:528
virtual void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition: TList.cxx:760
Definition: file.py:1
Int_t GetClassVersion()
const char * GetArrayIndex() const
If the data member is pointer and has a valid array size in its comments GetArrayIndex returns a stri...
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:200
virtual void Reset(Option_t *option="")
Reset a Branch.
Definition: TBranch.cxx:2045
A TFriendElement TF describes a TTree object TF in a file.
virtual Long64_t GetZipBytes() const
Definition: TTree.h:461
virtual TObject * Next()=0
virtual const char * GetMinorName() const =0
Iterator on all the leaves in a TTree and its friend.
Definition: TTree.h:588
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:2272
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:7554
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:1819
#define snprintf
Definition: civetweb.c:822
TTree * GetTree() const
Definition: TBranch.h:199
#define gPad
Definition: TVirtualPad.h:285
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:522
virtual void SetCircular(Long64_t maxEntries)
Enable/Disable circularity for this tree.
Definition: TTree.cxx:8458
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
Int_t GetBufferSize() const
Definition: TBasket.h:110
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition: TTree.cxx:7650
virtual const char * GetMajorName() const =0
Definition: tree.py:1
std::atomic< Long64_t > fTotalBuffers
! Total number of bytes in branch buffers
Definition: TTree.h:99
TFileCacheRead * GetCacheRead(TObject *tree=0) const
Return a pointer to the current read cache.
Definition: TFile.cxx:1214
virtual char * GetAddress() const
Definition: TBranch.h:161
TObject * fNotify
! Object to be notified when loading a Tree
Definition: TTree.h:108
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition: TTree.cxx:8397
void Add(TObject *obj)
Definition: TObjArray.h:73
Double_t Atof() const
Return floating-point value contained in string.
Definition: TString.cxx:2041
A TTree object has a header with a name and a title.
Definition: TTree.h:70
#define gDirectory
Definition: TDirectory.h:213
TVirtualIndex * fTreeIndex
Pointer to the tree Index (if any)
Definition: TTree.h:117
TFriendLock & operator=(const TFriendLock &)
Assignment operator.
Definition: TTree.cxx:498
Int_t SetBranchAddressImp(TBranch *branch, void *addr, TBranch **ptr)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:8023
virtual TVirtualIndex * BuildIndex(const TTree *T, const char *majorname, const char *minorname)=0
void ResetBit(UInt_t f)
Definition: TObject.h:171
unsigned char UChar_t
Definition: RtypesCore.h:34
virtual void SetDefaultEntryOffsetLen(Int_t newdefault, Bool_t updateExisting=kFALSE)
Update the default value for the branch&#39;s fEntryOffsetLen.
Definition: TTree.cxx:8506
virtual TObject ** GetObjectRef(const TObject *obj) const =0
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1843
TObject * Next()
Go the next friend element.
Definition: TTree.cxx:9336
Definition: first.py:1
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition: TAttMarker.h:31
virtual void DropBaskets()
Remove some baskets from memory.
Definition: TTree.cxx:4360
Int_t FlushBaskets()
Flush to disk all the baskets of this branch and any of subbranches.
Definition: TBranch.cxx:1030
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:5838
static Long64_t fgMaxTreeSize
Maximum size of a file containing a Tree.
Definition: TTree.h:135
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition: TAttFill.h:31
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
virtual 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:1435
virtual Long64_t SetEntries(Long64_t n=-1)
Change number of entries in the tree.
Definition: TTree.cxx:8577
R__EXTERN TInterpreter * gCling
Definition: TInterpreter.h:528
TBranch * GetBranch() const
Definition: TLeaf.h:71
virtual void Compress()
Remove empty slots from array.
Definition: TObjArray.cxx:333
virtual TFile * ChangeFile(TFile *file)
Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize.
Definition: TTree.cxx:2676
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
static TTree * MergeTrees(TList *list, Option_t *option="")
Static function merging the trees in the TList into a new tree.
Definition: TTree.cxx:6595
virtual Int_t GetSize() const
Definition: TCollection.h:180
A TTree is a list of TBranches.
Definition: TBranch.h:59
virtual const char * GetName() const
Returns name of object.
Definition: TRealData.h:52
A TSelector object is used by the TTree::Draw, TTree::Scan, TTree::Process to navigate in a TTree and...
Definition: TSelector.h:33
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
void SetHistLineColor(Color_t color=1)
Definition: TStyle.h:354
Bool_t IsaPointer() const
Return true if data member is a pointer.
virtual void Print(Option_t *option="") const
Print TBranch parameters.
Definition: TBranch.cxx:1848
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
A List of entry numbers in a TTree or TChain.
Definition: TEntryList.h:25
virtual Int_t AddBranchToCache(const char *bname, Bool_t subbranches=kFALSE)
Add branch with name bname to the Tree cache.
Definition: TTree.cxx:986
const Bool_t kTRUE
Definition: RtypesCore.h:87
Int_t fPacketSize
! Number of entries in one packet for parallel root
Definition: TTree.h:100
void Set(Int_t n)
Set size of this array to n doubles.
Definition: TArrayD.cxx:106
const Int_t n
Definition: legend1.C:16
TString & String()
Definition: TString.h:110
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:7176
Line Attributes class.
Definition: TAttLine.h:18
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor) const =0
Bool_t IsObject() const
Definition: TRealData.h:56
TIOFeatures fIOFeatures
IO features to define for newly-written baskets and branches.
Definition: TTree.h:105
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Definition: TMath.h:1092
static constexpr Long64_t kMaxEntries
Definition: TTree.h:206
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1652
char name[80]
Definition: TGX11.cxx:109
TFriendLock(const TFriendLock &)
Copy constructor.
Definition: TTree.cxx:488
virtual void SetObject(void *objadd)
Set object this branch is pointing to.
Definition: TBranch.cxx:2424
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual const char * GetName() const
Return name of this collection.
virtual Long64_t GetEntriesFriend() const
Return pointer to the 1st Leaf named name in any Branch of this Tree or any branch in the list of fri...
Definition: TTree.cxx:5279
virtual void SetName(const char *name)
Change the name of this tree.
Definition: TTree.cxx:8761
Int_t GetCompressionSettings() const
Definition: TFile.h:378
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:571
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual void PrintCacheStats(Option_t *option="") const
Print statistics about the TreeCache for this tree.
Definition: TTree.cxx:7050
void MoveReadCache(TFile *src, TDirectory *dir)
Move a cache from a file to the current file in dir.
Definition: TTree.cxx:6733
virtual void CopyAddresses(TTree *, Bool_t undo=kFALSE)
Set branch addresses of passed tree equal to ours.
Definition: TTree.cxx:3213
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:408
static void ResetCount()
Static function resetting fgCount.
Definition: TBranch.cxx:2162
Long64_t fSavedBytes
Number of autosaved bytes.
Definition: TTree.h:79
Long64_t fCacheSize
! Maximum size of file buffers
Definition: TTree.h:96
virtual const char * GetFriendAlias(TTree *) const
If the &#39;tree&#39; is a friend, this method returns its alias name.
Definition: TTree.cxx:5788
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4783
Int_t GetNleaves() const
Definition: TBranch.h:196
virtual Long64_t AutoSave(Option_t *option="")
AutoSave tree header every fAutoSave bytes.
Definition: TTree.cxx:1386
const char * Data() const
Definition: TString.h:345
std::atomic< Long64_t > fIMTTotBytes
! Total bytes for the IMT flush baskets
Definition: TTree.h:140