Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TChain.cxx
Go to the documentation of this file.
1// @(#)root/tree:$Id$
2// Author: Rene Brun 03/02/97
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/** \class TChain
13\ingroup tree
14
15A chain is a collection of files containing TTree objects.
16When the chain is created, the first parameter is the default name
17for the Tree to be processed later on.
18
19Enter a new element in the chain via the TChain::Add function.
20Once a chain is defined, one can use the normal TTree functions
21to Draw,Scan,etc.
22
23Use TChain::SetBranchStatus to activate one or more branches for all
24the trees in the chain.
25*/
26
27#include "TChain.h"
29
30#include <iostream>
31#include <cfloat>
32#include <string>
33
34#include "TBranch.h"
35#include "TBrowser.h"
36#include "TBuffer.h"
37#include "TChainElement.h"
38#include "TClass.h"
39#include "TColor.h"
40#include "TCut.h"
41#include "TError.h"
42#include "TFile.h"
43#include "TFileInfo.h"
44#include "TFriendElement.h"
45#include "TLeaf.h"
46#include "TList.h"
47#include "TObjString.h"
48#include "TPluginManager.h"
49#include "TROOT.h"
50#include "TRegexp.h"
51#include "TSelector.h"
52#include "TSystem.h"
53#include "TTree.h"
54#include "TTreeCache.h"
55#include "TUrl.h"
56#include "TVirtualIndex.h"
57#include "TEventList.h"
58#include "TEntryList.h"
59#include "TEntryListFromFile.h"
60#include "TFileStager.h"
61#include "TFilePrefetch.h"
62#include "TVirtualMutex.h"
63#include "TVirtualPerfStats.h"
64#include "strlcpy.h"
65#include "snprintf.h"
66
67#include <string_view>
68#include "ROOT/StringUtils.hxx"
69
70////////////////////////////////////////////////////////////////////////////////
71/// Default constructor.
72
74 : TTree(), fTreeOffsetLen(100), fNtrees(0), fTreeNumber(-1), fTreeOffset(nullptr), fCanDeleteRefs(false), fTree(nullptr),
75 fFile(nullptr), fFiles(nullptr), fStatus(nullptr), fGlobalRegistration(mode == kWithGlobalRegistration)
76{
79 fStatus = new TList();
80 fTreeOffset[0] = 0;
82 gROOT->GetListOfSpecials()->Add(this);
83 }
84 fFile = nullptr;
85 fDirectory = nullptr;
86
88 // Add to the global list
89 gROOT->GetListOfDataSets()->Add(this);
90
91 // Make sure we are informed if the TFile is deleted.
93 gROOT->GetListOfCleanups()->Add(this);
94 }
95}
96
97////////////////////////////////////////////////////////////////////////////////
98/// Create a chain.
99///
100/// A TChain is a collection of TFile objects.
101/// the first parameter "name" is the name of the TTree object
102/// in the files added with Add.
103/// Use TChain::Add to add a new element to this chain.
104///
105/// In case the Tree is in a subdirectory, do, eg:
106/// ~~~ {.cpp}
107/// TChain ch("subdir/treename");
108/// ~~~
109/// Example:
110/// Suppose we have 3 files f1.root, f2.root and f3.root. Each file
111/// contains a TTree object named "T".
112/// ~~~ {.cpp}
113/// TChain ch("T"); creates a chain to process a Tree called "T"
114/// ch.Add("f1.root");
115/// ch.Add("f2.root");
116/// ch.Add("f3.root");
117/// ch.Draw("x");
118/// ~~~
119/// The Draw function above will process the variable "x" in Tree "T"
120/// reading sequentially the 3 files in the chain ch.
121///
122/// The TChain data structure:
123///
124/// Each TChainElement has a name equal to the tree name of this TChain
125/// and a title equal to the file name. So, to loop over the
126/// TFiles that have been added to this chain:
127/// ~~~ {.cpp}
128/// TObjArray *fileElements=chain->GetListOfFiles();
129/// TIter next(fileElements);
130/// TChainElement *chEl=0;
131/// while (( chEl=(TChainElement*)next() )) {
132/// TFile f(chEl->GetTitle());
133/// ... do something with f ...
134/// }
135/// ~~~
136
137TChain::TChain(const char *name, const char *title, Mode mode)
138 : TTree(name, title, /*splitlevel*/ 99, nullptr), fTreeOffsetLen(100), fNtrees(0), fTreeNumber(-1), fTreeOffset(nullptr),
139 fCanDeleteRefs(false), fTree(nullptr), fFile(nullptr), fFiles(nullptr), fStatus(nullptr),
140 fGlobalRegistration(mode == kWithGlobalRegistration)
141{
142 //
143 //*-*
144
147 fStatus = new TList();
148 fTreeOffset[0] = 0;
149 fFile = nullptr;
150
153
154 // Add to the global lists
155 gROOT->GetListOfSpecials()->Add(this);
156 gROOT->GetListOfDataSets()->Add(this);
157
158 // Make sure we are informed if the TFile is deleted.
159 gROOT->GetListOfCleanups()->Add(this);
160 }
161}
162
163////////////////////////////////////////////////////////////////////////////////
164/// Destructor.
165
167{
168 bool rootAlive = gROOT && !gROOT->TestBit(TObject::kInvalidObject);
169
172 gROOT->GetListOfCleanups()->Remove(this);
173 }
174
175 fStatus->Delete();
176 delete fStatus;
177 fStatus = nullptr;
178 fFiles->Delete();
179 delete fFiles;
180 fFiles = nullptr;
181
182 //first delete cache if exists
183 auto tc = fFile && fTree ? fTree->GetReadCache(fFile) : nullptr;
184 if (tc) {
185 delete tc;
186 fFile->SetCacheRead(nullptr, fTree);
187 }
188
189 delete fFile;
190 fFile = nullptr;
191 // Note: We do *not* own the tree.
192 fTree = nullptr;
193 delete[] fTreeOffset;
194 fTreeOffset = nullptr;
195
196 // Remove from the global lists
199 gROOT->GetListOfSpecials()->Remove(this);
200 gROOT->GetListOfDataSets()->Remove(this);
201 }
202
203 // This is the same as fFile, don't delete it a second time.
204 fDirectory = nullptr;
205}
206
207////////////////////////////////////////////////////////////////////////////////
208/// Add all files referenced by the passed chain to this chain.
209/// The function returns the total number of files connected.
210
212{
213 if (!chain) return 0;
214
215 // Check for enough space in fTreeOffset.
216 if ((fNtrees + chain->GetNtrees()) >= fTreeOffsetLen) {
217 fTreeOffsetLen += 2 * chain->GetNtrees();
219 for (Int_t i = 0; i <= fNtrees; i++) {
220 trees[i] = fTreeOffset[i];
221 }
222 delete[] fTreeOffset;
224 }
225 chain->GetEntries(); //to force the computation of nentries
226 TIter next(chain->GetListOfFiles());
227 Int_t nf = 0;
228 TChainElement* element = nullptr;
229 while ((element = (TChainElement*) next())) {
230 Long64_t nentries = element->GetEntries();
233 } else {
235 }
236 fNtrees++;
238 TChainElement* newelement = new TChainElement(element->GetName(), element->GetTitle());
239 newelement->SetPacketSize(element->GetPacketSize());
240 newelement->SetNumberEntries(nentries);
242 nf++;
243 }
244
245 return nf;
246}
247
248////////////////////////////////////////////////////////////////////////////////
249/// \brief Add a new file to this chain.
250///
251/// \param[in] name The path to the file to be added. See below for details.
252/// \param[in] nentries Number of entries in the file. This can be an estimate
253/// or queried from the file. See below for details.
254/// \returns There are different possible return values:
255/// - If nentries>0 (including the default of TTree::kMaxEntries) and no
256/// wildcarding is used, ALWAYS returns 1 irrespective of whether the file
257/// exists or contains the correct tree.
258/// - If wildcarding is used, regardless of the value of \p nentries, returns
259/// the number of files matching the name irrespective of whether they contain
260/// the correct tree.
261/// - If nentries<=0 and wildcarding is not used, returns 1 if the file
262/// exists and contains the correct tree and 0 otherwise.
263///
264/// <h4>Details of the name parameter</h4>
265/// There are two sets of formats accepted for the parameter \p name . The first
266/// one is:
267///
268/// ~~~{.cpp}
269/// [//machine]/path/file_name[?[query][#tree_name]]
270/// or [//machine]/path/file_name.root[.oext][/tree_name]
271/// ~~~
272///
273/// Note the following:
274/// - If the \p tree_name part is missing, it will be assumed that
275/// the file contains a tree with the same name as the chain.
276/// - Tagging the name of the tree with a slash (e.g. \p /tree_name ) is only
277/// supported for backward compatibility; it requires the file name to contain
278/// the string '.root' and its use is deprecated. Instead, use the form
279/// \p ?#%tree_name (that is an "?" followed by an empty query), for example:
280/// ~~~{.cpp}
281/// TChain c;
282/// // DO NOT DO THIS
283/// // c.Add("myfile.root/treename");
284/// // DO THIS INSTEAD
285/// c.Add("myfile.root?#treename");
286/// ~~~
287/// - Wildcard treatment is triggered by any of the special characters:
288/// <b>[]*?</b> which may be used in the file name or subdirectory name,
289/// eg. specifying "xxx*.root" adds all files starting with xxx in the
290/// current file system directory and "*/*.root" adds all the files in the
291/// current subdirectories (but not in the subsubdirectories).
292///
293/// The second format accepted for \p name may have the form of a URL, e.g.:
294///
295/// ~~~ {.cpp}
296/// root://machine/path/file_name[?[query][#tree_name]]
297/// or root://machine/path/file_name
298/// or root://machine/path/file_name.root[.oext]/tree_name
299/// or root://machine/path/file_name.root[.oext]/tree_name?query
300/// ~~~
301///
302/// Note the following:
303/// - The optional "query" token is to be interpreted by the remote server.
304/// - Wildcards may be supported in URLs, depending on the protocol plugin and
305/// the remote server.
306/// - \p http or \p https URLs can contain a query identifier without
307/// \p tree_name, but generally URLs can not be written with them because of
308/// ambiguity with the wildcard character. (Also see the documentation for
309/// TChain::AddFile, which does not support wildcards but allows the URL name
310/// to contain a query).
311/// - The rules for tagging the name of the tree in the file are the same as
312/// in the format above.
313///
314/// <h4>Details of the nentries parameter</h4>
315/// Depending on the value of the parameter, the number of entries in the file
316/// is retrieved differently:
317/// - If <tt>nentries <= 0</tt>, the file is connected and the tree header read
318/// in memory to get the number of entries.
319/// - If <tt>nentries > 0</tt>, the file is not connected, \p nentries is
320/// assumed to be the number of entries in the file. In this case, no check is
321/// made that the file exists and that the corresponding tree exists as well.
322/// This second mode is interesting in case the number of entries in the file
323/// is already stored in a run data base for example.
324/// - If <tt>nentries == TTree::kMaxEntries</tt> (default), the file is not
325/// connected. The number of entries in each file will be read only when the
326/// file will need to be connected to read an entry. This option is the
327/// default and very efficient if one processes the chain sequentially. Note
328/// that in case TChain::GetEntry(entry) is called and entry refers to an
329/// entry in the 3rd file, for example, this forces the tree headers in the
330/// first and second file to be read to find the number of entries in these
331/// files. Note that calling TChain::GetEntriesFast after having
332/// created a chain with this default returns TTree::kMaxEntries ! Using
333/// TChain::GetEntries instead will force all the tree headers in the chain to
334/// be read to get the number of entries in each tree.
335///
336/// <h4>The %TChain data structure</h4>
337/// Each element of the chain is a TChainElement object. It has a name equal to
338/// the tree name of this chain (or the name of the specific tree in the added
339/// file if it was explicitly tagged) and a title equal to the file name. So, to
340/// loop over the files that have been added to this chain:
341/// ~~~ {.cpp}
342/// TObjArray *fileElements=chain->GetListOfFiles();
343/// for (TObject *op: *fileElements) {
344/// auto chainElement = static_cast<TChainElement *>(op);
345/// TFile f{chainElement->GetTitle()};
346/// TTree *tree = f.Get<TTree>(chainElement->GetName());
347/// // Do something with the file or the tree
348/// }
349/// ~~~
350///
351/// \note To add all the files of another \p TChain to this one, use
352/// TChain::Add(TChain* chain).
353
354Int_t TChain::Add(const char *name, Long64_t nentries /* = TTree::kMaxEntries */)
355{
358
359 // Special case: ? used for query string AND as wildcard in the filename.
360 // In this case, everything after the first ? is parsed as query/suffix
361 // string in ParseTreeFilename. We assume that everything until the last
362 // occurrence of .root should be part of the basename so we remove it
363 // from the suffix and add it back to the basename.
364 // See: https://github.com/root-project/root/issues/10239
365 static const char *dotr = ".root";
366 static Ssiz_t dotrl = strlen(dotr);
367 // Find the last one
369 Ssiz_t dotrIdx = suffix.Index(dotr);
370 while (dotrIdx != kNPOS) {
372 dotrIdx = suffix.Index(dotr, dotrIdx + 1);
373 }
374 if (lastDotrIdx != kNPOS) {
375 // Add the part up until '.root' to the basename for globbing
376 basename.Append(suffix, lastDotrIdx + dotrl);
377 // Remove the part up until '.root' from the suffix
378 suffix.Replace(0, lastDotrIdx + dotrl, "");
379 }
380
381 // case with one single file
382 if (!basename.MaybeWildcard()) {
383 return AddFile(name, nentries);
384 }
385
386 // wildcarding used in name
387 Int_t nf = 0;
388 std::vector<std::string> expanded_glob;
389 try {
391 } catch (const std::runtime_error &) {
392 // The 'ExpandGlob' function may throw in case the directory from the glob
393 // cannot be opened. We return 0 to signify no files were added.
394 return nf;
395 }
396
397 const TString hashMarkTreeName{"#" + treename};
398 for (const auto &path : expanded_glob) {
399 if (suffix == hashMarkTreeName) {
400 // See https://github.com/root-project/root/issues/11483
401 // In case the input parameter 'name' contains both a glob and the
402 // '?#' token to identify the tree name, the call to
403 // `ParseTreeFileName` will produce a 'suffix' string of the form
404 // '#treename'. Passing this to the `AddFile` call produces a bogus
405 // file name that TChain won't be able to open afterwards. Thus,
406 // we do not pass the 'suffix' as part of the file name, instead we
407 // directly pass 'treename' to `AddFile`.
408 nf += AddFile(path.c_str(), nentries, treename);
409 } else {
410 nf += AddFile(TString::Format("%s%s", path.c_str(), suffix.Data()), nentries);
411 }
412 }
413
414 return nf;
415}
416
417////////////////////////////////////////////////////////////////////////////////
418/// Add a new file to this chain.
419///
420/// Filename formats are similar to TChain::Add. Wildcards are not
421/// applied. urls may also contain query and fragment identifiers
422/// where the tree name can be specified in the url fragment.
423///
424/// eg.
425/// ~~~ {.cpp}
426/// root://machine/path/file_name[?query[#tree_name]]
427/// root://machine/path/file_name.root[.oext]/tree_name[?query]
428/// ~~~
429/// If tree_name is given as a part of the file name it is used to
430/// as the name of the tree to load from the file. Otherwise if tname
431/// argument is specified the chain will load the tree named tname from
432/// the file, otherwise the original treename specified in the TChain
433/// constructor will be used.
434/// Tagging the tree_name with a slash [/tree_name] is only supported for
435/// backward compatibility; it requires the file name ot contain the string
436/// '.root' and its use is deprecated.
437///
438/// A. If nentries <= 0, the file is opened and the tree header read
439/// into memory to get the number of entries.
440///
441/// B. If nentries > 0, the file is not opened, and nentries is assumed
442/// to be the number of entries in the file. In this case, no check
443/// is made that the file exists nor that the tree exists in the file,
444/// nor that the real TTree entries match with the input argument.
445/// This second mode is interesting in case the number of entries in
446/// the file is already stored in a run database for example.
447/// \warning If you pass `nentries` > `tree_entries`, this may lead to silent
448/// data corruption in your analysis or undefined behavior in your program.
449/// Use the other options if unsure.
450///
451/// C. If nentries == TTree::kMaxEntries (default), the file is not opened.
452/// The number of entries in each file will be read only when the file
453/// is opened to read an entry. This option is the default and very
454/// efficient if one processes the chain sequentially. Note that in
455/// case GetEntry(entry) is called and entry refers to an entry in the
456/// third file, for example, this forces the tree headers in the first
457/// and second file to be read to find the number of entries in those
458/// files. Note that if one calls GetEntriesFast() after having created
459/// a chain with this default, GetEntriesFast() will return TTree::kMaxEntries!
460/// Using the GetEntries() function instead will force all of the tree
461/// headers in the chain to be read to read the number of entries in
462/// each tree.
463///
464/// D. The TChain data structure
465/// Each TChainElement has a name equal to the tree name of this TChain
466/// and a title equal to the file name. So, to loop over the
467/// TFiles that have been added to this chain:
468/// ~~~ {.cpp}
469/// TObjArray *fileElements=chain->GetListOfFiles();
470/// TIter next(fileElements);
471/// TChainElement *chEl=0;
472/// while (( chEl=(TChainElement*)next() )) {
473/// TFile f(chEl->GetTitle());
474/// ... do something with f ...
475/// }
476/// ~~~
477/// The function returns 1 if the file is successfully connected, 0 otherwise.
478
479Int_t TChain::AddFile(const char* name, Long64_t nentries /* = TTree::kMaxEntries */, const char* tname /* = "" */)
480{
481 if(name==nullptr || name[0]=='\0') {
482 Error("AddFile", "No file name; no files connected");
483 return 0;
484 }
485
486 const char *treename = GetName();
487 if (tname && strlen(tname) > 0) treename = tname;
488
491
492 if (!tn.IsNull()) {
493 treename = tn.Data();
494 }
495
496 Int_t nch = basename.Length() + query.Length();
497 char *filename = new char[nch+1];
498 strlcpy(filename,basename.Data(),nch+1);
499 strlcat(filename,query.Data(),nch+1);
500
501 //Check enough space in fTreeOffset
502 if (fNtrees+1 >= fTreeOffsetLen) {
503 fTreeOffsetLen *= 2;
505 for (Int_t i=0;i<=fNtrees;i++) trees[i] = fTreeOffset[i];
506 delete [] fTreeOffset;
508 }
509
510 // Open the file to get the number of entries.
511 Int_t pksize = 0;
512 if (nentries <= 0) {
513 TFile* file;
514 {
516 const char *option = fGlobalRegistration ? "READ" : "READ_WITHOUT_GLOBALREGISTRATION";
517 file = TFile::Open(filename, option);
518 }
519 if (!file || file->IsZombie()) {
520 delete file;
521 file = nullptr;
522 delete[] filename;
523 filename = nullptr;
524 return 0;
525 }
526
527 // Check that tree with the right name exists in the file.
528 // Note: We are not the owner of obj, the file is!
529 TObject* obj = file->Get(treename);
530 if (!obj || !obj->InheritsFrom(TTree::Class())) {
531 Error("AddFile", "cannot find tree with name %s in file %s", treename, filename);
532 delete file;
533 file = nullptr;
534 delete[] filename;
535 filename = nullptr;
536 return 0;
537 }
538 TTree* tree = (TTree*) obj;
539 nentries = tree->GetEntries();
540 pksize = tree->GetPacketSize();
541 // Note: This deletes the tree we fetched.
542 delete file;
543 file = nullptr;
544 }
545
546 if (nentries > 0) {
550 } else {
553 }
554 fNtrees++;
555
557 element->SetPacketSize(pksize);
558 element->SetNumberEntries(nentries);
560 } else {
561 Warning("AddFile", "Adding tree with no entries from file: %s", filename);
562 }
563
564 delete [] filename;
565
566 return 1;
567}
568
569////////////////////////////////////////////////////////////////////////////////
570/// Add all files referenced in the list to the chain. The object type in the
571/// list must be either TFileInfo or TObjString or TUrl .
572/// The function return 1 if successful, 0 otherwise.
573
575{
576 if (!filelist)
577 return 0;
578 TIter next(filelist);
579
580 TObject *o = nullptr;
581 Long64_t cnt=0;
582 while ((o = next())) {
583 // Get the url
584 TString cn = o->ClassName();
585 const char *url = nullptr;
586 if (cn == "TFileInfo") {
587 TFileInfo *fi = (TFileInfo *)o;
588 url = (fi->GetCurrentUrl()) ? fi->GetCurrentUrl()->GetUrl() : nullptr;
589 if (!url) {
590 Warning("AddFileInfoList", "found TFileInfo with empty Url - ignoring");
591 continue;
592 }
593 } else if (cn == "TUrl") {
594 url = ((TUrl*)o)->GetUrl();
595 } else if (cn == "TObjString") {
596 url = ((TObjString*)o)->GetName();
597 }
598 if (!url) {
599 Warning("AddFileInfoList", "object is of type %s : expecting TFileInfo, TUrl"
600 " or TObjString - ignoring", o->ClassName());
601 continue;
602 }
603 // Good entry
604 cnt++;
605 AddFile(url);
606 if (cnt >= nfiles)
607 break;
608 }
609
610 return 1;
611}
612
613////////////////////////////////////////////////////////////////////////////////
614/// Add a TFriendElement to the list of friends of this chain.
615///
616/// A TChain has a list of friends similar to a tree (see TTree::AddFriend).
617/// You can add a friend to a chain with the TChain::AddFriend method, and you
618/// can retrieve the list of friends with TChain::GetListOfFriends.
619/// This example has four chains each has 20 ROOT trees from 20 ROOT files.
620/// ~~~ {.cpp}
621/// TChain ch("t"); // a chain with 20 trees from 20 files
622/// TChain ch1("t1");
623/// TChain ch2("t2");
624/// TChain ch3("t3");
625/// ~~~
626/// Now we can add the friends to the first chain.
627/// ~~~ {.cpp}
628/// ch.AddFriend("t1")
629/// ch.AddFriend("t2")
630/// ch.AddFriend("t3")
631/// ~~~
632/// \image html tchain_friend.png
633///
634///
635/// The parameter is the name of friend chain (the name of a chain is always
636/// the name of the tree from which it was created).
637/// The original chain has access to all variable in its friends.
638/// We can use the TChain::Draw method as if the values in the friends were
639/// in the original chain.
640/// To specify the chain to use in the Draw method, use the syntax:
641/// ~~~ {.cpp}
642/// <chainname>.<branchname>.<varname>
643/// ~~~
644/// If the variable name is enough to uniquely identify the variable, you can
645/// leave out the chain and/or branch name.
646/// For example, this generates a 3-d scatter plot of variable "var" in the
647/// TChain ch versus variable v1 in TChain t1 versus variable v2 in TChain t2.
648/// ~~~ {.cpp}
649/// ch.Draw("var:t1.v1:t2.v2");
650/// ~~~
651/// When a TChain::Draw is executed, an automatic call to TTree::AddFriend
652/// connects the trees in the chain. When a chain is deleted, its friend
653/// elements are also deleted.
654///
655/// The number of entries in the friend must be equal or greater to the number
656/// of entries of the original chain. If the friend has fewer entries a warning
657/// is given and the resulting histogram will have missing entries.
658/// For additional information see TTree::AddFriend.
659
660TFriendElement* TChain::AddFriend(const char* chain, const char* dummy /* = "" */)
661{
662 if (!fFriends) {
663 fFriends = new TList();
664 }
665 TFriendElement* fe = new TFriendElement(this, chain, dummy);
666
667 R__ASSERT(fe); // There used to be a "if (fe)" test ... Keep this assert until we are sure that fe is never null
668
669 fFriends->Add(fe);
670
671 // We need to invalidate the loading of the current tree because its list
672 // of real friends is now obsolete. It is repairable only from LoadTree.
674
675 TTree* tree = fe->GetTree();
676 if (!tree) {
677 Warning("AddFriend", "Unknown TChain %s", chain);
678 }
679 return fe;
680}
681
682////////////////////////////////////////////////////////////////////////////////
683/// Add the whole chain or tree as a friend of this chain.
684
685TFriendElement* TChain::AddFriend(const char* chain, TFile* dummy)
686{
687 if (!fFriends) fFriends = new TList();
688 TFriendElement *fe = new TFriendElement(this,chain,dummy);
689
690 R__ASSERT(fe); // There used to be a "if (fe)" test ... Keep this assert until we are sure that fe is never null
691
692 fFriends->Add(fe);
693
694 // We need to invalidate the loading of the current tree because its list
695 // of real friend is now obsolete. It is repairable only from LoadTree
697
698 TTree *t = fe->GetTree();
699 if (!t) {
700 Warning("AddFriend","Unknown TChain %s",chain);
701 }
702 return fe;
703}
704
705////////////////////////////////////////////////////////////////////////////////
706/// Add the whole chain or tree as a friend of this chain.
707
708TFriendElement* TChain::AddFriend(TTree* chain, const char* alias, bool /* warn = false */)
709{
710 if (!chain) return nullptr;
711 if (!fFriends) fFriends = new TList();
712 TFriendElement *fe = new TFriendElement(this,chain,alias);
713 R__ASSERT(fe);
714
715 fFriends->Add(fe);
716
717 // We need to invalidate the loading of the current tree because its list
718 // of real friend is now obsolete. It is repairable only from LoadTree
720
721 TTree *t = fe->GetTree();
722 if (!t) {
723 Warning("AddFriend","Unknown TChain %s",chain->GetName());
724 }
725 return fe;
726}
727
728////////////////////////////////////////////////////////////////////////////////
729/// Browse the contents of the chain.
730
732{
734}
735
736////////////////////////////////////////////////////////////////////////////////
737/// When closing a file during the chain processing, the file
738/// may be closed with option "R" if flag is set to true.
739/// by default flag is true.
740/// When closing a file with option "R", all TProcessIDs referenced by this
741/// file are deleted.
742/// Calling TFile::Close("R") might be necessary in case one reads a long list
743/// of files having TRef, writing some of the referenced objects or TRef
744/// to a new file. If the TRef or referenced objects of the file being closed
745/// will not be referenced again, it is possible to minimize the size
746/// of the TProcessID data structures in memory by forcing a delete of
747/// the unused TProcessID.
748
749void TChain::CanDeleteRefs(bool flag /* = true */)
750{
752}
753
754////////////////////////////////////////////////////////////////////////////////
755/// Copy a tree with selection.
756///
757/// See the documentation of TTree::CopyTree
758///
759/// ### Known limitations for TChain
760/// - This method is not supported if used on an instance with friends
761
762TTree* TChain::CopyTree(const char* selection, Option_t* option /* = 0 */, Long64_t nentries /* = TTree::kMaxEntries */, Long64_t firstentry /* = 0 */)
763{
764 // A clear error for ROOT-10778
765 if (GetListOfFriends()) {
766 Error("CopyTree","TChain::CopyTree is not supported if the TChain instance has friends.");
767 return nullptr;
768 }
769 return this->TTree::CopyTree(selection, option, nentries, firstentry);
770}
771
772////////////////////////////////////////////////////////////////////////////////
773/// Initialize the packet descriptor string.
774
776{
777 TIter next(fFiles);
778 TChainElement* element = nullptr;
779 while ((element = (TChainElement*) next())) {
780 element->CreatePackets();
781 }
782}
783
784////////////////////////////////////////////////////////////////////////////////
785/// Override the TTree::DirectoryAutoAdd behavior:
786/// we never auto add.
787
789{
790}
791
792////////////////////////////////////////////////////////////////////////////////
793/// Draw expression varexp for selected entries.
794/// Returns -1 in case of error or number of selected events in case of success.
795///
796/// This function accepts TCut objects as arguments.
797/// Useful to use the string operator +, example:
798/// ~~~{.cpp}
799/// ntuple.Draw("x",cut1+cut2+cut3);
800/// ~~~
801///
802
808
809////////////////////////////////////////////////////////////////////////////////
810/// Process all entries in this chain and draw histogram corresponding to
811/// expression varexp.
812/// Returns -1 in case of error or number of selected events in case of success.
813
821
822////////////////////////////////////////////////////////////////////////////////
823/// See TTree::GetReadEntry().
824
826{
827 auto findBranchImpl = [this](const char *resolvedBranchName) -> TBranch * {
828 if (fTree) {
830 }
831 LoadTree(0);
832 if (fTree) {
834 }
835 return nullptr;
836 };
837
838 // This will allow the branchname to be preceded by the name of this chain.
839 // See similar code in TTree::FindBranch
840 std::string_view branchNameView{branchname};
841 std::string_view chainPrefix = GetName();
842
844 branchNameView.remove_prefix(chainPrefix.length());
845 if (!branchNameView.empty() && branchNameView.front() == '.') {
846 branchNameView.remove_prefix(1);
847 // We're only removing characters from the beginning of the view so we
848 // don't need to worry about missing null-termination character
849 return findBranchImpl(branchNameView.data());
850 }
851 }
852
854}
855
856////////////////////////////////////////////////////////////////////////////////
857/// See TTree::GetReadEntry().
858
860{
861 auto findLeafImpl = [this](const char *resolvedBranchName) -> TLeaf * {
862 if (fTree) {
864 }
865 LoadTree(0);
866 if (fTree) {
868 }
869 return nullptr;
870 };
871
872 // This will allow the branchname to be preceded by the name of this chain.
873 // See similar code in TTree::FindLeaf
874 std::string_view branchNameView{searchname};
875 std::string_view chainPrefix = GetName();
876
878 branchNameView.remove_prefix(chainPrefix.length());
879 if (!branchNameView.empty() && branchNameView.front() == '.') {
880 branchNameView.remove_prefix(1);
881 // We're only removing characters from the beginning of the view so we
882 // don't need to worry about missing null-termination character
883 return findLeafImpl(branchNameView.data());
884 }
885 }
886
887 return findLeafImpl(searchname);
888}
889
890////////////////////////////////////////////////////////////////////////////////
891/// Returns the expanded value of the alias. Search in the friends if any.
892
893const char* TChain::GetAlias(const char* aliasName) const
894{
895 const char* alias = TTree::GetAlias(aliasName);
896 if (alias) {
897 return alias;
898 }
899 if (fTree) {
900 return fTree->GetAlias(aliasName);
901 }
902 const_cast<TChain*>(this)->LoadTree(0);
903 if (fTree) {
904 return fTree->GetAlias(aliasName);
905 }
906 return nullptr;
907}
908
909////////////////////////////////////////////////////////////////////////////////
910/// Return pointer to the branch name in the current tree.
911
913{
914 if (fTree) {
915 return fTree->GetBranch(name);
916 }
917 LoadTree(0);
918 if (fTree) {
919 return fTree->GetBranch(name);
920 }
921 return nullptr;
922}
923
924////////////////////////////////////////////////////////////////////////////////
925/// See TTree::GetReadEntry().
926
927bool TChain::GetBranchStatus(const char* branchname) const
928{
930}
931
932////////////////////////////////////////////////////////////////////////////////
933/// Return an iterator over the cluster of baskets starting at firstentry.
934///
935/// This iterator is not yet supported for TChain object.
936
938{
939 Fatal("GetClusterIterator","TChain objects are not supported");
940 return TTree::GetClusterIterator(-1);
941}
942
943////////////////////////////////////////////////////////////////////////////////
944/// Return absolute entry number in the chain.
945/// The input parameter entry is the entry number in
946/// the current tree of this chain.
947
952
953////////////////////////////////////////////////////////////////////////////////
954/// Return the total number of entries in the chain.
955/// In case the number of entries in each tree is not yet known,
956/// the offset table is computed.
957
959{
961 // If the following is true, we are within a recursion about friend,
962 // and `LoadTree` will be no-op.
964 return fEntries;
967 if (chainEl->GetEntries() != TTree::kMaxEntries) {
968 totalEntries += chainEl->GetEntries();
969 continue;
970 }
972 std::unique_ptr<TFile> curFile{TFile::Open(chainEl->GetTitle(), "READ_WITHOUT_GLOBALREGISTRATION")};
973 if (!curFile || curFile->IsZombie()) {
974 continue;
975 }
976 std::unique_ptr<TTree> curTree{curFile->Get<TTree>(chainEl->GetName())};
977 if (!curTree) {
978 continue;
979 }
980 totalEntries += curTree->GetEntries();
981 }
982 const_cast<TChain *>(this)->fEntries = totalEntries;
983 }
984 return fEntries;
985}
986
987////////////////////////////////////////////////////////////////////////////////
988/// Get entry from the file to memory.
989///
990/// - getall = 0 : get only active branches
991/// - getall = 1 : get all branches
992///
993/// Return the total number of bytes read,
994/// 0 bytes read indicates a failure.
995
997{
999 if (treeReadEntry < 0) {
1000 return 0;
1001 }
1002 if (!fTree) {
1003 return 0;
1004 }
1006}
1007
1008////////////////////////////////////////////////////////////////////////////////
1009/// Return entry number corresponding to entry.
1010///
1011/// if no TEntryList set returns entry
1012/// else returns entry \#entry from this entry list and
1013/// also computes the global entry number (loads all tree headers)
1014
1016{
1017
1018 if (fEntryList){
1019 Int_t treenum = 0;
1021 //find the global entry number
1022 //same const_cast as in the GetEntries() function
1023 if (localentry<0) return -1;
1024 if (treenum != fTreeNumber){
1026 for (Int_t i=0; i<=treenum; i++){
1028 (const_cast<TChain*>(this))->LoadTree(fTreeOffset[i-1]);
1029 }
1030 }
1031 //(const_cast<TChain*>(this))->LoadTree(fTreeOffset[treenum]);
1032 }
1034 return globalentry;
1035 }
1036 return entry;
1037}
1038
1039////////////////////////////////////////////////////////////////////////////////
1040/// Return entry corresponding to major and minor number.
1041///
1042/// The function returns the total number of bytes read; -1 if entry not found.
1043/// If the Tree has friend trees, the corresponding entry with
1044/// the index values (major,minor) is read. Note that the master Tree
1045/// and its friend may have different entry serial numbers corresponding
1046/// to (major,minor).
1047/// \note See TTreeIndex::GetEntryNumberWithIndex for information about the maximum values accepted for major and minor
1048
1050{
1052 if (serial < 0) return -1;
1053 return GetEntry(serial);
1054}
1055
1056////////////////////////////////////////////////////////////////////////////////
1057/// Return a pointer to the current file.
1058/// If no file is connected, the first file is automatically loaded.
1059
1061{
1062 if (fFile) {
1063 return fFile;
1064 }
1065 // Force opening the first file in the chain.
1066 const_cast<TChain*>(this)->LoadTree(0);
1067 return fFile;
1068}
1069
1070////////////////////////////////////////////////////////////////////////////////
1071/// Return a pointer to the leaf name in the current tree.
1072
1073TLeaf* TChain::GetLeaf(const char* branchname, const char *leafname)
1074{
1075 if (fTree) {
1076 return fTree->GetLeaf(branchname, leafname);
1077 }
1078 LoadTree(0);
1079 if (fTree) {
1080 return fTree->GetLeaf(branchname, leafname);
1081 }
1082 return nullptr;
1083}
1084
1085////////////////////////////////////////////////////////////////////////////////
1086/// Return a pointer to the leaf name in the current tree.
1087
1089{
1090 if (fTree) {
1091 return fTree->GetLeaf(name);
1092 }
1093 LoadTree(0);
1094 if (fTree) {
1095 return fTree->GetLeaf(name);
1096 }
1097 return nullptr;
1098}
1099
1100////////////////////////////////////////////////////////////////////////////////
1101/// Return a pointer to the list of branches of the current tree.
1102///
1103/// Warning: If there is no current TTree yet, this routine will open the
1104/// first in the chain.
1105///
1106/// Returns 0 on failure.
1107
1109{
1110 if (fTree) {
1111 return fTree->GetListOfBranches();
1112 }
1113 LoadTree(0);
1114 if (fTree) {
1115 return fTree->GetListOfBranches();
1116 }
1117 return nullptr;
1118}
1119
1120////////////////////////////////////////////////////////////////////////////////
1121/// Return a pointer to the list of leaves of the current tree.
1122///
1123/// Warning: May set the current tree!
1124
1126{
1127 if (fTree) {
1128 return fTree->GetListOfLeaves();
1129 }
1130 LoadTree(0);
1131 if (fTree) {
1132 return fTree->GetListOfLeaves();
1133 }
1134 return nullptr;
1135}
1136
1137////////////////////////////////////////////////////////////////////////////////
1138/// Return maximum of column with name columname.
1139
1141{
1143 TLeaf *leaf = nullptr;
1144 TBranch *branch = nullptr;
1145 Int_t treenumber = -1;
1146 for (Long64_t i = 0; i < fEntries; ++i) {
1148 if (entryNumber < 0)
1149 break;
1150 Long64_t localEntryNumber = this->LoadTree(entryNumber);
1151 if (localEntryNumber < 0)
1152 break;
1153 if (treenumber != this->GetTreeNumber()) {
1154 leaf = this->GetLeaf(columname);
1155 if (leaf)
1156 branch = leaf->GetBranch();
1157 }
1158 treenumber = this->GetTreeNumber();
1159 if (!branch)
1160 continue;
1161 branch->GetEntry(localEntryNumber);
1162 for (Int_t j = 0; j < leaf->GetLen(); ++j) {
1163 Double_t val = leaf->GetValue(j);
1164 if (val > cmax) {
1165 cmax = val;
1166 }
1167 }
1168 }
1169 return cmax;
1170}
1171
1172////////////////////////////////////////////////////////////////////////////////
1173/// Return minimum of column with name columname.
1174
1176{
1178 TLeaf *leaf = nullptr;
1179 TBranch *branch = nullptr;
1180 Int_t treenumber = -1;
1181 for (Long64_t i = 0; i < fEntries; ++i) {
1183 if (entryNumber < 0)
1184 break;
1185 Long64_t localEntryNumber = this->LoadTree(entryNumber);
1186 if (localEntryNumber < 0)
1187 break;
1188 if (treenumber != this->GetTreeNumber()) {
1189 leaf = this->GetLeaf(columname);
1190 if (leaf)
1191 branch = leaf->GetBranch();
1192 }
1193 treenumber = this->GetTreeNumber();
1194 if (!branch)
1195 continue;
1196 branch->GetEntry(localEntryNumber);
1197 for (Int_t j = 0; j < leaf->GetLen(); ++j) {
1198 Double_t val = leaf->GetValue(j);
1199 if (val < cmin) {
1200 cmin = val;
1201 }
1202 }
1203 }
1204 return cmin;
1205}
1206
1207////////////////////////////////////////////////////////////////////////////////
1208/// Return the number of branches of the current tree.
1209///
1210/// Warning: May set the current tree!
1211
1213{
1214 if (fTree) {
1215 return fTree->GetNbranches();
1216 }
1217 LoadTree(0);
1218 if (fTree) {
1219 return fTree->GetNbranches();
1220 }
1221 return 0;
1222}
1223
1224////////////////////////////////////////////////////////////////////////////////
1225/// See TTree::GetReadEntry().
1226
1228{
1229 return TTree::GetReadEntry();
1230}
1231
1232////////////////////////////////////////////////////////////////////////////////
1233/// Return the chain weight.
1234///
1235/// By default the weight is the weight of the current tree.
1236/// However, if the weight has been set in TChain::SetWeight()
1237/// with the option "global", then that weight will be returned.
1238///
1239/// Warning: May set the current tree!
1240
1242{
1243 if (TestBit(kGlobalWeight)) {
1244 return fWeight;
1245 } else {
1246 if (fTree) {
1247 return fTree->GetWeight();
1248 }
1249 const_cast<TChain*>(this)->LoadTree(0);
1250 if (fTree) {
1251 return fTree->GetWeight();
1252 }
1253 return 0;
1254 }
1255}
1256
1257////////////////////////////////////////////////////////////////////////////////
1258/// Move content to a new file. (NOT IMPLEMENTED for TChain)
1259bool TChain::InPlaceClone(TDirectory * /* new directory */, const char * /* options */)
1260{
1261 Error("InPlaceClone", "not implemented");
1262 return false;
1263}
1264
1265////////////////////////////////////////////////////////////////////////////////
1266/// Set the TTree to be reloaded as soon as possible. In particular this
1267/// is needed when adding a Friend.
1268///
1269/// If the tree has clones, copy them into the chain
1270/// clone list so we can change their branch addresses
1271/// when necessary.
1272///
1273/// This is to support the syntax:
1274/// ~~~ {.cpp}
1275/// TTree* clone = chain->GetTree()->CloneTree(0);
1276/// ~~~
1277
1279{
1280 if (fTree && fTree->GetListOfClones()) {
1281 for (TObjLink* lnk = fTree->GetListOfClones()->FirstLink(); lnk; lnk = lnk->Next()) {
1282 TTree* clone = (TTree*) lnk->GetObject();
1283 AddClone(clone);
1284 }
1285 }
1286 fTreeNumber = -1;
1287 fTree = nullptr;
1288}
1289
1290////////////////////////////////////////////////////////////////////////////////
1291/// Dummy function.
1292/// It could be implemented and load all baskets of all trees in the chain.
1293/// For the time being use TChain::Merge and TTree::LoadBasket
1294/// on the resulting tree.
1295
1297{
1298 Error("LoadBaskets", "Function not yet implemented for TChain.");
1299 return 0;
1300}
1301
1302////////////////////////////////////////////////////////////////////////////////
1303/// Refresh branch/leaf addresses of friend trees
1304///
1305/// The method acts only on the current tree in the chain (fTree), but it may
1306/// be called in two different scenarios: when there are friends of the chain
1307/// or when there are friends of fTree itself.
1309{
1310 assert(fTree != nullptr);
1311
1312 bool needUpdate = false;
1313 if (auto *innerFriendList = fTree->GetListOfFriends()) {
1314 // If the current tree has friends, check if they were mark for update
1315 // when switching to the following tree, detect it so that we later we
1316 // actually refresh the addresses of the friends.
1318 if (frEl->IsUpdated()) {
1319 needUpdate = true;
1320 frEl->ResetUpdated();
1321 }
1322 if (frEl->IsUpdatedForChain()) {
1323 needUpdate = true;
1324 frEl->ResetUpdatedForChain();
1325 }
1326 }
1327 }
1328
1329 if (!needUpdate)
1330 return 0;
1331
1332 // Update the branch/leaf addresses and the list of leaves in all
1333 // TTreeFormula of the TTreePlayer (if any).
1335 // Set the branch status of all the chain elements, which may include also
1336 // branches that are available in friends. Only set the branch status
1337 // if it has a value provided by the user
1338 Int_t status = chainEl->GetStatus();
1339 if (status != -1)
1340 fTree->SetBranchStatus(chainEl->GetName(), status);
1341
1342 // Set the branch addresses for the newly opened file.
1343 void *addr = chainEl->GetBaddress();
1344 if (!addr)
1345 continue;
1346
1347 TBranch *br = fTree->GetBranch(chainEl->GetName());
1348 TBranch **pp = chainEl->GetBranchPtr();
1349 if (pp) {
1350 // FIXME: What if br is zero here?
1351 *pp = br;
1352 }
1353 if (!br)
1354 continue;
1355
1356 if (!chainEl->GetCheckedType()) {
1357 Int_t res = CheckBranchAddressType(br, TClass::GetClass(chainEl->GetBaddressClassName()),
1358 (EDataType)chainEl->GetBaddressType(), chainEl->GetBaddressIsPtr());
1359 if ((res & kNeedEnableDecomposedObj) && !br->GetMakeClass()) {
1360 br->SetMakeClass(true);
1361 }
1362 chainEl->SetDecomposedObj(br->GetMakeClass());
1363 chainEl->SetCheckedType(true);
1364 }
1365 // FIXME: We may have to tell the branch it should
1366 // not be an owner of the object pointed at.
1367 br->SetAddress(addr);
1368 if (TestBit(kAutoDelete)) {
1369 br->SetAutoDelete(true);
1370 }
1371 }
1372
1373 // We cannot know a priori if the branch(es) of the friend TChain(s) that were just
1374 // updated were supposed to be connected to one of the TChainElement of this chain
1375 // or possibly to another TChainElement belonging to another chain that has befriended
1376 // this chain (i.e., one of the "external friends"). Thus, we forward the notification
1377 // that one or more friend trees were updated to the friends of this chain.
1378 if (fExternalFriends)
1380 external_fe->MarkUpdated();
1381
1382 if (fPlayer) {
1384 }
1385 // Notify user if requested.
1386 if (fNotify) {
1387 if (!fNotify->Notify())
1388 return -6;
1389 }
1390
1391 return 0;
1392}
1393
1394////////////////////////////////////////////////////////////////////////////////
1395/// Find the tree which contains entry, and set it as the current tree.
1396///
1397/// Returns the entry number in that tree.
1398///
1399/// The input argument entry is the entry serial number in the whole chain.
1400///
1401/// In case of error, LoadTree returns a negative number:
1402/// * -1: The chain is empty.
1403/// * -2: The requested entry number is less than zero or too large for the chain.
1404/// * -3: The file corresponding to the entry could not be correctly opened
1405/// * -4: The TChainElement corresponding to the entry is missing or
1406/// the TTree is missing from the file.
1407/// * -5: Internal error, please report the circumstance when this happen
1408/// as a ROOT issue.
1409/// * -6: An error occurred within the notify callback.
1410///
1411/// Calls fNotify->Notify() (if fNotify is not null) when starting the processing of a new sub-tree.
1412/// See TNotifyLink for more information on the notification mechanism.
1413///
1414/// \note This is the only routine which sets the value of fTree to a non-zero pointer.
1415///
1417{
1418 // We already have been visited while recursively looking
1419 // through the friends tree, let's return.
1421 return 0;
1422 }
1423
1424 if (!fNtrees) {
1425 // -- The chain is empty.
1426 return -1;
1427 }
1428
1429 if ((entry < 0) || ((entry > 0) && (entry >= fEntries && entry!=(TTree::kMaxEntries-1) ))) {
1430 // -- Invalid entry number.
1431 if (fTree) fTree->LoadTree(-1);
1432 fReadEntry = -1;
1433 return -2;
1434 }
1435
1436 // Find out which tree in the chain contains the passed entry.
1439 // -- Entry is *not* in the chain's current tree.
1440 // Do a linear search of the tree offset array.
1441 // FIXME: We could be smarter by starting at the
1442 // current tree number and going forwards,
1443 // then wrapping around at the end.
1444 for (treenum = 0; treenum < fNtrees; treenum++) {
1445 if (entry < fTreeOffset[treenum+1]) {
1446 break;
1447 }
1448 }
1449 }
1450
1451 // Calculate the entry number relative to the found tree.
1453 fReadEntry = entry;
1454
1455 // If entry belongs to the current tree return entry.
1456 if (fTree && treenum == fTreeNumber) {
1457 // First load entry on the current tree, this will set the cursor also
1458 // on its friend trees. Their branch addresses cannot be updated yet,
1459 // as the required branch names are only available via `fStatus`, i.e.
1460 // only the chain knows about them. This is taken care of in the following
1461 // RefreshFriendAddresses call
1463
1464 if (fFriends || fTree->GetListOfFriends()) {
1465 TFriendLock lock(this, kLoadTree);
1466 if (fFriends) {
1467 // Make sure we load friends of the chain aligned to the current global entry number
1469 auto *frTree = frEl->GetTree();
1470 frTree->LoadTreeFriend(entry, this);
1471 }
1472 }
1473
1474 // Now refresh branch addresses of friend trees. This acts on the current tree of the chain, whether the
1475 // friends are friends of the chain or friends of the tree itself.
1478 }
1479
1480 return treeReadEntry;
1481 }
1482
1483 if (fExternalFriends) {
1485 external_fe->MarkUpdated();
1486 }
1487 }
1488
1489 // Delete the current tree and open the new tree.
1490 TTreeCache* tpf = nullptr;
1491 // Delete file unless the file owns this chain!
1492 // FIXME: The "unless" case here causes us to leak memory.
1493 if (fFile) {
1494 if (!fDirectory->GetList()->FindObject(this)) {
1495 if (fTree) {
1496 // (fFile != 0 && fTree == 0) can happen when
1497 // InvalidateCurrentTree is called (for example from
1498 // AddFriend). Having fTree === 0 is necessary in that
1499 // case because in some cases GetTree is used as a check
1500 // to see if a TTree is already loaded.
1501 // However, this prevent using the following to reuse
1502 // the TTreeCache object.
1504 if (tpf) {
1505 tpf->ResetCache();
1506 }
1507
1508 fFile->SetCacheRead(nullptr, fTree);
1509 // If the tree has clones, copy them into the chain
1510 // clone list so we can change their branch addresses
1511 // when necessary.
1512 //
1513 // This is to support the syntax:
1514 //
1515 // TTree* clone = chain->GetTree()->CloneTree(0);
1516 //
1517 // We need to call the invalidate exactly here, since
1518 // we no longer need the value of fTree and it is
1519 // about to be deleted.
1521 }
1522
1523 if (fCanDeleteRefs) {
1524 fFile->Close("R");
1525 }
1526 delete fFile;
1527 fFile = nullptr;
1528 } else {
1529 // If the tree has clones, copy them into the chain
1530 // clone list so we can change their branch addresses
1531 // when necessary.
1532 //
1533 // This is to support the syntax:
1534 //
1535 // TTree* clone = chain->GetTree()->CloneTree(0);
1536 //
1538 }
1539 }
1540
1542 if (!element) {
1543 if (treeReadEntry) {
1544 return -4;
1545 }
1546 // Last attempt, just in case all trees in the chain have 0 entries.
1547 element = (TChainElement*) fFiles->At(0);
1548 if (!element) {
1549 return -4;
1550 }
1551 }
1552
1553 // FIXME: We leak memory here, we've just lost the open file
1554 // if we did not delete it above.
1555 {
1557 const char *option = fGlobalRegistration ? "READ" : "READ_WITHOUT_GLOBALREGISTRATION";
1558 fFile = TFile::Open(element->GetTitle(), option);
1561 }
1562
1563 // ----- Begin of modifications by MvL
1564 Int_t returnCode = 0;
1565 if (!fFile || fFile->IsZombie()) {
1566 if (fFile) {
1567 delete fFile;
1568 fFile = nullptr;
1569 }
1570 // Note: We do *not* own fTree.
1571 fTree = nullptr;
1572 returnCode = -3;
1573 } else {
1574 if (fPerfStats)
1576
1577 // Note: We do *not* own fTree after this, the file does!
1578 fTree = dynamic_cast<TTree*>(fFile->Get(element->GetName()));
1579 if (!fTree) {
1580 // Now that we do not check during the addition, we need to check here!
1581 Error("LoadTree", "Cannot find tree with name %s in file %s", element->GetName(), element->GetTitle());
1582 delete fFile;
1583 fFile = nullptr;
1584 // We do not return yet so that 'fEntries' can be updated with the
1585 // sum of the entries of all the other trees.
1586 returnCode = -4;
1587 } else if (!fGlobalRegistration) {
1589 }
1590 // Propagate the IMT settings
1591 if (fTree) {
1593 }
1594 }
1595
1597 // FIXME: We own fFile, we must be careful giving away a pointer to it!
1598 // FIXME: We may set fDirectory to zero here!
1599 fDirectory = fFile;
1600
1601 // Reuse cache from previous file (if any).
1602 if (tpf) {
1603 if (fFile) {
1604 // FIXME: fTree may be zero here.
1605 tpf->UpdateBranches(fTree);
1606 tpf->ResetCache();
1608 } else {
1609 // FIXME: One of the file in the chain is missing
1610 // we have no place to hold the pointer to the
1611 // TTreeCache.
1612 delete tpf;
1613 tpf = nullptr;
1614 }
1615 } else {
1616 if (fCacheUserSet) {
1617 this->SetCacheSize(fCacheSize);
1618 }
1619 }
1620
1621 // Check if fTreeOffset has really been set.
1622 Long64_t nentries = 0;
1623 if (fTree) {
1625 }
1626
1630 element->SetNumberEntries(nentries);
1631 // Below we must test >= in case the tree has no entries.
1632 if (entry >= fTreeOffset[fTreeNumber+1]) {
1633 if ((fTreeNumber < (fNtrees - 1)) && (entry < fTreeOffset[fTreeNumber+2])) {
1634 // The request entry is not in the tree 'fTreeNumber' we will need
1635 // to look further.
1636
1637 // Before moving on, let's record the result.
1638 element->SetLoadResult(returnCode);
1639
1640 // Before trying to read the file file/tree, notify the user
1641 // that we have switched trees if requested; the user might need
1642 // to properly account for the number of files/trees even if they
1643 // have no entries.
1644 if (fNotify) {
1645 if(!fNotify->Notify()) return -6;
1646 }
1647
1648 // Load the next TTree.
1649 return LoadTree(entry);
1650 } else {
1652 }
1653 }
1654 }
1655
1656
1657 if (!fTree) {
1658 // The Error message already issued. However if we reach here
1659 // we need to make sure that we do not use fTree.
1660 //
1661 // Force a reload of the tree next time.
1662 fTreeNumber = -1;
1663
1664 element->SetLoadResult(returnCode);
1665 return returnCode;
1666 }
1667 // ----- End of modifications by MvL
1668
1669 // Copy the chain's clone list into the new tree's
1670 // clone list so that branch addresses stay synchronized.
1671 if (fClones) {
1672 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
1673 TTree* clone = (TTree*) lnk->GetObject();
1674 ((TChain*) fTree)->TTree::AddClone(clone);
1675 }
1676 }
1677
1678 // Since some of the friends of this chain might simple trees
1679 // (i.e., not really chains at all), we need to execute this
1680 // before calling LoadTree(entry) on the friends (so that
1681 // they use the correct read entry number).
1682
1683 // Change the new current tree to the new entry.
1685 if (loadResult == treeReadEntry) {
1686 element->SetLoadResult(0);
1687 } else {
1688 // This is likely to be an internal error, if treeReadEntry was not in range
1689 // (or intentionally -2 for TChain::GetEntries) then something happened
1690 // that is very odd/surprising.
1691 element->SetLoadResult(-5);
1692 }
1693
1694
1695 // Change the chain friends to the new entry.
1696 if (fFriends) {
1697 // An alternative would move this code to each of the function
1698 // calling LoadTree (and to overload a few more).
1699 TIter next(fFriends);
1700 TFriendLock lock(this, kLoadTree);
1701 TFriendElement* fe = nullptr;
1702 while ((fe = (TFriendElement*) next())) {
1703 TTree* t = fe->GetTree();
1704 if (!t) continue;
1705 if (t->GetTreeIndex()) {
1706 t->GetTreeIndex()->UpdateFormulaLeaves(GetTree());
1707 }
1708 if (t->GetTree() && t->GetTree()->GetTreeIndex()) {
1709 t->GetTree()->GetTreeIndex()->UpdateFormulaLeaves(GetTree());
1710 }
1711 if (treeReadEntry == -2) {
1712 // an entry after the end of the chain was requested (it usually happens when GetEntries is called)
1713 t->LoadTree(entry);
1714 } else {
1715 t->LoadTreeFriend(entry, this);
1716 }
1717 TTree* friend_t = t->GetTree();
1718 if (friend_t) {
1719 auto localfe = fTree->AddFriend(t, fe->GetName());
1721 }
1722 }
1723 }
1724
1727
1730
1731 // Set the branch statuses for the newly opened file.
1732 TIter next(fStatus);
1733 while ((element = (TChainElement*) next())) {
1734 Int_t status = element->GetStatus();
1735 if (element->IsDelayed()) {
1736 // In case we don't want spurious error message about missing branch in this tree
1737 UInt_t dummyFound = std::numeric_limits<UInt_t>::max();
1738 // Only set the branch status if it has a value provided
1739 // by the user
1740 if (status != -1)
1741 fTree->SetBranchStatus(element->GetName(), status, &dummyFound);
1742 } else {
1743 // Only set the branch status if it has a value provided
1744 // by the user
1745 if (status != -1)
1746 fTree->SetBranchStatus(element->GetName(), status);
1747 }
1748 }
1749
1750 // Set the branch addresses for the newly opened file.
1751 next.Reset();
1752 while ((element = (TChainElement*) next())) {
1753 void* addr = element->GetBaddress();
1754 if (addr) {
1755 TBranch* br = fTree->GetBranch(element->GetName());
1756 TBranch** pp = element->GetBranchPtr();
1757 if (pp) {
1758 // FIXME: What if br is zero here?
1759 *pp = br;
1760 }
1761 if (br) {
1762 if (!element->GetCheckedType()) {
1763 Int_t res = CheckBranchAddressType(br, TClass::GetClass(element->GetBaddressClassName()),
1764 (EDataType) element->GetBaddressType(), element->GetBaddressIsPtr());
1765 if ((res & kNeedEnableDecomposedObj) && !br->GetMakeClass()) {
1766 br->SetMakeClass(true);
1767 }
1768 element->SetDecomposedObj(br->GetMakeClass());
1769 element->SetCheckedType(true);
1770 }
1771 // FIXME: We may have to tell the branch it should
1772 // not be an owner of the object pointed at.
1773 br->SetAddress(addr);
1774 if (TestBit(kAutoDelete)) {
1775 br->SetAutoDelete(true);
1776 }
1777 }
1778 }
1779 }
1780
1781 // Update the addresses of the chain's cloned trees, if any.
1782 if (fClones) {
1783 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
1784 TTree* clone = (TTree*) lnk->GetObject();
1785 CopyAddresses(clone);
1786 }
1787 }
1788
1789 // Update list of leaves in all TTreeFormula's of the TTreePlayer (if any).
1790 if (fPlayer) {
1792 }
1793
1794 // Notify user we have switched trees if requested.
1795 if (fNotify) {
1796 if(!fNotify->Notify()) return -6;
1797 }
1798
1799 // Return the new local entry number.
1800 return treeReadEntry;
1801}
1802
1803////////////////////////////////////////////////////////////////////////////////
1804/// Check / locate the files in the chain.
1805/// By default only the files not yet looked up are checked.
1806/// Use force = true to check / re-check every file.
1807
1809{
1810 TIter next(fFiles);
1811 TChainElement* element = nullptr;
1813 printf("\n");
1814 printf("TChain::Lookup - Looking up %d files .... \n", nelements);
1815 Int_t nlook = 0;
1816 TFileStager *stg = nullptr;
1817 while ((element = (TChainElement*) next())) {
1818 // Do not do it more than needed
1819 if (element->HasBeenLookedUp() && !force) continue;
1820 // Count
1821 nlook++;
1822 // Get the Url
1823 TUrl elemurl(element->GetTitle(), true);
1824 // Save current options and anchor
1825 TString anchor = elemurl.GetAnchor();
1826 TString options = elemurl.GetOptions();
1827 // Reset options and anchor
1828 elemurl.SetOptions("");
1829 elemurl.SetAnchor("");
1830 // Locate the file
1831 TString eurl(elemurl.GetUrl());
1832 if (!stg || !stg->Matches(eurl)) {
1833 SafeDelete(stg);
1834 {
1837 }
1838 if (!stg) {
1839 Error("Lookup", "TFileStager instance cannot be instantiated");
1840 break;
1841 }
1842 }
1843 Int_t n1 = (nelements > 100) ? (Int_t) nelements / 100 : 1;
1844 if (stg->Locate(eurl.Data(), eurl) == 0) {
1845 if (nlook > 0 && !(nlook % n1)) {
1846 printf("Lookup | %3d %% finished\r", 100 * nlook / nelements);
1847 fflush(stdout);
1848 }
1849 // Get the effective end-point Url
1850 elemurl.SetUrl(eurl);
1851 // Restore original options and anchor, if any
1852 elemurl.SetOptions(options);
1853 elemurl.SetAnchor(anchor);
1854 // Save it into the element
1855 element->SetTitle(elemurl.GetUrl());
1856 // Remember
1857 element->SetLookedUp();
1858 } else {
1859 // Failure: remove
1862 Error("Lookup", "file %s does not exist\n", eurl.Data());
1863 else
1864 Error("Lookup", "file %s cannot be read\n", eurl.Data());
1865 }
1866 }
1867 if (nelements > 0)
1868 printf("Lookup | %3d %% finished\n", 100 * nlook / nelements);
1869 else
1870 printf("\n");
1871 fflush(stdout);
1872 SafeDelete(stg);
1873}
1874
1875////////////////////////////////////////////////////////////////////////////////
1876/// List the chain.
1877
1879{
1881 TIter next(fFiles);
1882 TChainElement* file = nullptr;
1884 while ((file = (TChainElement*)next())) {
1885 file->ls(option);
1886 }
1888}
1889
1890////////////////////////////////////////////////////////////////////////////////
1891/// Merge all the entries in the chain into a new tree in a new file.
1892///
1893/// See important note in the following function Merge().
1894///
1895/// If the chain is expecting the input tree inside a directory,
1896/// this directory is NOT created by this routine.
1897///
1898/// So in a case where we have:
1899/// ~~~ {.cpp}
1900/// TChain ch("mydir/mytree");
1901/// ch.Merge("newfile.root");
1902/// ~~~
1903/// The resulting file will have not subdirectory. To recreate
1904/// the directory structure do:
1905/// ~~~ {.cpp}
1906/// TFile* file = TFile::Open("newfile.root", "RECREATE");
1907/// file->mkdir("mydir")->cd();
1908/// ch.Merge(file, 0);
1909/// ~~~
1910
1912{
1913 TFile *file = TFile::Open(name, "recreate", "chain files", 1);
1914 return Merge(file, 0, option);
1915}
1916
1917////////////////////////////////////////////////////////////////////////////////
1918/// Merge all chains in the collection. (NOT IMPLEMENTED)
1919
1920Long64_t TChain::Merge(TCollection* /* list */, Option_t* /* option */ )
1921{
1922 Error("Merge", "not implemented");
1923 return -1;
1924}
1925
1926////////////////////////////////////////////////////////////////////////////////
1927/// Merge all chains in the collection. (NOT IMPLEMENTED)
1928
1930{
1931 Error("Merge", "not implemented");
1932 return -1;
1933}
1934
1935////////////////////////////////////////////////////////////////////////////////
1936/// Merge all the entries in the chain into a new tree in the current file.
1937///
1938/// Note: The "file" parameter is *not* the file where the new
1939/// tree will be inserted. The new tree is inserted into
1940/// gDirectory, which is usually the most recently opened
1941/// file, or the directory most recently cd()'d to.
1942///
1943/// If option = "C" is given, the compression level for all branches
1944/// in the new Tree is set to the file compression level. By default,
1945/// the compression level of all branches is the original compression
1946/// level in the old trees.
1947///
1948/// If basketsize > 1000, the basket size for all branches of the
1949/// new tree will be set to basketsize.
1950///
1951/// Example using the file generated in $ROOTSYS/test/Event
1952/// merge two copies of Event.root
1953/// ~~~ {.cpp}
1954/// gSystem.Load("libEvent");
1955/// TChain ch("T");
1956/// ch.Add("Event1.root");
1957/// ch.Add("Event2.root");
1958/// ch.Merge("all.root");
1959/// ~~~
1960/// If the chain is expecting the input tree inside a directory,
1961/// this directory is NOT created by this routine.
1962///
1963/// So if you do:
1964/// ~~~ {.cpp}
1965/// TChain ch("mydir/mytree");
1966/// ch.Merge("newfile.root");
1967/// ~~~
1968/// The resulting file will not have subdirectories. In order to
1969/// preserve the directory structure do the following instead:
1970/// ~~~ {.cpp}
1971/// TFile* file = TFile::Open("newfile.root", "RECREATE");
1972/// file->mkdir("mydir")->cd();
1973/// ch.Merge(file, 0);
1974/// ~~~
1975/// If 'option' contains the word 'fast' the merge will be done without
1976/// unzipping or unstreaming the baskets (i.e., a direct copy of the raw
1977/// bytes on disk).
1978///
1979/// When 'fast' is specified, 'option' can also contains a
1980/// sorting order for the baskets in the output file.
1981///
1982/// There is currently 3 supported sorting order:
1983/// ~~~ {.cpp}
1984/// SortBasketsByOffset (the default)
1985/// SortBasketsByBranch
1986/// SortBasketsByEntry
1987/// ~~~
1988/// When using SortBasketsByOffset the baskets are written in
1989/// the output file in the same order as in the original file
1990/// (i.e. the basket are sorted on their offset in the original
1991/// file; Usually this also means that the baskets are sorted
1992/// on the index/number of the _last_ entry they contain)
1993///
1994/// When using SortBasketsByBranch all the baskets of each
1995/// individual branches are stored contiguously. This tends to
1996/// optimize reading speed when reading a small number (1->5) of
1997/// branches, since all their baskets will be clustered together
1998/// instead of being spread across the file. However it might
1999/// decrease the performance when reading more branches (or the full
2000/// entry).
2001///
2002/// When using SortBasketsByEntry the baskets with the lowest
2003/// starting entry are written first. (i.e. the baskets are
2004/// sorted on the index/number of the first entry they contain).
2005/// This means that on the file the baskets will be in the order
2006/// in which they will be needed when reading the whole tree
2007/// sequentially.
2008///
2009/// ## IMPORTANT Note 1: AUTOMATIC FILE OVERFLOW
2010///
2011/// When merging many files, it may happen that the resulting file
2012/// reaches a size > TTree::fgMaxTreeSize (default = 100 GBytes).
2013/// In this case the current file is automatically closed and a new
2014/// file started. If the name of the merged file was "merged.root",
2015/// the subsequent files will be named "merged_1.root", "merged_2.root",
2016/// etc. fgMaxTreeSize may be modified via the static function
2017/// TTree::SetMaxTreeSize.
2018/// When in fast mode, the check and switch is only done in between each
2019/// input file.
2020///
2021/// ## IMPORTANT Note 2: The output file is automatically closed and deleted.
2022///
2023/// This is required because in general the automatic file overflow described
2024/// above may happen during the merge.
2025/// If only the current file is produced (the file passed as first argument),
2026/// one can instruct Merge to not close and delete the file by specifying
2027/// the option "keep".
2028///
2029/// The function returns the total number of files produced.
2030/// To check that all files have been merged use something like:
2031/// ~~~ {.cpp}
2032/// if (newchain->GetEntries()!=oldchain->GetEntries()) {
2033/// ... not all the file have been copied ...
2034/// }
2035/// ~~~
2036
2038{
2039 // We must have been passed a file, we will use it
2040 // later to reset the compression level of the branches.
2041 if (!file) {
2042 // FIXME: We need an error message here.
2043 return 0;
2044 }
2045
2046 // Options
2047 bool fastClone = false;
2048 TString opt = option;
2049 opt.ToLower();
2050 if (opt.Contains("fast")) {
2051 fastClone = true;
2052 }
2053
2054 // The chain tree must have a list of branches
2055 // because we may try to change their basket
2056 // size later.
2058 if (!lbranches) {
2059 // FIXME: We need an error message here.
2060 return 0;
2061 }
2062
2063 // The chain must have a current tree because
2064 // that is the one we will clone.
2065 if (!fTree) {
2066 // -- LoadTree() has not yet been called, no current tree.
2067 // FIXME: We need an error message here.
2068 return 0;
2069 }
2070
2071 // Copy the chain's current tree without
2072 // copying any entries, we will do that later.
2073 TTree* newTree = CloneTree(0);
2074 if (!newTree) {
2075 // FIXME: We need an error message here.
2076 return 0;
2077 }
2078
2079 // Strip out the (potential) directory name.
2080 // FIXME: The merged chain may or may not have the
2081 // same name as the original chain. This is
2082 // bad because the chain name determines the
2083 // names of the trees in the chain by default.
2084 newTree->SetName(gSystem->BaseName(GetName()));
2085
2086 // FIXME: Why do we do this?
2087 newTree->SetAutoSave(2000000000);
2088
2089 // Circularity is incompatible with merging, it may
2090 // force us to throw away entries, which is not what
2091 // we are supposed to do.
2092 newTree->SetCircular(0);
2093
2094 // Reset the compression level of the branches.
2095 if (opt.Contains("c")) {
2096 TBranch* branch = nullptr;
2097 TIter nextb(newTree->GetListOfBranches());
2098 while ((branch = (TBranch*) nextb())) {
2099 branch->SetCompressionSettings(file->GetCompressionSettings());
2100 }
2101 }
2102
2103 // Reset the basket size of the branches.
2104 if (basketsize > 1000) {
2105 TBranch* branch = nullptr;
2106 TIter nextb(newTree->GetListOfBranches());
2107 while ((branch = (TBranch*) nextb())) {
2108 branch->SetBasketSize(basketsize);
2109 }
2110 }
2111
2112 // Copy the entries.
2113 if (fastClone) {
2114 if ( newTree->CopyEntries( this, -1, option ) < 0 ) {
2115 // There was a problem!
2116 Error("Merge", "TTree has not been cloned\n");
2117 }
2118 } else {
2119 newTree->CopyEntries( this, -1, option );
2120 }
2121
2122 // Write the new tree header.
2123 newTree->Write();
2124
2125 // Get our return value.
2126 Int_t nfiles = newTree->GetFileNumber() + 1;
2127
2128 // Close and delete the current file of the new tree.
2129 if (!opt.Contains("keep")) {
2130 // Delete the currentFile and the TTree object.
2131 delete newTree->GetCurrentFile();
2132 }
2133 return nfiles;
2134}
2135
2136////////////////////////////////////////////////////////////////////////////////
2137/// Get the tree url or filename and other information from the name
2138///
2139/// A treename and a url's query section is split off from name. The
2140/// splitting depends on whether the resulting filename is to be
2141/// subsequently treated for wildcards or not, since the question mark is
2142/// both the url query identifier and a wildcard. Wildcard matching is not
2143/// done in this method itself.
2144/// ~~~ {.cpp}
2145/// [xxx://host]/a/path/file_name[?query[#treename]]
2146/// ~~~
2147///
2148/// The following way to specify the treename is still supported with the
2149/// constrain that the file name contains the sub-string '.root'.
2150/// This is now deprecated and will be removed in future versions.
2151/// ~~~ {.cpp}
2152/// [xxx://host]/a/path/file.root[.oext][/treename]
2153/// [xxx://host]/a/path/file.root[.oext][/treename][?query]
2154/// ~~~
2155///
2156/// Note that in a case like this
2157/// ~~~ {.cpp}
2158/// [xxx://host]/a/path/file#treename
2159/// ~~~
2160/// i.e. anchor but no options (query), the filename will be the full path, as
2161/// the anchor may be the internal file name of an archive. Use '?#%treename' to
2162/// pass the treename if the query field is empty.
2163///
2164/// \param[in] name is the original name
2165/// \param[out] filename the url or filename to be opened or matched
2166/// \param[out] treename the treename, which may be found in a url fragment section
2167/// as a trailing part of the name (deprecated).
2168/// If not found this will be empty.
2169/// Exception: a fragment containing the '=' character is _not_
2170/// interpreted as a treename
2171/// \param[out] query is the url query section, including the leading question
2172/// mark. If not found or the query section is only followed by
2173/// a fragment this will be empty.
2174/// \param[out] suffix the portion of name which was removed to from filename.
2175
2177 TString &suffix) const
2178{
2179 Ssiz_t pIdx = kNPOS;
2180 filename.Clear();
2181 treename.Clear();
2182 query.Clear();
2183 suffix.Clear();
2184
2185 // General case
2186 TUrl url(name, true);
2187 filename = (strcmp(url.GetProtocol(), "file")) ? url.GetUrl() : url.GetFileAndOptions();
2188
2189 TString fn = url.GetFile();
2190 // Extract query, if any
2191 if (url.GetOptions() && (strlen(url.GetOptions()) > 0))
2192 query.Form("?%s", url.GetOptions());
2193 // The treename can be passed as anchor
2194 const char *anchor = url.GetAnchor();
2195 if (anchor && anchor[0] != '\0') {
2196 // Support "?#tree_name" and "?query#tree_name"
2197 // "#tree_name" (no '?' is for tar archives)
2198 // If the treename would contain a '=', treat the anchor as part of the query instead. This makes sure
2199 // that Davix parameters are passed.
2200 if (!query.IsNull() || strstr(name, "?#")) {
2201 if (strstr(anchor, "=")) {
2202 query.Append("#");
2203 query.Append(anchor);
2204 } else {
2205 treename = anchor;
2206 }
2207 } else {
2208 // The anchor is part of the file name
2209 fn = url.GetFileAndOptions();
2210 }
2211 }
2212 // Suffix
2213 suffix = url.GetFileAndOptions();
2214 // Get options from suffix by removing the file name
2215 suffix.Replace(suffix.Index(fn), fn.Length(), "");
2216 // Remove the options suffix from the original file name
2217 filename.Replace(filename.Index(suffix), suffix.Length(), "");
2218
2219 // Special case: [...]file.root/treename
2220 static const char *dotr = ".root";
2221 static Ssiz_t dotrl = strlen(dotr);
2222 // Find the last one
2223 Ssiz_t js = filename.Index(dotr);
2224 while (js != kNPOS) {
2225 pIdx = js;
2226 js = filename.Index(dotr, js + 1);
2227 }
2228 if (pIdx != kNPOS) {
2229 static const char *slash = "/";
2230 static Ssiz_t slashl = strlen(slash);
2231 // Find the last one
2232 Ssiz_t ppIdx = filename.Index(slash, pIdx + dotrl);
2233 if (ppIdx != kNPOS) {
2234 // Good treename with the old recipe
2235 treename = filename(ppIdx + slashl, filename.Length());
2236 filename.Remove(ppIdx + slashl - 1);
2237 suffix.Insert(0, TString::Format("/%s", treename.Data()));
2238 }
2239 }
2240}
2241
2242////////////////////////////////////////////////////////////////////////////////
2243/// Print the header information of each tree in the chain.
2244/// See TTree::Print for a list of options.
2245
2247{
2248 TIter next(fFiles);
2250 while ((element = (TChainElement*)next())) {
2251 Printf("******************************************************************************");
2252 Printf("*Chain :%-10s: %-54s *", GetName(), element->GetTitle());
2253 Printf("******************************************************************************");
2254 TFile *file = TFile::Open(element->GetTitle());
2255 if (file && !file->IsZombie()) {
2256 TTree *tree = (TTree*)file->Get(element->GetName());
2257 if (tree) tree->Print(option);
2258 }
2259 delete file;
2260 }
2261}
2262
2263////////////////////////////////////////////////////////////////////////////////
2264/// Process all entries in this chain, calling functions in filename.
2265/// The return value is -1 in case of error and TSelector::GetStatus() in
2266/// in case of success.
2267/// See TTree::Process.
2268
2270{
2271 if (LoadTree(firstentry) < 0) {
2272 return 0;
2273 }
2275}
2276
2277////////////////////////////////////////////////////////////////////////////////
2278/// Process this chain executing the code in selector.
2279/// The return value is -1 in case of error and TSelector::GetStatus() in
2280/// in case of success.
2281
2286
2287////////////////////////////////////////////////////////////////////////////////
2288/// Make sure that obj (which is being deleted or will soon be) is no
2289/// longer referenced by this TTree.
2290
2292{
2293 if (fFile == obj) {
2294 fFile = nullptr;
2295 fDirectory = nullptr;
2296 fTree = nullptr;
2297 }
2298 if (fDirectory == obj) {
2299 fDirectory = nullptr;
2300 fTree = nullptr;
2301 }
2302 if (fTree == obj) {
2303 fTree = nullptr;
2304 }
2305}
2306
2307////////////////////////////////////////////////////////////////////////////////
2308/// Remove a friend from the list of friends.
2309
2311{
2312 // We already have been visited while recursively looking
2313 // through the friends tree, let return
2314
2315 if (!fFriends) {
2316 return;
2317 }
2318
2320
2321 // We need to invalidate the loading of the current tree because its list
2322 // of real friends is now obsolete. It is repairable only from LoadTree.
2324}
2325
2326////////////////////////////////////////////////////////////////////////////////
2327/// Resets the state of this chain.
2328
2330{
2331 delete fFile;
2332 fFile = nullptr;
2333 fNtrees = 0;
2334 fTreeNumber = -1;
2335 fTree = nullptr;
2336 fFile = nullptr;
2337 fFiles->Delete();
2338 fStatus->Delete();
2339 fTreeOffset[0] = 0;
2340 TChainElement* element = new TChainElement("*", "");
2342 fDirectory = nullptr;
2343
2344 TTree::Reset();
2345}
2346
2347////////////////////////////////////////////////////////////////////////////////
2348/// Resets the state of this chain after a merge (keep the customization but
2349/// forget the data).
2350
2352{
2353 fNtrees = 0;
2354 fTreeNumber = -1;
2355 fTree = nullptr;
2356 fFile = nullptr;
2357 fFiles->Delete();
2358 fTreeOffset[0] = 0;
2359
2361}
2362
2363////////////////////////////////////////////////////////////////////////////////
2364/// Save TChain as a C++ statements on output stream out.
2365/// With the option "friend" save the description of all the
2366/// TChain's friend trees or chains as well.
2367
2368void TChain::SavePrimitive(std::ostream &out, Option_t *option)
2369{
2370 static Int_t chCounter = 0;
2371
2372 TString chName = gInterpreter->MapCppName(GetName());
2373 if (chName.IsNull())
2374 chName = "_chain";
2375 ++chCounter;
2376 chName += chCounter;
2377
2378 TString opt = option;
2379 opt.ToLower();
2380
2381 out << " TChain *" << chName.Data() << " = new TChain(\"" << GetName() << "\");" << std::endl;
2382
2383 if (opt.Contains("friend")) {
2384 opt.ReplaceAll("friend", "");
2385 for (TObject *frel : *fFriends) {
2386 TTree *frtree = ((TFriendElement *)frel)->GetTree();
2387 if (dynamic_cast<TChain *>(frtree)) {
2388 if (strcmp(frtree->GetName(), GetName()) != 0)
2389 --chCounter; // make friends get the same chain counter
2390 frtree->SavePrimitive(out, opt.Data());
2391 out << " " << chName.Data() << "->AddFriend(\"" << frtree->GetName() << "\");" << std::endl;
2392 } else { // ordinary friend TTree
2393 TDirectory *file = frtree->GetDirectory();
2394 if (file && dynamic_cast<TFile *>(file))
2395 out << " " << chName.Data() << "->AddFriend(\"" << frtree->GetName() << "\", \"" << file->GetName()
2396 << "\");" << std::endl;
2397 }
2398 }
2399 }
2400 out << std::endl;
2401
2402 for (TObject *el : *fFiles) {
2404 // Save tree file if it is really loaded to the chain
2405 if (chel->GetLoadResult() == 0 && chel->GetEntries() != 0) {
2406 if (chel->GetEntries() == TTree::kMaxEntries) // tree number of entries is not yet known
2407 out << " " << chName.Data() << "->AddFile(\"" << chel->GetTitle() << "\");" << std::endl;
2408 else
2409 out << " " << chName.Data() << "->AddFile(\"" << chel->GetTitle() << "\"," << chel->GetEntries() << ");"
2410 << std::endl;
2411 }
2412 }
2413 out << std::endl;
2414
2415 SaveMarkerAttributes(out, chName.Data(), 1, 1, 1);
2416}
2417
2418////////////////////////////////////////////////////////////////////////////////
2419/// Loop on tree and print entries passing selection.
2420/// - If varexp is 0 (or "") then print only first 8 columns.
2421/// - If varexp = "*" print all columns.
2422/// - Otherwise a columns selection can be made using "var1:var2:var3".
2423/// See TTreePlayer::Scan for more information.
2424
2426{
2427 if (LoadTree(firstentry) < 0) {
2428 return 0;
2429 }
2431}
2432
2433////////////////////////////////////////////////////////////////////////////////
2434/// Set the global branch kAutoDelete bit.
2435///
2436/// When LoadTree loads a new Tree, the branches for which
2437/// the address is set will have the option AutoDelete set
2438/// For more details on AutoDelete, see TBranch::SetAutoDelete.
2439
2441{
2442 if (autodelete) {
2443 SetBit(kAutoDelete, true);
2444 } else {
2445 SetBit(kAutoDelete, false);
2446 }
2447}
2448
2450{
2451 // Set the cache size of the underlying TTree,
2452 // See TTree::SetCacheSize.
2453 // Returns 0 cache state ok (exists or not, as appropriate)
2454 // -1 on error
2455
2456 Int_t res = 0;
2457
2458 // remember user has requested this cache setting
2459 fCacheUserSet = true;
2460
2461 if (fTree) {
2462 res = fTree->SetCacheSize(cacheSize);
2463 } else {
2464 // If we don't have a TTree yet only record the cache size wanted
2465 res = 0;
2466 }
2467 fCacheSize = cacheSize; // Record requested size.
2468 return res;
2469}
2470
2471////////////////////////////////////////////////////////////////////////////////
2472/// Reset the addresses of the branch.
2473
2475{
2477 if (element) {
2478 element->SetBaddress(nullptr);
2479 }
2480 if (fTree) {
2482 }
2483}
2484
2485////////////////////////////////////////////////////////////////////////////////
2486/// Reset the addresses of the branches.
2487
2489{
2490 // We already have been visited while recursively looking
2491 // through the friends tree, let return
2493 return;
2494 }
2495 TIter next(fStatus);
2496 TChainElement* element = nullptr;
2497 while ((element = (TChainElement*) next())) {
2498 element->SetBaddress(nullptr);
2499 }
2500 if (fTree) {
2502 }
2503 if (fFriends) {
2506 auto *frTree = frEl->GetTree();
2507 if (frTree) {
2508 frTree->ResetBranchAddresses();
2509 }
2510 }
2511 }
2512}
2513
2514////////////////////////////////////////////////////////////////////////////////
2515/// Set branch address.
2516///
2517/// \param[in] bname is the name of a branch.
2518/// \param[in] add is the address of the branch.
2519/// \param[in] ptr
2520///
2521/// Note: See the comments in TBranchElement::SetAddress() for a more
2522/// detailed discussion of the meaning of the add parameter.
2523///
2524/// IMPORTANT REMARK:
2525///
2526/// In case TChain::SetBranchStatus is called, it must be called
2527/// BEFORE calling this function.
2528///
2529/// See TTree::CheckBranchAddressType for the semantic of the return value.
2530
2531Int_t TChain::SetBranchAddress(const char *bname, void* add, TBranch** ptr)
2532{
2533 Int_t res = kNoCheck;
2534
2535 // Check if bname is already in the status list.
2536 // If not, create a TChainElement object and set its address.
2538 if (!element) {
2539 element = new TChainElement(bname, "");
2541 }
2542 element->SetBaddress(add);
2543 element->SetBranchPtr(ptr);
2544
2545 if (!fTree && fReadEntry == -1 && fTreeNumber == -1) {
2546 // Try to load the first tree to retrieve the dataset schema
2547 LoadTree(0);
2548 // Something went wrong when loading the first tree (possibly there are no
2549 // files connected to this chain), let the user know.
2550 if (!fTree && fReadEntry == -1 && fTreeNumber == -1)
2551 Warning("SetBranchAddress",
2552 "Could not load the first tree in chain \"%s\", no dataset schema available. Thus, it is not possible "
2553 "to know whether the branch name \"%s\" corresponds to an available branch or not. This could happen "
2554 "if the chain has no files connected yet, make sure to add files to the chain before calling "
2555 "'TChain::SetBranchAddress'.",
2556 GetName(), bname);
2557 }
2558
2559 // Also set address in current tree.
2560 // FIXME: What about the chain clones?
2561 if (fTreeNumber >= 0) {
2562 TBranch* branch = fTree->GetBranch(bname);
2563 if (ptr) {
2564 *ptr = branch;
2565 }
2566 if (branch) {
2567 res = CheckBranchAddressType(branch, TClass::GetClass(element->GetBaddressClassName()), (EDataType) element->GetBaddressType(), element->GetBaddressIsPtr());
2568 if ((res & kNeedEnableDecomposedObj) && !branch->GetMakeClass()) {
2569 branch->SetMakeClass(true);
2570 }
2571 element->SetDecomposedObj(branch->GetMakeClass());
2572 element->SetCheckedType(true);
2573 if (fClones) {
2574 void* oldAdd = branch->GetAddress();
2575 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
2576 TTree* clone = (TTree*) lnk->GetObject();
2577 TBranch* cloneBr = clone->GetBranch(bname);
2578 if (cloneBr && (cloneBr->GetAddress() == oldAdd)) {
2579 // the clone's branch is still pointing to us
2580 cloneBr->SetAddress(add);
2581 if ((res & kNeedEnableDecomposedObj) && !cloneBr->GetMakeClass()) {
2582 cloneBr->SetMakeClass(true);
2583 }
2584 }
2585 }
2586 }
2587
2588 branch->SetAddress(add);
2589 } else {
2590 if (!element->IsDelayed())
2591 Error("SetBranchAddress", "unknown branch -> %s", bname);
2592 return kMissingBranch;
2593 }
2594 } else {
2595 if (ptr) {
2596 *ptr = nullptr;
2597 }
2598 }
2599 return res;
2600}
2601
2602////////////////////////////////////////////////////////////////////////////////
2603/// Check if bname is already in the status list, and if not, create a TChainElement object and set its address.
2604/// See TTree::CheckBranchAddressType for the semantic of the return value.
2605///
2606/// Note: See the comments in TBranchElement::SetAddress() for a more
2607/// detailed discussion of the meaning of the add parameter.
2608
2610{
2611 return SetBranchAddress(bname, add, nullptr, realClass, datatype, isptr);
2612}
2613
2614////////////////////////////////////////////////////////////////////////////////
2615/// Check if bname is already in the status list, and if not, create a TChainElement object and set its address.
2616/// See TTree::CheckBranchAddressType for the semantic of the return value.
2617///
2618/// Note: See the comments in TBranchElement::SetAddress() for a more
2619/// detailed discussion of the meaning of the add parameter.
2620
2621Int_t TChain::SetBranchAddress(const char* bname, void* add, TBranch** ptr, TClass* realClass, EDataType datatype, bool isptr)
2622{
2624 if (!element) {
2625 element = new TChainElement(bname, "");
2627 }
2628 if (realClass) {
2629 element->SetBaddressClassName(realClass->GetName());
2630 }
2631 element->SetBaddressType((UInt_t) datatype);
2632 element->SetBaddressIsPtr(isptr);
2633 element->SetBranchPtr(ptr);
2634
2635 return SetBranchAddress(bname, add, ptr);
2636}
2637
2638////////////////////////////////////////////////////////////////////////////////
2639/// Set branch status to Process or DoNotProcess
2640///
2641/// \param[in] bname is the name of a branch. if bname="*", apply to all branches.
2642/// \param[in] status = 1 branch will be processed,
2643/// = 0 branch will not be processed
2644/// \param[out] found
2645///
2646/// See IMPORTANT REMARKS in TTree::SetBranchStatus and TChain::SetBranchAddress
2647///
2648/// If found is not 0, the number of branch(es) found matching the regular
2649/// expression is returned in *found AND the error message 'unknown branch'
2650/// is suppressed.
2651
2652void TChain::SetBranchStatus(const char* bname, bool status, UInt_t* found)
2653{
2654 // FIXME: We never explicitly set found to zero!
2655
2656 // Check if bname is already in the status list,
2657 // if not create a TChainElement object and set its status.
2659 if (element) {
2661 } else {
2662 element = new TChainElement(bname, "");
2663 }
2665 element->SetStatus(status);
2666 // Also set status in current tree.
2667 if (fTreeNumber >= 0) {
2668 fTree->SetBranchStatus(bname, status, found);
2669 } else if (found) {
2670 *found = 1;
2671 }
2672}
2673
2674////////////////////////////////////////////////////////////////////////////////
2675/// Remove reference to this chain from current directory and add
2676/// reference to new directory dir. dir can be 0 in which case the chain
2677/// does not belong to any directory.
2678
2680{
2681 if (fDirectory == dir) return;
2682 if (fDirectory) fDirectory->Remove(this);
2683 fDirectory = dir;
2684 if (fDirectory) {
2685 fDirectory->Append(this);
2687 } else {
2688 fFile = nullptr;
2689 }
2690}
2691
2692////////////////////////////////////////////////////////////////////////////////
2693/// \brief Set the input entry list (processing the entries of the chain will
2694/// then be limited to the entries in the list).
2695///
2696/// \param[in] elist The entry list to be assigned to this chain.
2697/// \param[in] opt An option string. Possible values are:
2698/// - "" (default): both the file names of the chain elements and the file
2699/// names of the TEntryList sublists are expanded to full path name.
2700/// - "ne": the file names are taken as they are and not expanded
2701/// - "sync": the TChain will go through the TEntryList in lockstep with the
2702/// trees in the chain rather than performing a lookup based on
2703/// treename and filename. This is mostly useful when the TEntryList
2704/// has multiple sublists for the same tree and filename.
2705/// \throws std::runtime_error If option "sync" was chosen and either:
2706/// - \p elist doesn't have sub entry lists.
2707/// - the number of sub entry lists in \p elist is different than the
2708/// number of trees in the chain.
2709/// - any of the sub entry lists in \p elist doesn't correspond to the
2710/// tree of the chain with the same index (i.e. it doesn't share the
2711/// same tree name and file name).
2712///
2713/// This function finds correspondence between the sub-lists of the TEntryList
2714/// and the trees of the TChain.
2715
2717{
2718 if (fEntryList){
2719 //check, if the chain is the owner of the previous entry list
2720 //(it happens, if the previous entry list was created from a user-defined
2721 //TEventList in SetEventList() function)
2723 TEntryList *tmp = fEntryList;
2724 fEntryList = nullptr; // Avoid problem with RecursiveRemove.
2725 delete tmp;
2726 } else {
2727 fEntryList = nullptr;
2728 }
2729 }
2730 if (!elist){
2731 fEntryList = nullptr;
2732 fEventList = nullptr;
2733 return;
2734 }
2735 if (!elist->TestBit(kCanDelete)){
2736 //this is a direct call to SetEntryList, not via SetEventList
2737 fEventList = nullptr;
2738 }
2739 if (elist->GetN() == 0){
2740 fEntryList = elist;
2741 return;
2742 }
2743
2745 Int_t listfound=0;
2747
2748 TEntryList *templist = nullptr;
2749
2750 const auto *subentrylists = elist->GetLists();
2751 if(strcmp(opt, "sync") == 0){
2752 if(!subentrylists){
2753 std::string msg{"In 'TChain::SetEntryList': "};
2754 msg += "the input TEntryList doesn't have sub entry lists. Please make sure too add them through ";
2755 msg += "TEntryList::AddSubList";
2756 throw std::runtime_error(msg);
2757 }
2758 const auto nsubelists = subentrylists->GetEntries();
2759 if(nsubelists != ne){
2760 std::string msg{"In 'TChain::SetEntryList': "};
2761 msg += "the number of sub entry lists in the input TEntryList (";
2762 msg += std::to_string(nsubelists);
2763 msg += ") is not equal to the number of files in the chain (";
2764 msg += std::to_string(ne);
2765 msg += ")";
2766 throw std::runtime_error(msg);
2767 }
2768 }
2769
2770 for (Int_t ie = 0; ie<ne; ie++){
2772 treename = chainElement->GetName();
2773 filename = chainElement->GetTitle();
2774
2775 if(strcmp(opt, "sync") == 0){
2776 // If the user asked for "sync" option, there should be a 1:1 mapping
2777 // between trees in the chain and sub entry lists in the argument elist
2778 // We have already checked that the input TEntryList has a number of
2779 // sub entry lists equal to the number of files in the chain.
2780 templist = static_cast<TEntryList*>(subentrylists->At(ie));
2781 auto elisttreename = templist->GetTreeName();
2782 auto elistfilename = templist->GetFileName();
2783
2785 std::string msg{"In 'TChain::SetEntryList': "};
2786 msg += "the sub entry list at index ";
2787 msg += std::to_string(ie);
2788 msg += " doesn't correspond to treename '";
2789 msg += treename;
2790 msg += "' and filename '";
2791 msg += filename;
2792 msg += "': it has treename '";
2793 msg += elisttreename;
2794 msg += "' and filename '";
2795 msg += elistfilename;
2796 msg += "'";
2797 throw std::runtime_error(msg);
2798 }
2799
2800 }else{
2801 templist = elist->GetEntryList(treename, filename, opt);
2802 }
2803
2804 if (templist) {
2805 listfound++;
2806 templist->SetTreeNumber(ie);
2807 }
2808 }
2809
2810 if (listfound == 0){
2811 Error("SetEntryList", "No list found for the trees in this chain");
2812 fEntryList = nullptr;
2813 return;
2814 }
2815 fEntryList = elist;
2816 TList *elists = elist->GetLists();
2817 bool shift = false;
2818 TIter next(elists);
2819
2820 //check, if there are sub-lists in the entry list, that don't
2821 //correspond to any trees in the chain
2822 while((templist = (TEntryList*)next())){
2823 if (templist->GetTreeNumber() < 0){
2824 shift = true;
2825 break;
2826 }
2827 }
2828 fEntryList->SetShift(shift);
2829
2830}
2831
2832////////////////////////////////////////////////////////////////////////////////
2833/// Set the input entry list (processing the entries of the chain will then be
2834/// limited to the entries in the list). This function creates a special kind
2835/// of entry list (TEntryListFromFile object) that loads lists, corresponding
2836/// to the chain elements, one by one, so that only one list is in memory at a time.
2837///
2838/// If there is an error opening one of the files, this file is skipped and the
2839/// next file is loaded
2840///
2841/// File naming convention:
2842///
2843/// - by default, filename_elist.root is used, where filename is the
2844/// name of the chain element
2845/// - xxx$xxx.root - $ sign is replaced by the name of the chain element
2846///
2847/// If the list name is not specified (by passing filename_elist.root/listname to
2848/// the TChain::SetEntryList() function, the first object of class TEntryList
2849/// in the file is taken.
2850///
2851/// It is assumed, that there are as many list files, as there are elements in
2852/// the chain and they are in the same order
2853
2854void TChain::SetEntryListFile(const char *filename, Option_t * /*opt*/)
2855{
2856
2857 if (fEntryList){
2858 //check, if the chain is the owner of the previous entry list
2859 //(it happens, if the previous entry list was created from a user-defined
2860 //TEventList in SetEventList() function)
2862 TEntryList *tmp = fEntryList;
2863 fEntryList = nullptr; // Avoid problem with RecursiveRemove.
2864 delete tmp;
2865 } else {
2866 fEntryList = nullptr;
2867 }
2868 }
2869
2870 fEventList = nullptr;
2871
2873
2874 Int_t dotslashpos = basename.Index(".root/");
2876 if (dotslashpos>=0) {
2877 // Copy the list name specification
2879 // and remove it from basename
2880 basename.Remove(dotslashpos+5);
2881 }
2884 fEntryList->SetDirectory(nullptr);
2885 ((TEntryListFromFile*)fEntryList)->SetFileNames(fFiles);
2886}
2887
2888////////////////////////////////////////////////////////////////////////////////
2889/// This function transfroms the given TEventList into a TEntryList
2890///
2891/// NOTE, that this function loads all tree headers, because the entry numbers
2892/// in the TEventList are global and have to be recomputed, taking into account
2893/// the number of entries in each tree.
2894///
2895/// The new TEntryList is owned by the TChain and gets deleted when the chain
2896/// is deleted. This TEntryList is returned by GetEntryList() function, and after
2897/// GetEntryList() function is called, the TEntryList is not owned by the chain
2898/// any more and will not be deleted with it.
2899
2901{
2903 if (fEntryList) {
2905 TEntryList *tmp = fEntryList;
2906 fEntryList = nullptr; // Avoid problem with RecursiveRemove.
2907 delete tmp;
2908 } else {
2909 fEntryList = nullptr;
2910 }
2911 }
2912
2913 if (!evlist) {
2914 fEntryList = nullptr;
2915 fEventList = nullptr;
2916 return;
2917 }
2918
2919 char enlistname[100];
2920 snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
2921 TEntryList *enlist = new TEntryList(enlistname, evlist->GetTitle());
2922 enlist->SetDirectory(nullptr);
2923
2924 Int_t nsel = evlist->GetN();
2926 const char *treename;
2927 const char *filename;
2929 //Load all the tree headers if the tree offsets are not known
2930 //It is assumed here, that loading the last tree will load all
2931 //previous ones
2932 printf("loading trees\n");
2933 (const_cast<TChain*>(this))->LoadTree(evlist->GetEntry(evlist->GetN()-1));
2934 }
2935 for (Int_t i=0; i<nsel; i++){
2936 globalentry = evlist->GetEntry(i);
2937 //add some protection from globalentry<0 here
2938 Int_t treenum = 0;
2940 treenum++;
2941 treenum--;
2943 // printf("globalentry=%lld, treeoffset=%lld, localentry=%lld\n", globalentry, fTreeOffset[treenum], localentry);
2946 //printf("entering for tree %s %s\n", treename, filename);
2947 enlist->SetTree(treename, filename);
2948 enlist->Enter(localentry);
2949 }
2950 enlist->SetBit(kCanDelete, true);
2951 enlist->SetReapplyCut(evlist->GetReapplyCut());
2953}
2954
2955////////////////////////////////////////////////////////////////////////////////
2956/// Change the name of this TChain.
2957
2958void TChain::SetName(const char* name)
2959{
2960 if (fGlobalRegistration) {
2961 // Should this be extended to include the call to TTree::SetName?
2962 R__WRITE_LOCKGUARD(ROOT::gCoreMutex); // Take the lock once rather than 3 times.
2963 gROOT->GetListOfCleanups()->Remove(this);
2964 gROOT->GetListOfSpecials()->Remove(this);
2965 gROOT->GetListOfDataSets()->Remove(this);
2966 }
2968 if (fGlobalRegistration) {
2969 // Should this be extended to include the call to TTree::SetName?
2970 R__WRITE_LOCKGUARD(ROOT::gCoreMutex); // Take the lock once rather than 3 times.
2971 gROOT->GetListOfCleanups()->Add(this);
2972 gROOT->GetListOfSpecials()->Add(this);
2973 gROOT->GetListOfDataSets()->Add(this);
2974 }
2975}
2976
2977////////////////////////////////////////////////////////////////////////////////
2978/// Set number of entries per packet for parallel root.
2979
2981{
2982 fPacketSize = size;
2983 TIter next(fFiles);
2985 while ((element = (TChainElement*)next())) {
2986 element->SetPacketSize(size);
2987 }
2988}
2989
2990////////////////////////////////////////////////////////////////////////////////
2991/// Set chain weight.
2992///
2993/// The weight is used by TTree::Draw to automatically weight each
2994/// selected entry in the resulting histogram.
2995/// For example the equivalent of
2996/// ~~~ {.cpp}
2997/// chain.Draw("x","w")
2998/// ~~~
2999/// is
3000/// ~~~ {.cpp}
3001/// chain.SetWeight(w,"global");
3002/// chain.Draw("x");
3003/// ~~~
3004/// By default the weight used will be the weight
3005/// of each Tree in the TChain. However, one can force the individual
3006/// weights to be ignored by specifying the option "global".
3007/// In this case, the TChain global weight will be used for all Trees.
3008
3010{
3011 fWeight = w;
3012 TString opt = option;
3013 opt.ToLower();
3015 if (opt.Contains("global")) {
3017 }
3018}
3019
3020////////////////////////////////////////////////////////////////////////////////
3021/// Stream a class object.
3022
3024{
3025 if (b.IsReading()) {
3026 // Remove using the 'old' name.
3027 {
3029 gROOT->GetListOfCleanups()->Remove(this);
3030 }
3031
3032 UInt_t R__s, R__c;
3033 Version_t R__v = b.ReadVersion(&R__s, &R__c);
3034 if (R__v > 2) {
3035 b.ReadClassBuffer(TChain::Class(), this, R__v, R__s, R__c);
3036 } else {
3037 //====process old versions before automatic schema evolution
3039 b >> fTreeOffsetLen;
3040 b >> fNtrees;
3041 fFiles->Streamer(b);
3042 if (R__v > 1) {
3043 fStatus->Streamer(b);
3045 b.ReadFastArray(fTreeOffset,fTreeOffsetLen);
3046 }
3047 b.CheckByteCount(R__s, R__c, TChain::IsA());
3048 //====end of old versions
3049 }
3050 // Re-add using the new name.
3051 {
3053 gROOT->GetListOfCleanups()->Add(this);
3054 }
3055
3056 } else {
3057 b.WriteClassBuffer(TChain::Class(),this);
3058 }
3059}
3060
3061////////////////////////////////////////////////////////////////////////////////
3062/// Dummy function kept for back compatibility.
3063/// The cache is now activated automatically when processing TTrees/TChain.
3064
3065void TChain::UseCache(Int_t /* maxCacheSize */, Int_t /* pageSize */)
3066{
3067}
3068
3071{
3072 if (!fStatus->FindObject(bname)) {
3073 auto *element = new TChainElement(bname, "");
3076 }
3077
3078 return SetBranchAddress(bname, addr, ptr, ptrClass, datatype, isptr);
3079}
#define SafeDelete(p)
Definition RConfig.hxx:531
#define b(i)
Definition RSha256.hxx:100
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:131
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:83
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
EDataType
Definition TDataType.h:28
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char mode
char name[80]
Definition TGX11.cxx:110
int nentries
#define gInterpreter
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:414
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2509
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
#define R__LOCKGUARD(mutex)
#define R__WRITE_LOCKGUARD(mutex)
#define snprintf
Definition civetweb.c:1579
virtual void SaveMarkerAttributes(std::ostream &out, const char *name, Int_t coldef=1, Int_t stydef=1, Int_t sizdef=1)
Save line attributes as C++ statement(s) on output stream out.
A TTree is a list of TBranches.
Definition TBranch.h:93
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
Buffer base class used for serializing objects.
Definition TBuffer.h:43
A TChainElement describes a component of a TChain.
void ls(Option_t *option="") const override
List files in the chain.
A chain is a collection of files containing TTree objects.
Definition TChain.h:33
TLeaf * FindLeaf(const char *name) override
See TTree::GetReadEntry().
Definition TChain.cxx:859
Int_t SetCacheSize(Long64_t cacheSize=-1) override
Set maximum size of the file cache (TTreeCache) in bytes.
Definition TChain.cxx:2449
virtual void CanDeleteRefs(bool flag=true)
When closing a file during the chain processing, the file may be closed with option "R" if flag is se...
Definition TChain.cxx:749
TObjArray * GetListOfBranches() override
Return a pointer to the list of branches of the current tree.
Definition TChain.cxx:1108
void Streamer(TBuffer &) override
Stream a class object.
Definition TChain.cxx:3023
Long64_t GetEntryNumber(Long64_t entry) const override
Return entry number corresponding to entry.
Definition TChain.cxx:1015
Double_t GetWeight() const override
Return the chain weight.
Definition TChain.cxx:1241
virtual void SetAutoDelete(bool autodel=true)
Set the global branch kAutoDelete bit.
Definition TChain.cxx:2440
bool fCanDeleteRefs
! If true, TProcessIDs are deleted when closing a file
Definition TChain.h:40
Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr, TClass *realClass, EDataType datatype, bool isptr, bool suppressMissingBranchError) override
Definition TChain.cxx:3069
void SetEntryList(TEntryList *elist, Option_t *opt="") override
Set the input entry list (processing the entries of the chain will then be limited to the entries in ...
Definition TChain.cxx:2716
Int_t fNtrees
Number of trees.
Definition TChain.h:37
TFriendElement * AddFriend(const char *chainname, const char *dummy="") override
Add a TFriendElement to the list of friends of this chain.
Definition TChain.cxx:660
void DirectoryAutoAdd(TDirectory *) override
Override the TTree::DirectoryAutoAdd behavior: we never auto add.
Definition TChain.cxx:788
~TChain() override
Destructor.
Definition TChain.cxx:166
Int_t LoadBaskets(Long64_t maxmemory) override
Dummy function.
Definition TChain.cxx:1296
TTree * GetTree() const override
Definition TChain.h:123
void Print(Option_t *option="") const override
Print the header information of each tree in the chain.
Definition TChain.cxx:2246
void RecursiveRemove(TObject *obj) override
Make sure that obj (which is being deleted or will soon be) is no longer referenced by this TTree.
Definition TChain.cxx:2291
const char * GetAlias(const char *aliasName) const override
Returns the expanded value of the alias. Search in the friends if any.
Definition TChain.cxx:893
TChain(const TChain &)
TClass * IsA() const override
Definition TChain.h:175
virtual Int_t AddFile(const char *name, Long64_t nentries=TTree::kMaxEntries, const char *tname="")
Add a new file to this chain.
Definition TChain.cxx:479
void Reset(Option_t *option="") override
Resets the state of this chain.
Definition TChain.cxx:2329
void ResetAfterMerge(TFileMergeInfo *) override
Resets the state of this chain after a merge (keep the customization but forget the data).
Definition TChain.cxx:2351
Long64_t * fTreeOffset
[fTreeOffsetLen] Array of variables
Definition TChain.h:39
TBranch * FindBranch(const char *name) override
See TTree::GetReadEntry().
Definition TChain.cxx:825
void ResetBranchAddresses() override
Reset the addresses of the branches.
Definition TChain.cxx:2488
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save TChain as a C++ statements on output stream out.
Definition TChain.cxx:2368
void SetEventList(TEventList *evlist) override
This function transfroms the given TEventList into a TEntryList.
Definition TChain.cxx:2900
TObjArray * GetListOfLeaves() override
Return a pointer to the list of leaves of the current tree.
Definition TChain.cxx:1125
bool GetBranchStatus(const char *branchname) const override
See TTree::GetReadEntry().
Definition TChain.cxx:927
TBranch * GetBranch(const char *name) override
Return pointer to the branch name in the current tree.
Definition TChain.cxx:912
Long64_t Scan(const char *varexp="", const char *selection="", Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0) override
Loop on tree and print entries passing selection.
Definition TChain.cxx:2425
Double_t GetMaximum(const char *columname) override
Return maximum of column with name columname.
Definition TChain.cxx:1140
void SetWeight(Double_t w=1, Option_t *option="") override
Set chain weight.
Definition TChain.cxx:3009
static TClass * Class()
Long64_t Process(const char *filename, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0) override
Process all entries in this chain, calling functions in filename.
Definition TChain.cxx:2269
void RemoveFriend(TTree *) override
Remove a friend from the list of friends.
Definition TChain.cxx:2310
virtual Int_t AddFileInfoList(TCollection *list, Long64_t nfiles=TTree::kMaxEntries)
Add all files referenced in the list to the chain.
Definition TChain.cxx:574
virtual void CreatePackets()
Initialize the packet descriptor string.
Definition TChain.cxx:775
void ResetBranchAddress(TBranch *) override
Reset the addresses of the branch.
Definition TChain.cxx:2474
TList * fStatus
-> List of active/inactive branches (TChainElement, owned)
Definition TChain.h:44
void SetDirectory(TDirectory *dir) override
Remove reference to this chain from current directory and add reference to new directory dir.
Definition TChain.cxx:2679
Double_t GetMinimum(const char *columname) override
Return minimum of column with name columname.
Definition TChain.cxx:1175
virtual Long64_t Merge(const char *name, Option_t *option="")
Merge all the entries in the chain into a new tree in a new file.
Definition TChain.cxx:1911
TTree * fTree
! Pointer to current tree (Note: We do not own this tree.)
Definition TChain.h:41
virtual Int_t Add(TChain *chain)
Add all files referenced by the passed chain to this chain.
Definition TChain.cxx:211
void ParseTreeFilename(const char *name, TString &filename, TString &treename, TString &query, TString &suffix) const
Get the tree url or filename and other information from the name.
Definition TChain.cxx:2176
bool InPlaceClone(TDirectory *newdirectory, const char *options="") override
Move content to a new file. (NOT IMPLEMENTED for TChain)
Definition TChain.cxx:1259
Int_t GetNbranches() override
Return the number of branches of the current tree.
Definition TChain.cxx:1212
Long64_t Draw(const char *varexp, const TCut &selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0) override
Draw expression varexp for selected entries.
Definition TChain.cxx:803
bool fGlobalRegistration
! if true, bypass use of global lists
Definition TChain.h:45
virtual void SetEntryListFile(const char *filename="", Option_t *opt="")
Set the input entry list (processing the entries of the chain will then be limited to the entries in ...
Definition TChain.cxx:2854
Long64_t GetChainEntryNumber(Long64_t entry) const override
Return absolute entry number in the chain.
Definition TChain.cxx:948
Int_t fTreeOffsetLen
Current size of fTreeOffset array.
Definition TChain.h:36
void SetName(const char *name) override
Change the name of this TChain.
Definition TChain.cxx:2958
void ls(Option_t *option="") const override
List the chain.
Definition TChain.cxx:1878
void SetBranchStatus(const char *bname, bool status=true, UInt_t *found=nullptr) override
Set branch status to Process or DoNotProcess.
Definition TChain.cxx:2652
Long64_t LoadTree(Long64_t entry) override
Find the tree which contains entry, and set it as the current tree.
Definition TChain.cxx:1416
TClusterIterator GetClusterIterator(Long64_t firstentry) override
Return an iterator over the cluster of baskets starting at firstentry.
Definition TChain.cxx:937
void Browse(TBrowser *) override
Browse the contents of the chain.
Definition TChain.cxx:731
virtual TTree * CopyTree(const char *selection, Option_t *option="", Long64_t nentries=kMaxEntries, Long64_t firstentry=0) override
Copy a tree with selection.
Definition TChain.cxx:762
TObjArray * fFiles
-> List of file names containing the trees (TChainElement, owned)
Definition TChain.h:43
Long64_t GetReadEntry() const override
See TTree::GetReadEntry().
Definition TChain.cxx:1227
TFile * fFile
! Pointer to current file (We own the file).
Definition TChain.h:42
virtual void UseCache(Int_t maxCacheSize=10, Int_t pageSize=0)
Dummy function kept for back compatibility.
Definition TChain.cxx:3065
void InvalidateCurrentTree()
Set the TTree to be reloaded as soon as possible.
Definition TChain.cxx:1278
Long64_t GetEntries() const override
Return the total number of entries in the chain.
Definition TChain.cxx:958
TFile * GetFile() const
Return a pointer to the current file.
Definition TChain.cxx:1060
Int_t GetEntry(Long64_t entry=0, Int_t getall=0) override
Get entry from the file to memory.
Definition TChain.cxx:996
virtual void SetPacketSize(Int_t size=100)
Set number of entries per packet for parallel root.
Definition TChain.cxx:2980
Int_t fTreeNumber
! Current Tree number in fTreeOffset table
Definition TChain.h:38
Int_t GetTreeNumber() const override
Definition TChain.h:124
void Lookup(bool force=false)
Check / locate the files in the chain.
Definition TChain.cxx:1808
Long64_t RefreshFriendAddresses()
Refresh branch/leaf addresses of friend trees.
Definition TChain.cxx:1308
TLeaf * GetLeaf(const char *branchname, const char *leafname) override
Return a pointer to the leaf name in the current tree.
Definition TChain.cxx:1073
Int_t GetEntryWithIndex(Long64_t major, Long64_t minor=0) override
Return entry corresponding to major and minor number.
Definition TChain.cxx:1049
@ kAutoDelete
Definition TChain.h:67
@ kGlobalWeight
Definition TChain.h:66
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
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:2973
Collection abstract base class.
Definition TCollection.h:65
A specialized string object used for TTree selections.
Definition TCut.h:25
TObject * Get(const char *namecycle) override
Return pointer to object identified by namecycle.
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
Describe directory structure in memory.
Definition TDirectory.h:45
virtual TList * GetList() const
Definition TDirectory.h:223
virtual void Append(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
virtual void Add(TObject *obj, Bool_t replace=kFALSE)
Append object to this directory.
Definition TDirectory.h:184
virtual TFile * GetFile() const
Definition TDirectory.h:221
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
Manages entry lists from different files, when they are not loaded in memory at the same time.
A List of entry numbers in a TTree or TChain.
Definition TEntryList.h:26
virtual TEntryList * GetEntryList(const char *treename, const char *filename, Option_t *opt="")
Return the entry list, corresponding to treename and filename By default, the filename is first tried...
virtual TList * GetLists() const
Definition TEntryList.h:76
virtual void SetShift(bool shift)
Definition TEntryList.h:102
virtual Long64_t GetEntryAndTree(Long64_t index, Int_t &treenum)
Return the index of "index"-th non-zero entry in the TTree or TChain and the # of the corresponding t...
virtual void SetDirectory(TDirectory *dir)
Add reference to directory dir. dir can be 0.
virtual Long64_t GetN() const
Definition TEntryList.h:78
<div class="legacybox"><h2>Legacy Code</h2> TEventList is a legacy interface: there will be no bug fi...
Definition TEventList.h:31
Class describing a generic file including meta information.
Definition TFileInfo.h:39
A class to pass information from the TFileMerger to the objects being merged.
static TFileStager * Open(const char *stager)
Open a stager, after having loaded the relevant plug-in.
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:130
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=nullptr, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition TFile.cxx:2395
Int_t GetCompressionSettings() const
Definition TFile.h:489
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:3765
void Close(Option_t *option="") override
Close a file.
Definition TFile.cxx:958
A TFriendElement TF describes a TTree object TF in a file.
void Reset()
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition TLeaf.h:57
A doubly linked list.
Definition TList.h:38
void Streamer(TBuffer &) override
Stream all objects in the collection to or from the I/O buffer.
Definition TList.cxx:1323
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
virtual TObjLink * FirstLink() const
Definition TList.h:107
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:600
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
An array of TObjects.
Definition TObjArray.h:31
void Streamer(TBuffer &) override
Stream all objects in the array to or from the I/O buffer.
Int_t GetEntries() const override
Return the number of objects in array (i.e.
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * At(Int_t idx) const override
Definition TObjArray.h:170
TObject * UncheckedAt(Int_t i) const
Definition TObjArray.h:90
TObject * Remove(TObject *obj) override
Remove object from array.
void Add(TObject *obj) override
Definition TObjArray.h:68
Collectable string class.
Definition TObjString.h:28
Mother of all ROOT objects.
Definition TObject.h:42
virtual Bool_t Notify()
This method must be overridden to handle object notification (the base implementation is no-op).
Definition TObject.cxx:613
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:226
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1075
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition TObject.h:161
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:882
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:544
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1089
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1117
virtual void ls(Option_t *option="") const
The ls function lists the contents of a class on stdout.
Definition TObject.cxx:593
void ResetBit(UInt_t f)
Definition TObject.h:203
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:70
@ kInvalidObject
if object ctor succeeded but object should not be used
Definition TObject.h:80
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:72
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition TROOT.cxx:2894
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition TROOT.cxx:2751
A TSelector object is used by the TTree::Draw, TTree::Scan, TTree::Process to navigate in a TTree and...
Definition TSelector.h:31
Basic string class.
Definition TString.h:138
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
const char * Data() const
Definition TString.h:384
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:713
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:2384
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
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:1307
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition TSystem.cxx:944
A cache to speed-up the reading of ROOT datasets.
Definition TTreeCache.h:32
Helper class to iterate over cluster of baskets.
Definition TTree.h:314
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition TTree.h:221
A TTree represents a columnar dataset.
Definition TTree.h:89
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition TTree.cxx:1359
virtual TBranch * FindBranch(const char *name)
Return the branch that correspond to the path 'branchname', which can include the name of the tree or...
Definition TTree.cxx:4890
virtual void SetBranchStatus(const char *bname, bool status=true, UInt_t *found=nullptr)
Set branch status to Process or DoNotProcess.
Definition TTree.cxx:8779
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5430
TList * fFriends
pointer to list of friend elements
Definition TTree.h:140
bool fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition TTree.h:152
virtual bool GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition TTree.cxx:5456
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition TTree.h:147
TEventList * fEventList
! Pointer to event selection list (if one)
Definition TTree.h:135
virtual Int_t GetEntry(Long64_t entry, Int_t getall=0)
Read all branches of entry and return total number of bytes read.
Definition TTree.cxx:5718
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition TTree.cxx:5543
virtual void ResetBranchAddress(TBranch *)
Tell a branch to set its address to zero.
Definition TTree.cxx:8258
bool fCacheUserSet
! true if the cache setting was explicitly given by user
Definition TTree.h:151
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition TTree.cxx:5990
virtual TObjArray * GetListOfLeaves()
Definition TTree.h:576
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:3759
void Streamer(TBuffer &) override
Stream a class object.
Definition TTree.cxx:9812
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition TTree.cxx:6416
virtual Double_t GetWeight() const
Definition TTree.h:631
void Draw(Option_t *opt) override
Default Draw method for all objects.
Definition TTree.h:478
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition TTree.h:144
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:9442
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition TTree.cxx:6429
Long64_t fEntries
Number of entries.
Definition TTree.h:94
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition TTree.h:136
virtual TVirtualIndex * GetTreeIndex() const
Definition TTree.h:605
TList * fExternalFriends
! List of TFriendsElement pointing to us and need to be notified of LoadTree. Content not owned.
Definition TTree.h:141
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition TTree.h:717
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:7644
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data).
Definition TTree.cxx:8227
virtual Long64_t GetEntries() const
Definition TTree.h:510
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition TTree.cxx:3173
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:6306
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition TTree.cxx:8196
virtual void SetImplicitMT(bool enabled)
Definition TTree.h:713
Long64_t fMaxVirtualSize
Maximum total size of buffers kept in memory.
Definition TTree.h:109
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition TTree.h:142
Double_t fWeight
Tree weight (see TTree::SetWeight)
Definition TTree.h:100
virtual Long64_t GetReadEntry() const
Definition TTree.h:596
virtual TObjArray * GetListOfBranches()
Definition TTree.h:575
virtual TTree * GetTree() const
Definition TTree.h:604
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition TTree.cxx:6584
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition TTree.cxx:5275
virtual void RemoveFriend(TTree *)
Remove a friend from the list of friends.
Definition TTree.cxx:8170
void Browse(TBrowser *) override
Browse content of the TTree.
Definition TTree.cxx:2639
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:6676
TObject * fNotify
Object to be notified when loading a Tree.
Definition TTree.h:130
virtual TList * GetListOfClones()
Definition TTree.h:574
Long64_t fCacheSize
! Maximum size of file buffers
Definition TTree.h:115
TList * fClones
! List of cloned trees which share our addresses
Definition TTree.h:145
static TClass * Class()
@ kResetBranchAddresses
Definition TTree.h:266
@ kLoadTree
Definition TTree.h:254
virtual void CopyAddresses(TTree *, bool undo=false)
Set branch addresses of passed tree equal to ours.
Definition TTree.cxx:3339
virtual TList * GetListOfFriends() const
Definition TTree.h:577
Long64_t fReadEntry
! Number of the entry being processed
Definition TTree.h:117
virtual Int_t GetNbranches()
Definition TTree.h:589
virtual TLeaf * FindLeaf(const char *name)
Find first leaf containing searchname.
Definition TTree.cxx:4965
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition TTree.h:131
@ kNeedEnableDecomposedObj
Definition TTree.h:288
@ kNoCheck
Definition TTree.h:287
@ kMissingBranch
Definition TTree.h:277
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition TTree.cxx:8268
void SetName(const char *name) override
Change the name of this tree.
Definition TTree.cxx:9470
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache (TTreeCache) in bytes.
Definition TTree.cxx:8932
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:1246
virtual Int_t CheckBranchAddressType(TBranch *branch, TClass *ptrClass, EDataType datatype, bool ptr)
Check whether or not the address described by the last 3 parameters matches the content of the branch...
Definition TTree.cxx:2901
virtual void SetChainOffset(Long64_t offset=0)
Definition TTree.h:696
Int_t fPacketSize
! Number of entries in one packet for parallel root
Definition TTree.h:119
virtual Long64_t GetChainOffset() const
Definition TTree.h:503
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:8306
Int_t fMakeClass
! not zero when processing code generated by MakeClass
Definition TTree.h:125
static constexpr Long64_t kMaxEntries
Used as the max value for any TTree range operation.
Definition TTree.h:273
This class represents a WWW compatible URL.
Definition TUrl.h:33
virtual void SetFile(TFile *)=0
virtual void UpdateFormulaLeaves()=0
std::vector< std::string > ExpandGlob(const std::string &glob)
Expands input glob into a collection of full paths to files.
R__EXTERN TVirtualRWMutex * gCoreMutex
bool StartsWith(std::string_view string, std::string_view prefix)
TCanvas * slash()
Definition slash.C:1