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
66#include <cstdio>
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
170 if (rootAlive && fGlobalRegistration) {
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
197 if (rootAlive && fGlobalRegistration) {
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();
218 Long64_t* trees = new Long64_t[fTreeOffsetLen];
219 for (Int_t i = 0; i <= fNtrees; i++) {
220 trees[i] = fTreeOffset[i];
221 }
222 delete[] fTreeOffset;
223 fTreeOffset = trees;
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);
241 fFiles->Add(newelement);
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{
356 TString basename, treename, query, suffix;
357 ParseTreeFilename(name, basename, treename, query, suffix);
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
368 Ssiz_t lastDotrIdx = kNPOS;
369 Ssiz_t dotrIdx = suffix.Index(dotr);
370 while (dotrIdx != kNPOS) {
371 lastDotrIdx = dotrIdx;
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 {
390 expanded_glob = ROOT::Internal::TreeUtils::ExpandGlob(std::string(basename));
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
489 TString basename, tn, query, suffix;
490 ParseTreeFilename(name, basename, tn, query, suffix);
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;
504 Long64_t *trees = new Long64_t[fTreeOffsetLen];
505 for (Int_t i=0;i<=fNtrees;i++) trees[i] = fTreeOffset[i];
506 delete [] fTreeOffset;
507 fTreeOffset = trees;
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
556 TChainElement* element = new TChainElement(treename, filename);
557 element->SetPacketSize(pksize);
558 element->SetNumberEntries(nentries);
559 fFiles->Add(element);
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
574Int_t TChain::AddFileInfoList(TCollection* filelist, Long64_t nfiles /* = TTree::kMaxEntries */)
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{
751 fCanDeleteRefs = flag;
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
803Long64_t TChain::Draw(const char* varexp, const TCut& selection,
805{
806 return TChain::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
807}
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
814Long64_t TChain::Draw(const char* varexp, const char* selection,
816{
817 GetPlayer();
818 if (LoadTree(firstentry) < 0) return 0;
819 return TTree::Draw(varexp,selection,option,nentries,firstentry);
820}
821
822////////////////////////////////////////////////////////////////////////////////
823/// See TTree::GetReadEntry().
824
825TBranch *TChain::FindBranch(const char *branchname)
826{
827 auto findBranchImpl = [this](const char *resolvedBranchName) -> TBranch * {
828 if (fTree) {
829 return fTree->FindBranch(resolvedBranchName);
830 }
831 LoadTree(0);
832 if (fTree) {
833 return fTree->FindBranch(resolvedBranchName);
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
843 if (ROOT::StartsWith(branchNameView, chainPrefix)) {
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
853 return findBranchImpl(branchname);
854}
855
856////////////////////////////////////////////////////////////////////////////////
857/// See TTree::GetReadEntry().
858
859TLeaf* TChain::FindLeaf(const char* searchname)
860{
861 auto findLeafImpl = [this](const char *resolvedBranchName) -> TLeaf * {
862 if (fTree) {
863 return fTree->FindLeaf(resolvedBranchName);
864 }
865 LoadTree(0);
866 if (fTree) {
867 return fTree->FindLeaf(resolvedBranchName);
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
877 if (ROOT::StartsWith(branchNameView, chainPrefix)) {
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{
929 return TTree::GetBranchStatus(branchname);
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
949{
950 return entry + fTreeOffset[fTreeNumber];
951}
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;
965 Long64_t totalEntries{};
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{
998 Long64_t treeReadEntry = LoadTree(entry);
999 if (treeReadEntry < 0) {
1000 return 0;
1001 }
1002 if (!fTree) {
1003 return 0;
1004 }
1005 return fTree->GetEntry(treeReadEntry, getall);
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;
1020 Long64_t localentry = fEntryList->GetEntryAndTree(entry, treenum);
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){
1025 if (fTreeOffset[treenum]==TTree::kMaxEntries){
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 }
1033 Long64_t globalentry = fTreeOffset[treenum] + localentry;
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{
1051 Long64_t serial = GetEntryNumberWithIndex(major, minor);
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 the number of branches of the current tree.
1139///
1140/// Warning: May set the current tree!
1141
1143{
1144 if (fTree) {
1145 return fTree->GetNbranches();
1146 }
1147 LoadTree(0);
1148 if (fTree) {
1149 return fTree->GetNbranches();
1150 }
1151 return 0;
1152}
1153
1154////////////////////////////////////////////////////////////////////////////////
1155/// See TTree::GetReadEntry().
1156
1158{
1159 return TTree::GetReadEntry();
1160}
1161
1162////////////////////////////////////////////////////////////////////////////////
1163/// Return the chain weight.
1164///
1165/// By default the weight is the weight of the current tree.
1166/// However, if the weight has been set in TChain::SetWeight()
1167/// with the option "global", then that weight will be returned.
1168///
1169/// Warning: May set the current tree!
1170
1172{
1173 if (TestBit(kGlobalWeight)) {
1174 return fWeight;
1175 } else {
1176 if (fTree) {
1177 return fTree->GetWeight();
1178 }
1179 const_cast<TChain*>(this)->LoadTree(0);
1180 if (fTree) {
1181 return fTree->GetWeight();
1182 }
1183 return 0;
1184 }
1185}
1186
1187////////////////////////////////////////////////////////////////////////////////
1188/// Move content to a new file. (NOT IMPLEMENTED for TChain)
1189bool TChain::InPlaceClone(TDirectory * /* new directory */, const char * /* options */)
1190{
1191 Error("InPlaceClone", "not implemented");
1192 return false;
1193}
1194
1195////////////////////////////////////////////////////////////////////////////////
1196/// Set the TTree to be reloaded as soon as possible. In particular this
1197/// is needed when adding a Friend.
1198///
1199/// If the tree has clones, copy them into the chain
1200/// clone list so we can change their branch addresses
1201/// when necessary.
1202///
1203/// This is to support the syntax:
1204/// ~~~ {.cpp}
1205/// TTree* clone = chain->GetTree()->CloneTree(0);
1206/// ~~~
1207
1209{
1210 if (fTree && fTree->GetListOfClones()) {
1211 for (TObjLink* lnk = fTree->GetListOfClones()->FirstLink(); lnk; lnk = lnk->Next()) {
1212 TTree* clone = (TTree*) lnk->GetObject();
1213 AddClone(clone);
1214 }
1215 }
1216 fTreeNumber = -1;
1217 fTree = nullptr;
1218}
1219
1220////////////////////////////////////////////////////////////////////////////////
1221/// Dummy function.
1222/// It could be implemented and load all baskets of all trees in the chain.
1223/// For the time being use TChain::Merge and TTree::LoadBasket
1224/// on the resulting tree.
1225
1227{
1228 Error("LoadBaskets", "Function not yet implemented for TChain.");
1229 return 0;
1230}
1231
1232////////////////////////////////////////////////////////////////////////////////
1233/// Refresh branch/leaf addresses of friend trees
1234///
1235/// The method acts only on the current tree in the chain (fTree), but it may
1236/// be called in two different scenarios: when there are friends of the chain
1237/// or when there are friends of fTree itself.
1239{
1240 assert(fTree != nullptr);
1241
1242 bool needUpdate = false;
1243 if (auto *innerFriendList = fTree->GetListOfFriends()) {
1244 // If the current tree has friends, check if they were mark for update
1245 // when switching to the following tree, detect it so that we later we
1246 // actually refresh the addresses of the friends.
1247 for (auto *frEl : ROOT::Detail::TRangeStaticCast<TFriendElement>(*innerFriendList)) {
1248 if (frEl->IsUpdated()) {
1249 needUpdate = true;
1250 frEl->ResetUpdated();
1251 }
1252 if (frEl->IsUpdatedForChain()) {
1253 needUpdate = true;
1254 frEl->ResetUpdatedForChain();
1255 }
1256 }
1257 }
1258
1259 if (!needUpdate)
1260 return 0;
1261
1262 // Update the branch/leaf addresses and the list of leaves in all
1263 // TTreeFormula of the TTreePlayer (if any).
1265 // Set the branch status of all the chain elements, which may include also
1266 // branches that are available in friends. Only set the branch status
1267 // if it has a value provided by the user
1268 Int_t status = chainEl->GetStatus();
1269 if (status != -1)
1270 fTree->SetBranchStatus(chainEl->GetName(), status);
1271
1272 // Set the branch addresses for the newly opened file.
1273 void *addr = chainEl->GetBaddress();
1274 if (!addr)
1275 continue;
1276
1277 TBranch *br = fTree->GetBranch(chainEl->GetName());
1278 TBranch **pp = chainEl->GetBranchPtr();
1279 if (pp) {
1280 // FIXME: What if br is zero here?
1281 *pp = br;
1282 }
1283 if (!br)
1284 continue;
1285
1286 if (!chainEl->GetCheckedType()) {
1287 Int_t res = CheckBranchAddressType(br, TClass::GetClass(chainEl->GetBaddressClassName()),
1288 (EDataType)chainEl->GetBaddressType(), chainEl->GetBaddressIsPtr());
1289 if ((res & kNeedEnableDecomposedObj) && !br->GetMakeClass()) {
1290 br->SetMakeClass(true);
1291 }
1292 chainEl->SetDecomposedObj(br->GetMakeClass());
1293 chainEl->SetCheckedType(true);
1294 }
1295 // FIXME: We may have to tell the branch it should
1296 // not be an owner of the object pointed at.
1297 br->SetAddress(addr);
1298 if (TestBit(kAutoDelete)) {
1299 br->SetAutoDelete(true);
1300 }
1301 }
1302
1303 // We cannot know a priori if the branch(es) of the friend TChain(s) that were just
1304 // updated were supposed to be connected to one of the TChainElement of this chain
1305 // or possibly to another TChainElement belonging to another chain that has befriended
1306 // this chain (i.e., one of the "external friends"). Thus, we forward the notification
1307 // that one or more friend trees were updated to the friends of this chain.
1308 if (fExternalFriends)
1310 external_fe->MarkUpdated();
1311
1312 if (fPlayer) {
1314 }
1315 // Notify user if requested.
1316 if (fNotify) {
1317 if (!fNotify->Notify())
1318 return -6;
1319 }
1320
1321 return 0;
1322}
1323
1324////////////////////////////////////////////////////////////////////////////////
1325/// Find the tree which contains entry, and set it as the current tree.
1326///
1327/// Returns the entry number in that tree.
1328///
1329/// The input argument entry is the entry serial number in the whole chain.
1330///
1331/// In case of error, LoadTree returns a negative number:
1332/// * -1: The chain is empty.
1333/// * -2: The requested entry number is less than zero or too large for the chain.
1334/// * -3: The file corresponding to the entry could not be correctly opened
1335/// * -4: The TChainElement corresponding to the entry is missing or
1336/// the TTree is missing from the file.
1337/// * -5: Internal error, please report the circumstance when this happen
1338/// as a ROOT issue.
1339/// * -6: An error occurred within the notify callback.
1340///
1341/// Calls fNotify->Notify() (if fNotify is not null) when starting the processing of a new sub-tree.
1342/// See TNotifyLink for more information on the notification mechanism.
1343///
1344/// \note This is the only routine which sets the value of fTree to a non-zero pointer.
1345///
1347{
1348 // We already have been visited while recursively looking
1349 // through the friends tree, let's return.
1351 return 0;
1352 }
1353
1354 if (!fNtrees) {
1355 // -- The chain is empty.
1356 return -1;
1357 }
1358
1359 if ((entry < 0) || ((entry > 0) && (entry >= fEntries && entry!=(TTree::kMaxEntries-1) ))) {
1360 // -- Invalid entry number.
1361 if (fTree) fTree->LoadTree(-1);
1362 fReadEntry = -1;
1363 return -2;
1364 }
1365
1366 // Find out which tree in the chain contains the passed entry.
1367 Int_t treenum = fTreeNumber;
1368 if ((fTreeNumber == -1) || (entry < fTreeOffset[fTreeNumber]) || (entry >= fTreeOffset[fTreeNumber+1]) || (entry==TTree::kMaxEntries-1)) {
1369 // -- Entry is *not* in the chain's current tree.
1370 // Do a linear search of the tree offset array.
1371 // FIXME: We could be smarter by starting at the
1372 // current tree number and going forwards,
1373 // then wrapping around at the end.
1374 for (treenum = 0; treenum < fNtrees; treenum++) {
1375 if (entry < fTreeOffset[treenum+1]) {
1376 break;
1377 }
1378 }
1379 }
1380
1381 // Calculate the entry number relative to the found tree.
1382 Long64_t treeReadEntry = entry - fTreeOffset[treenum];
1383 fReadEntry = entry;
1384
1385 // If entry belongs to the current tree return entry.
1386 if (fTree && treenum == fTreeNumber) {
1387 // First load entry on the current tree, this will set the cursor also
1388 // on its friend trees. Their branch addresses cannot be updated yet,
1389 // as the required branch names are only available via `fStatus`, i.e.
1390 // only the chain knows about them. This is taken care of in the following
1391 // RefreshFriendAddresses call
1392 fTree->LoadTree(treeReadEntry);
1393
1394 if (fFriends || fTree->GetListOfFriends()) {
1395 TFriendLock lock(this, kLoadTree);
1396 if (fFriends) {
1397 // Make sure we load friends of the chain aligned to the current global entry number
1399 auto *frTree = frEl->GetTree();
1400 frTree->LoadTreeFriend(entry, this);
1401 }
1402 }
1403
1404 // Now refresh branch addresses of friend trees. This acts on the current tree of the chain, whether the
1405 // friends are friends of the chain or friends of the tree itself.
1406 if (auto refreshFriendAddressesRet = RefreshFriendAddresses(); refreshFriendAddressesRet == -6)
1407 return refreshFriendAddressesRet;
1408 }
1409
1410 return treeReadEntry;
1411 }
1412
1413 if (fExternalFriends) {
1415 external_fe->MarkUpdated();
1416 }
1417 }
1418
1419 // Delete the current tree and open the new tree.
1420 TTreeCache* tpf = nullptr;
1421 // Delete file unless the file owns this chain!
1422 // FIXME: The "unless" case here causes us to leak memory.
1423 if (fFile) {
1424 if (!fDirectory->GetList()->FindObject(this)) {
1425 if (fTree) {
1426 // (fFile != 0 && fTree == 0) can happen when
1427 // InvalidateCurrentTree is called (for example from
1428 // AddFriend). Having fTree === 0 is necessary in that
1429 // case because in some cases GetTree is used as a check
1430 // to see if a TTree is already loaded.
1431 // However, this prevent using the following to reuse
1432 // the TTreeCache object.
1433 tpf = fTree->GetReadCache(fFile);
1434 if (tpf) {
1435 tpf->ResetCache();
1436 }
1437
1438 fFile->SetCacheRead(nullptr, fTree);
1439 // If the tree has clones, copy them into the chain
1440 // clone list so we can change their branch addresses
1441 // when necessary.
1442 //
1443 // This is to support the syntax:
1444 //
1445 // TTree* clone = chain->GetTree()->CloneTree(0);
1446 //
1447 // We need to call the invalidate exactly here, since
1448 // we no longer need the value of fTree and it is
1449 // about to be deleted.
1451 }
1452
1453 if (fCanDeleteRefs) {
1454 fFile->Close("R");
1455 }
1456 delete fFile;
1457 fFile = nullptr;
1458 } else {
1459 // If the tree has clones, copy them into the chain
1460 // clone list so we can change their branch addresses
1461 // when necessary.
1462 //
1463 // This is to support the syntax:
1464 //
1465 // TTree* clone = chain->GetTree()->CloneTree(0);
1466 //
1468 }
1469 }
1470
1471 TChainElement* element = (TChainElement*) fFiles->At(treenum);
1472 if (!element) {
1473 if (treeReadEntry) {
1474 return -4;
1475 }
1476 // Last attempt, just in case all trees in the chain have 0 entries.
1477 element = (TChainElement*) fFiles->At(0);
1478 if (!element) {
1479 return -4;
1480 }
1481 }
1482
1483 // FIXME: We leak memory here, we've just lost the open file
1484 // if we did not delete it above.
1485 {
1487 const char *option = fGlobalRegistration ? "READ" : "READ_WITHOUT_GLOBALREGISTRATION";
1488 fFile = TFile::Open(element->GetTitle(), option);
1491 }
1492
1493 // ----- Begin of modifications by MvL
1494 Int_t returnCode = 0;
1495 if (!fFile || fFile->IsZombie()) {
1496 if (fFile) {
1497 delete fFile;
1498 fFile = nullptr;
1499 }
1500 // Note: We do *not* own fTree.
1501 fTree = nullptr;
1502 returnCode = -3;
1503 } else {
1504 if (fPerfStats)
1506
1507 // Note: We do *not* own fTree after this, the file does!
1508 fTree = dynamic_cast<TTree*>(fFile->Get(element->GetName()));
1509 if (!fTree) {
1510 // Now that we do not check during the addition, we need to check here!
1511 Error("LoadTree", "Cannot find tree with name %s in file %s", element->GetName(), element->GetTitle());
1512 delete fFile;
1513 fFile = nullptr;
1514 // We do not return yet so that 'fEntries' can be updated with the
1515 // sum of the entries of all the other trees.
1516 returnCode = -4;
1517 } else if (!fGlobalRegistration) {
1519 }
1520 // Propagate the IMT settings
1521 if (fTree) {
1523 }
1524 }
1525
1526 fTreeNumber = treenum;
1527 // FIXME: We own fFile, we must be careful giving away a pointer to it!
1528 // FIXME: We may set fDirectory to zero here!
1529 fDirectory = fFile;
1530
1531 // Reuse cache from previous file (if any).
1532 if (tpf) {
1533 if (fFile) {
1534 // FIXME: fTree may be zero here.
1535 tpf->UpdateBranches(fTree);
1536 tpf->ResetCache();
1537 fFile->SetCacheRead(tpf, fTree);
1538 } else {
1539 // FIXME: One of the file in the chain is missing
1540 // we have no place to hold the pointer to the
1541 // TTreeCache.
1542 delete tpf;
1543 tpf = nullptr;
1544 }
1545 } else {
1546 if (fCacheUserSet) {
1547 this->SetCacheSize(fCacheSize);
1548 }
1549 }
1550
1551 // Check if fTreeOffset has really been set.
1552 Long64_t nentries = 0;
1553 if (fTree) {
1555 }
1556
1560 element->SetNumberEntries(nentries);
1561 // Below we must test >= in case the tree has no entries.
1562 if (entry >= fTreeOffset[fTreeNumber+1]) {
1563 if ((fTreeNumber < (fNtrees - 1)) && (entry < fTreeOffset[fTreeNumber+2])) {
1564 // The request entry is not in the tree 'fTreeNumber' we will need
1565 // to look further.
1566
1567 // Before moving on, let's record the result.
1568 element->SetLoadResult(returnCode);
1569
1570 // Before trying to read the file file/tree, notify the user
1571 // that we have switched trees if requested; the user might need
1572 // to properly account for the number of files/trees even if they
1573 // have no entries.
1574 if (fNotify) {
1575 if(!fNotify->Notify()) return -6;
1576 }
1577
1578 // Load the next TTree.
1579 return LoadTree(entry);
1580 } else {
1581 treeReadEntry = fReadEntry = -2;
1582 }
1583 }
1584 }
1585
1586
1587 if (!fTree) {
1588 // The Error message already issued. However if we reach here
1589 // we need to make sure that we do not use fTree.
1590 //
1591 // Force a reload of the tree next time.
1592 fTreeNumber = -1;
1593
1594 element->SetLoadResult(returnCode);
1595 return returnCode;
1596 }
1597 // ----- End of modifications by MvL
1598
1599 // Copy the chain's clone list into the new tree's
1600 // clone list so that branch addresses stay synchronized.
1601 if (fClones) {
1602 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
1603 TTree* clone = (TTree*) lnk->GetObject();
1604 ((TChain*) fTree)->TTree::AddClone(clone);
1605 }
1606 }
1607
1608 // Since some of the friends of this chain might simple trees
1609 // (i.e., not really chains at all), we need to execute this
1610 // before calling LoadTree(entry) on the friends (so that
1611 // they use the correct read entry number).
1612
1613 // Change the new current tree to the new entry.
1614 Long64_t loadResult = fTree->LoadTree(treeReadEntry);
1615 if (loadResult == treeReadEntry) {
1616 element->SetLoadResult(0);
1617 } else {
1618 // This is likely to be an internal error, if treeReadEntry was not in range
1619 // (or intentionally -2 for TChain::GetEntries) then something happened
1620 // that is very odd/surprising.
1621 element->SetLoadResult(-5);
1622 }
1623
1624
1625 // Change the chain friends to the new entry.
1626 if (fFriends) {
1627 // An alternative would move this code to each of the function
1628 // calling LoadTree (and to overload a few more).
1629 TIter next(fFriends);
1630 TFriendLock lock(this, kLoadTree);
1631 TFriendElement* fe = nullptr;
1632 while ((fe = (TFriendElement*) next())) {
1633 TTree* t = fe->GetTree();
1634 if (!t) continue;
1635 if (t->GetTreeIndex()) {
1637 }
1638 if (t->GetTree() && t->GetTree()->GetTreeIndex()) {
1640 }
1641 if (treeReadEntry == -2) {
1642 // an entry after the end of the chain was requested (it usually happens when GetEntries is called)
1643 t->LoadTree(entry);
1644 } else {
1645 t->LoadTreeFriend(entry, this);
1646 }
1647 TTree* friend_t = t->GetTree();
1648 if (friend_t) {
1649 auto localfe = fTree->AddFriend(t, fe->GetName());
1651 }
1652 }
1653 }
1654
1657
1660
1661 // Set the branch statuses for the newly opened file.
1662 TIter next(fStatus);
1663 while ((element = (TChainElement*) next())) {
1664 Int_t status = element->GetStatus();
1665 if (element->IsDelayed()) {
1666 // In case we don't want spurious error message about missing branch in this tree
1667 UInt_t dummyFound = std::numeric_limits<UInt_t>::max();
1668 // Only set the branch status if it has a value provided
1669 // by the user
1670 if (status != -1)
1671 fTree->SetBranchStatus(element->GetName(), status, &dummyFound);
1672 } else {
1673 // Only set the branch status if it has a value provided
1674 // by the user
1675 if (status != -1)
1676 fTree->SetBranchStatus(element->GetName(), status);
1677 }
1678 }
1679
1680 // Set the branch addresses for the newly opened file.
1681 next.Reset();
1682 while ((element = (TChainElement*) next())) {
1683 void* addr = element->GetBaddress();
1684 if (addr) {
1685 TBranch* br = fTree->GetBranch(element->GetName());
1686 TBranch** pp = element->GetBranchPtr();
1687 if (pp) {
1688 // FIXME: What if br is zero here?
1689 *pp = br;
1690 }
1691 if (br) {
1692 if (!element->GetCheckedType()) {
1694 (EDataType) element->GetBaddressType(), element->GetBaddressIsPtr());
1695 if ((res & kNeedEnableDecomposedObj) && !br->GetMakeClass()) {
1696 br->SetMakeClass(true);
1697 }
1698 element->SetDecomposedObj(br->GetMakeClass());
1699 element->SetCheckedType(true);
1700 }
1701 // FIXME: We may have to tell the branch it should
1702 // not be an owner of the object pointed at.
1703 br->SetAddress(addr);
1704 if (TestBit(kAutoDelete)) {
1705 br->SetAutoDelete(true);
1706 }
1707 }
1708 }
1709 }
1710
1711 // Update the addresses of the chain's cloned trees, if any.
1712 if (fClones) {
1713 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
1714 TTree* clone = (TTree*) lnk->GetObject();
1715 CopyAddresses(clone);
1716 }
1717 }
1718
1719 // Update list of leaves in all TTreeFormula's of the TTreePlayer (if any).
1720 if (fPlayer) {
1722 }
1723
1724 // Notify user we have switched trees if requested.
1725 if (fNotify) {
1726 if(!fNotify->Notify()) return -6;
1727 }
1728
1729 // Return the new local entry number.
1730 return treeReadEntry;
1731}
1732
1733////////////////////////////////////////////////////////////////////////////////
1734/// Check / locate the files in the chain.
1735/// By default only the files not yet looked up are checked.
1736/// Use force = true to check / re-check every file.
1737
1738void TChain::Lookup(bool force)
1739{
1740 TIter next(fFiles);
1741 TChainElement* element = nullptr;
1742 Int_t nelements = fFiles->GetEntries();
1743 printf("\n");
1744 printf("TChain::Lookup - Looking up %d files .... \n", nelements);
1745 Int_t nlook = 0;
1746 TFileStager *stg = nullptr;
1747 while ((element = (TChainElement*) next())) {
1748 // Do not do it more than needed
1749 if (element->HasBeenLookedUp() && !force) continue;
1750 // Count
1751 nlook++;
1752 // Get the Url
1753 TUrl elemurl(element->GetTitle(), true);
1754 // Save current options and anchor
1755 TString anchor = elemurl.GetAnchor();
1756 TString options = elemurl.GetOptions();
1757 // Reset options and anchor
1758 elemurl.SetOptions("");
1759 elemurl.SetAnchor("");
1760 // Locate the file
1761 TString eurl(elemurl.GetUrl());
1762 if (!stg || !stg->Matches(eurl)) {
1763 SafeDelete(stg);
1764 {
1766 stg = TFileStager::Open(eurl);
1767 }
1768 if (!stg) {
1769 Error("Lookup", "TFileStager instance cannot be instantiated");
1770 break;
1771 }
1772 }
1773 Int_t n1 = (nelements > 100) ? (Int_t) nelements / 100 : 1;
1774 if (stg->Locate(eurl.Data(), eurl) == 0) {
1775 if (nlook > 0 && !(nlook % n1)) {
1776 printf("Lookup | %3d %% finished\r", 100 * nlook / nelements);
1777 fflush(stdout);
1778 }
1779 // Get the effective end-point Url
1780 elemurl.SetUrl(eurl);
1781 // Restore original options and anchor, if any
1782 elemurl.SetOptions(options);
1783 elemurl.SetAnchor(anchor);
1784 // Save it into the element
1785 element->SetTitle(elemurl.GetUrl());
1786 // Remember
1787 element->SetLookedUp();
1788 } else {
1789 // Failure: remove
1790 fFiles->Remove(element);
1791 if (gSystem->AccessPathName(eurl))
1792 Error("Lookup", "file %s does not exist\n", eurl.Data());
1793 else
1794 Error("Lookup", "file %s cannot be read\n", eurl.Data());
1795 }
1796 }
1797 if (nelements > 0)
1798 printf("Lookup | %3d %% finished\n", 100 * nlook / nelements);
1799 else
1800 printf("\n");
1801 fflush(stdout);
1802 SafeDelete(stg);
1803}
1804
1805////////////////////////////////////////////////////////////////////////////////
1806/// List the chain.
1807
1809{
1811 TIter next(fFiles);
1812 TChainElement* file = nullptr;
1814 while ((file = (TChainElement*)next())) {
1815 file->ls(option);
1816 }
1818}
1819
1820////////////////////////////////////////////////////////////////////////////////
1821/// Merge all the entries in the chain into a new tree in a new file.
1822///
1823/// See important note in the following function Merge().
1824///
1825/// If the chain is expecting the input tree inside a directory,
1826/// this directory is NOT created by this routine.
1827///
1828/// So in a case where we have:
1829/// ~~~ {.cpp}
1830/// TChain ch("mydir/mytree");
1831/// ch.Merge("newfile.root");
1832/// ~~~
1833/// The resulting file will have not subdirectory. To recreate
1834/// the directory structure do:
1835/// ~~~ {.cpp}
1836/// TFile* file = TFile::Open("newfile.root", "RECREATE");
1837/// file->mkdir("mydir")->cd();
1838/// ch.Merge(file, 0);
1839/// ~~~
1840
1842{
1843 TFile *file = TFile::Open(name, "recreate", "chain files");
1844 return Merge(file, 0, option);
1845}
1846
1847////////////////////////////////////////////////////////////////////////////////
1848/// Merge all chains in the collection. (NOT IMPLEMENTED)
1849
1850Long64_t TChain::Merge(TCollection* /* list */, Option_t* /* option */ )
1851{
1852 Error("Merge", "not implemented");
1853 return -1;
1854}
1855
1856////////////////////////////////////////////////////////////////////////////////
1857/// Merge all chains in the collection. (NOT IMPLEMENTED)
1858
1860{
1861 Error("Merge", "not implemented");
1862 return -1;
1863}
1864
1865////////////////////////////////////////////////////////////////////////////////
1866/// Merge all the entries in the chain into a new tree in the current file.
1867///
1868/// Note: The "file" parameter is *not* the file where the new
1869/// tree will be inserted. The new tree is inserted into
1870/// gDirectory, which is usually the most recently opened
1871/// file, or the directory most recently cd()'d to.
1872///
1873/// If option = "C" is given, the compression level for all branches
1874/// in the new Tree is set to the file compression level. By default,
1875/// the compression level of all branches is the original compression
1876/// level in the old trees.
1877///
1878/// If basketsize > 1000, the basket size for all branches of the
1879/// new tree will be set to basketsize.
1880///
1881/// Example using the file generated in $ROOTSYS/test/Event
1882/// merge two copies of Event.root
1883/// ~~~ {.cpp}
1884/// gSystem.Load("libEvent");
1885/// TChain ch("T");
1886/// ch.Add("Event1.root");
1887/// ch.Add("Event2.root");
1888/// ch.Merge("all.root");
1889/// ~~~
1890/// If the chain is expecting the input tree inside a directory,
1891/// this directory is NOT created by this routine.
1892///
1893/// So if you do:
1894/// ~~~ {.cpp}
1895/// TChain ch("mydir/mytree");
1896/// ch.Merge("newfile.root");
1897/// ~~~
1898/// The resulting file will not have subdirectories. In order to
1899/// preserve the directory structure do the following instead:
1900/// ~~~ {.cpp}
1901/// TFile* file = TFile::Open("newfile.root", "RECREATE");
1902/// file->mkdir("mydir")->cd();
1903/// ch.Merge(file, 0);
1904/// ~~~
1905/// If 'option' contains the word 'fast' the merge will be done without
1906/// unzipping or unstreaming the baskets (i.e., a direct copy of the raw
1907/// bytes on disk).
1908///
1909/// When 'fast' is specified, 'option' can also contains a
1910/// sorting order for the baskets in the output file.
1911///
1912/// There is currently 3 supported sorting order:
1913/// ~~~ {.cpp}
1914/// SortBasketsByOffset (the default)
1915/// SortBasketsByBranch
1916/// SortBasketsByEntry
1917/// ~~~
1918/// When using SortBasketsByOffset the baskets are written in
1919/// the output file in the same order as in the original file
1920/// (i.e. the basket are sorted on their offset in the original
1921/// file; Usually this also means that the baskets are sorted
1922/// on the index/number of the _last_ entry they contain)
1923///
1924/// When using SortBasketsByBranch all the baskets of each
1925/// individual branches are stored contiguously. This tends to
1926/// optimize reading speed when reading a small number (1->5) of
1927/// branches, since all their baskets will be clustered together
1928/// instead of being spread across the file. However it might
1929/// decrease the performance when reading more branches (or the full
1930/// entry).
1931///
1932/// When using SortBasketsByEntry the baskets with the lowest
1933/// starting entry are written first. (i.e. the baskets are
1934/// sorted on the index/number of the first entry they contain).
1935/// This means that on the file the baskets will be in the order
1936/// in which they will be needed when reading the whole tree
1937/// sequentially.
1938///
1939/// ## IMPORTANT Note 1: AUTOMATIC FILE OVERFLOW
1940///
1941/// When merging many files, it may happen that the resulting file
1942/// reaches a size > TTree::fgMaxTreeSize (default = 100 GBytes).
1943/// In this case the current file is automatically closed and a new
1944/// file started. If the name of the merged file was "merged.root",
1945/// the subsequent files will be named "merged_1.root", "merged_2.root",
1946/// etc. fgMaxTreeSize may be modified via the static function
1947/// TTree::SetMaxTreeSize.
1948/// When in fast mode, the check and switch is only done in between each
1949/// input file.
1950///
1951/// ## IMPORTANT Note 2: The output file is automatically closed and deleted.
1952///
1953/// This is required because in general the automatic file overflow described
1954/// above may happen during the merge.
1955/// If only the current file is produced (the file passed as first argument),
1956/// one can instruct Merge to not close and delete the file by specifying
1957/// the option "keep".
1958///
1959/// The function returns the total number of files produced.
1960/// To check that all files have been merged use something like:
1961/// ~~~ {.cpp}
1962/// if (newchain->GetEntries()!=oldchain->GetEntries()) {
1963/// ... not all the file have been copied ...
1964/// }
1965/// ~~~
1966
1968{
1969 // We must have been passed a file, we will use it
1970 // later to reset the compression level of the branches.
1971 if (!file) {
1972 // FIXME: We need an error message here.
1973 return 0;
1974 }
1975
1976 // Options
1977 bool fastClone = false;
1978 TString opt = option;
1979 opt.ToLower();
1980 if (opt.Contains("fast")) {
1981 fastClone = true;
1982 }
1983
1984 // The chain tree must have a list of branches
1985 // because we may try to change their basket
1986 // size later.
1987 TObjArray* lbranches = GetListOfBranches();
1988 if (!lbranches) {
1989 // FIXME: We need an error message here.
1990 return 0;
1991 }
1992
1993 // The chain must have a current tree because
1994 // that is the one we will clone.
1995 if (!fTree) {
1996 // -- LoadTree() has not yet been called, no current tree.
1997 // FIXME: We need an error message here.
1998 return 0;
1999 }
2000
2001 // Copy the chain's current tree without
2002 // copying any entries, we will do that later.
2003 TTree* newTree = CloneTree(0);
2004 if (!newTree) {
2005 // FIXME: We need an error message here.
2006 return 0;
2007 }
2008
2009 // Strip out the (potential) directory name.
2010 // FIXME: The merged chain may or may not have the
2011 // same name as the original chain. This is
2012 // bad because the chain name determines the
2013 // names of the trees in the chain by default.
2014 newTree->SetName(gSystem->BaseName(GetName()));
2015
2016 // FIXME: Why do we do this?
2017 newTree->SetAutoSave(2000000000);
2018
2019 // Circularity is incompatible with merging, it may
2020 // force us to throw away entries, which is not what
2021 // we are supposed to do.
2022 newTree->SetCircular(0);
2023
2024 // Reset the compression level of the branches.
2025 if (opt.Contains("c")) {
2026 TBranch* branch = nullptr;
2027 TIter nextb(newTree->GetListOfBranches());
2028 while ((branch = (TBranch*) nextb())) {
2030 }
2031 }
2032
2033 // Reset the basket size of the branches.
2034 if (basketsize > 1000) {
2035 TBranch* branch = nullptr;
2036 TIter nextb(newTree->GetListOfBranches());
2037 while ((branch = (TBranch*) nextb())) {
2038 branch->SetBasketSize(basketsize);
2039 }
2040 }
2041
2042 // Copy the entries.
2043 if (fastClone) {
2044 if ( newTree->CopyEntries( this, -1, option ) < 0 ) {
2045 // There was a problem!
2046 Error("Merge", "TTree has not been cloned\n");
2047 }
2048 } else {
2049 newTree->CopyEntries( this, -1, option );
2050 }
2051
2052 // Write the new tree header.
2053 newTree->Write();
2054
2055 // Get our return value.
2056 Int_t nfiles = newTree->GetFileNumber() + 1;
2057
2058 // Close and delete the current file of the new tree.
2059 if (!opt.Contains("keep")) {
2060 // Delete the currentFile and the TTree object.
2061 delete newTree->GetCurrentFile();
2062 }
2063 return nfiles;
2064}
2065
2066////////////////////////////////////////////////////////////////////////////////
2067/// Get the tree url or filename and other information from the name
2068///
2069/// A treename and a url's query section is split off from name. The
2070/// splitting depends on whether the resulting filename is to be
2071/// subsequently treated for wildcards or not, since the question mark is
2072/// both the url query identifier and a wildcard. Wildcard matching is not
2073/// done in this method itself.
2074/// ~~~ {.cpp}
2075/// [xxx://host]/a/path/file_name[?query[#treename]]
2076/// ~~~
2077///
2078/// The following way to specify the treename is still supported with the
2079/// constrain that the file name contains the sub-string '.root'.
2080/// This is now deprecated and will be removed in future versions.
2081/// ~~~ {.cpp}
2082/// [xxx://host]/a/path/file.root[.oext][/treename]
2083/// [xxx://host]/a/path/file.root[.oext][/treename][?query]
2084/// ~~~
2085///
2086/// Note that in a case like this
2087/// ~~~ {.cpp}
2088/// [xxx://host]/a/path/file#treename
2089/// ~~~
2090/// i.e. anchor but no options (query), the filename will be the full path, as
2091/// the anchor may be the internal file name of an archive. Use '?#%treename' to
2092/// pass the treename if the query field is empty.
2093///
2094/// \param[in] name is the original name
2095/// \param[out] filename the url or filename to be opened or matched
2096/// \param[out] treename the treename, which may be found in a url fragment section
2097/// as a trailing part of the name (deprecated).
2098/// If not found this will be empty.
2099/// Exception: a fragment containing the '=' character is _not_
2100/// interpreted as a treename
2101/// \param[out] query is the url query section, including the leading question
2102/// mark. If not found or the query section is only followed by
2103/// a fragment this will be empty.
2104/// \param[out] suffix the portion of name which was removed to from filename.
2105
2106void TChain::ParseTreeFilename(const char *name, TString &filename, TString &treename, TString &query,
2107 TString &suffix) const
2108{
2109 Ssiz_t pIdx = kNPOS;
2110 filename.Clear();
2111 treename.Clear();
2112 query.Clear();
2113 suffix.Clear();
2114
2115 // General case
2116 TUrl url(name, true);
2117 filename = (strcmp(url.GetProtocol(), "file")) ? url.GetUrl() : url.GetFileAndOptions();
2118
2119 TString fn = url.GetFile();
2120 // Extract query, if any
2121 if (url.GetOptions() && (strlen(url.GetOptions()) > 0))
2122 query.Form("?%s", url.GetOptions());
2123 // The treename can be passed as anchor
2124 const char *anchor = url.GetAnchor();
2125 if (anchor && anchor[0] != '\0') {
2126 // Support "?#tree_name" and "?query#tree_name"
2127 // "#tree_name" (no '?' is for tar archives)
2128 // If the treename would contain a '=', treat the anchor as part of the query instead. This makes sure
2129 // that Davix parameters are passed.
2130 if (!query.IsNull() || strstr(name, "?#")) {
2131 if (strstr(anchor, "=")) {
2132 query.Append("#");
2133 query.Append(anchor);
2134 } else {
2135 treename = anchor;
2136 }
2137 } else {
2138 // The anchor is part of the file name
2139 fn = url.GetFileAndOptions();
2140 }
2141 }
2142 // Suffix
2143 suffix = url.GetFileAndOptions();
2144 // Get options from suffix by removing the file name
2145 suffix.Replace(suffix.Index(fn), fn.Length(), "");
2146 // Remove the options suffix from the original file name
2147 filename.Replace(filename.Index(suffix), suffix.Length(), "");
2148
2149 // Special case: [...]file.root/treename
2150 static const char *dotr = ".root";
2151 static Ssiz_t dotrl = strlen(dotr);
2152 // Find the last one
2153 Ssiz_t js = filename.Index(dotr);
2154 while (js != kNPOS) {
2155 pIdx = js;
2156 js = filename.Index(dotr, js + 1);
2157 }
2158 if (pIdx != kNPOS) {
2159 static const char *slash = "/";
2160 static Ssiz_t slashl = strlen(slash);
2161 // Find the last one
2162 Ssiz_t ppIdx = filename.Index(slash, pIdx + dotrl);
2163 if (ppIdx != kNPOS) {
2164 // Good treename with the old recipe
2165 treename = filename(ppIdx + slashl, filename.Length());
2166 filename.Remove(ppIdx + slashl - 1);
2167 suffix.Insert(0, TString::Format("/%s", treename.Data()));
2168 }
2169 }
2170}
2171
2172////////////////////////////////////////////////////////////////////////////////
2173/// Print the header information of each tree in the chain.
2174/// See TTree::Print for a list of options.
2175
2177{
2178 TIter next(fFiles);
2179 TChainElement *element;
2180 while ((element = (TChainElement*)next())) {
2181 Printf("******************************************************************************");
2182 Printf("*Chain :%-10s: %-54s *", GetName(), element->GetTitle());
2183 Printf("******************************************************************************");
2184 TFile *file = TFile::Open(element->GetTitle());
2185 if (file && !file->IsZombie()) {
2186 TTree *tree = (TTree*)file->Get(element->GetName());
2187 if (tree) tree->Print(option);
2188 }
2189 delete file;
2190 }
2191}
2192
2193////////////////////////////////////////////////////////////////////////////////
2194/// Process all entries in this chain, calling functions in filename.
2195/// The return value is -1 in case of error and TSelector::GetStatus() in
2196/// in case of success.
2197/// See TTree::Process.
2198
2200{
2201 if (LoadTree(firstentry) < 0) {
2202 return 0;
2203 }
2204 return TTree::Process(filename, option, nentries, firstentry);
2205}
2206
2207////////////////////////////////////////////////////////////////////////////////
2208/// Process this chain executing the code in selector.
2209/// The return value is -1 in case of error and TSelector::GetStatus() in
2210/// in case of success.
2211
2213{
2214 return TTree::Process(selector, option, nentries, firstentry);
2215}
2216
2217////////////////////////////////////////////////////////////////////////////////
2218/// Make sure that obj (which is being deleted or will soon be) is no
2219/// longer referenced by this TTree.
2220
2222{
2223 if (fFile == obj) {
2224 fFile = nullptr;
2225 fDirectory = nullptr;
2226 fTree = nullptr;
2227 }
2228 if (fDirectory == obj) {
2229 fDirectory = nullptr;
2230 fTree = nullptr;
2231 }
2232 if (fTree == obj) {
2233 fTree = nullptr;
2234 }
2235}
2236
2237////////////////////////////////////////////////////////////////////////////////
2238/// Remove a friend from the list of friends.
2239
2241{
2242 // We already have been visited while recursively looking
2243 // through the friends tree, let return
2244
2245 if (!fFriends) {
2246 return;
2247 }
2248
2249 TTree::RemoveFriend(oldFriend);
2250
2251 // We need to invalidate the loading of the current tree because its list
2252 // of real friends is now obsolete. It is repairable only from LoadTree.
2254}
2255
2256////////////////////////////////////////////////////////////////////////////////
2257/// Resets the state of this chain.
2258
2260{
2261 delete fFile;
2262 fFile = nullptr;
2263 fNtrees = 0;
2264 fTreeNumber = -1;
2265 fTree = nullptr;
2266 fFile = nullptr;
2267 fFiles->Delete();
2268 fStatus->Delete();
2269 fTreeOffset[0] = 0;
2270 TChainElement* element = new TChainElement("*", "");
2271 fStatus->Add(element);
2272 fDirectory = nullptr;
2273
2274 TTree::Reset();
2275}
2276
2277////////////////////////////////////////////////////////////////////////////////
2278/// Resets the state of this chain after a merge (keep the customization but
2279/// forget the data).
2280
2282{
2283 fNtrees = 0;
2284 fTreeNumber = -1;
2285 fTree = nullptr;
2286 fFile = nullptr;
2287 fFiles->Delete();
2288 fTreeOffset[0] = 0;
2289
2291}
2292
2293////////////////////////////////////////////////////////////////////////////////
2294/// Save TChain as a C++ statements on output stream out.
2295/// With the option "friend" save the description of all the
2296/// TChain's friend trees or chains as well.
2297
2298void TChain::SavePrimitive(std::ostream &out, Option_t *option)
2299{
2300 static Int_t chCounter = 0;
2301
2302 TString chName = gInterpreter->MapCppName(GetName());
2303 if (chName.IsNull())
2304 chName = "_chain";
2305 ++chCounter;
2306 chName += chCounter;
2307
2308 TString opt = option;
2309 opt.ToLower();
2310
2311 out << " TChain *" << chName.Data() << " = new TChain(\"" << GetName() << "\");" << std::endl;
2312
2313 if (opt.Contains("friend")) {
2314 opt.ReplaceAll("friend", "");
2315 for (TObject *frel : *fFriends) {
2316 TTree *frtree = ((TFriendElement *)frel)->GetTree();
2317 if (dynamic_cast<TChain *>(frtree)) {
2318 if (strcmp(frtree->GetName(), GetName()) != 0)
2319 --chCounter; // make friends get the same chain counter
2320 frtree->SavePrimitive(out, opt.Data());
2321 out << " " << chName.Data() << "->AddFriend(\"" << frtree->GetName() << "\");" << std::endl;
2322 } else { // ordinary friend TTree
2323 TDirectory *file = frtree->GetDirectory();
2324 if (file && dynamic_cast<TFile *>(file))
2325 out << " " << chName.Data() << "->AddFriend(\"" << frtree->GetName() << "\", \"" << file->GetName()
2326 << "\");" << std::endl;
2327 }
2328 }
2329 }
2330 out << std::endl;
2331
2332 for (TObject *el : *fFiles) {
2333 TChainElement *chel = (TChainElement *)el;
2334 // Save tree file if it is really loaded to the chain
2335 if (chel->GetLoadResult() == 0 && chel->GetEntries() != 0) {
2336 if (chel->GetEntries() == TTree::kMaxEntries) // tree number of entries is not yet known
2337 out << " " << chName.Data() << "->AddFile(\"" << chel->GetTitle() << "\");" << std::endl;
2338 else
2339 out << " " << chName.Data() << "->AddFile(\"" << chel->GetTitle() << "\"," << chel->GetEntries() << ");"
2340 << std::endl;
2341 }
2342 }
2343 out << std::endl;
2344
2345 SaveMarkerAttributes(out, chName.Data(), 1, 1, 1);
2346}
2347
2348////////////////////////////////////////////////////////////////////////////////
2349/// Loop on tree and print entries passing selection.
2350/// - If varexp is 0 (or "") then print only first 8 columns.
2351/// - If varexp = "*" print all columns.
2352/// - Otherwise a columns selection can be made using "var1:var2:var3".
2353/// See TTreePlayer::Scan for more information.
2354
2355Long64_t TChain::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
2356{
2357 if (LoadTree(firstentry) < 0) {
2358 return 0;
2359 }
2360 return TTree::Scan(varexp, selection, option, nentries, firstentry);
2361}
2362
2363////////////////////////////////////////////////////////////////////////////////
2364/// Set the global branch kAutoDelete bit.
2365///
2366/// When LoadTree loads a new Tree, the branches for which
2367/// the address is set will have the option AutoDelete set
2368/// For more details on AutoDelete, see TBranch::SetAutoDelete.
2369
2370void TChain::SetAutoDelete(bool autodelete)
2371{
2372 if (autodelete) {
2373 SetBit(kAutoDelete, true);
2374 } else {
2375 SetBit(kAutoDelete, false);
2376 }
2377}
2378
2380{
2381 // Set the cache size of the underlying TTree,
2382 // See TTree::SetCacheSize.
2383 // Returns 0 cache state ok (exists or not, as appropriate)
2384 // -1 on error
2385
2386 Int_t res = 0;
2387
2388 // remember user has requested this cache setting
2389 fCacheUserSet = true;
2390
2391 if (fTree) {
2392 res = fTree->SetCacheSize(cacheSize);
2393 } else {
2394 // If we don't have a TTree yet only record the cache size wanted
2395 res = 0;
2396 }
2397 fCacheSize = cacheSize; // Record requested size.
2398 return res;
2399}
2400
2401////////////////////////////////////////////////////////////////////////////////
2402/// Reset the addresses of the branch.
2403
2405{
2406 TChainElement* element = (TChainElement*) fStatus->FindObject(branch->GetName());
2407 if (element) {
2408 element->SetBaddress(nullptr);
2409 }
2410 if (fTree) {
2411 fTree->ResetBranchAddress(branch);
2412 }
2413}
2414
2415////////////////////////////////////////////////////////////////////////////////
2416/// Reset the addresses of the branches.
2417
2419{
2420 // We already have been visited while recursively looking
2421 // through the friends tree, let return
2423 return;
2424 }
2425 TIter next(fStatus);
2426 TChainElement* element = nullptr;
2427 while ((element = (TChainElement*) next())) {
2428 element->SetBaddress(nullptr);
2429 }
2430 if (fTree) {
2432 }
2433 if (fFriends) {
2435 for (auto *frEl : TRangeDynCast<TFriendElement>(fFriends)) {
2436 auto *frTree = frEl->GetTree();
2437 if (frTree) {
2438 frTree->ResetBranchAddresses();
2439 }
2440 }
2441 }
2442}
2443
2444////////////////////////////////////////////////////////////////////////////////
2445/// Set branch address.
2446///
2447/// \param[in] bname is the name of a branch.
2448/// \param[in] add is the address of the branch.
2449/// \param[in] ptr
2450///
2451/// Note: See the comments in TBranchElement::SetAddress() for a more
2452/// detailed discussion of the meaning of the add parameter.
2453///
2454/// IMPORTANT REMARK:
2455///
2456/// In case TChain::SetBranchStatus is called, it must be called
2457/// BEFORE calling this function.
2458///
2459/// See TTree::CheckBranchAddressType for the semantic of the return value.
2460
2461Int_t TChain::SetBranchAddress(const char *bname, void* add, TBranch** ptr)
2462{
2463 Int_t res = kNoCheck;
2464
2465 // Check if bname is already in the status list.
2466 // If not, create a TChainElement object and set its address.
2467 TChainElement* element = (TChainElement*) fStatus->FindObject(bname);
2468 if (!element) {
2469 element = new TChainElement(bname, "");
2470 fStatus->Add(element);
2471 }
2472 element->SetBaddress(add);
2473 element->SetBranchPtr(ptr);
2474
2475 if (!fTree && fReadEntry == -1 && fTreeNumber == -1) {
2476 // Try to load the first tree to retrieve the dataset schema
2477 LoadTree(0);
2478 // Something went wrong when loading the first tree (possibly there are no
2479 // files connected to this chain), let the user know.
2480 if (!fTree && fReadEntry == -1 && fTreeNumber == -1)
2481 Warning("SetBranchAddress",
2482 "Could not load the first tree in chain \"%s\", no dataset schema available. Thus, it is not possible "
2483 "to know whether the branch name \"%s\" corresponds to an available branch or not. This could happen "
2484 "if the chain has no files connected yet, make sure to add files to the chain before calling "
2485 "'TChain::SetBranchAddress'.",
2486 GetName(), bname);
2487 }
2488
2489 // Also set address in current tree.
2490 // FIXME: What about the chain clones?
2491 if (fTreeNumber >= 0) {
2492 TBranch* branch = fTree->GetBranch(bname);
2493 if (ptr) {
2494 *ptr = branch;
2495 }
2496 if (branch) {
2498 if ((res & kNeedEnableDecomposedObj) && !branch->GetMakeClass()) {
2499 branch->SetMakeClass(true);
2500 }
2501 element->SetDecomposedObj(branch->GetMakeClass());
2502 element->SetCheckedType(true);
2503 if (fClones) {
2504 void* oldAdd = branch->GetAddress();
2505 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
2506 TTree* clone = (TTree*) lnk->GetObject();
2507 TBranch* cloneBr = clone->GetBranch(bname);
2508 if (cloneBr && (cloneBr->GetAddress() == oldAdd)) {
2509 // the clone's branch is still pointing to us
2510 cloneBr->SetAddress(add);
2511 if ((res & kNeedEnableDecomposedObj) && !cloneBr->GetMakeClass()) {
2512 cloneBr->SetMakeClass(true);
2513 }
2514 }
2515 }
2516 }
2517
2518 branch->SetAddress(add);
2519 } else {
2520 if (!element->IsDelayed())
2521 Error("SetBranchAddress", "unknown branch -> %s", bname);
2522 return kMissingBranch;
2523 }
2524 } else {
2525 if (ptr) {
2526 *ptr = nullptr;
2527 }
2528 }
2529 return res;
2530}
2531
2532////////////////////////////////////////////////////////////////////////////////
2533/// Check if bname is already in the status list, and if not, create a TChainElement object and set its address.
2534/// See TTree::CheckBranchAddressType for the semantic of the return value.
2535///
2536/// Note: See the comments in TBranchElement::SetAddress() for a more
2537/// detailed discussion of the meaning of the add parameter.
2538
2539Int_t TChain::SetBranchAddress(const char* bname, void* add, TClass* realClass, EDataType datatype, bool isptr)
2540{
2541 return SetBranchAddress(bname, add, nullptr, realClass, datatype, isptr);
2542}
2543
2544////////////////////////////////////////////////////////////////////////////////
2545/// Check if bname is already in the status list, and if not, create a TChainElement object and set its address.
2546/// See TTree::CheckBranchAddressType for the semantic of the return value.
2547///
2548/// Note: See the comments in TBranchElement::SetAddress() for a more
2549/// detailed discussion of the meaning of the add parameter.
2550
2551Int_t TChain::SetBranchAddress(const char* bname, void* add, TBranch** ptr, TClass* realClass, EDataType datatype, bool isptr)
2552{
2553 TChainElement* element = (TChainElement*) fStatus->FindObject(bname);
2554 if (!element) {
2555 element = new TChainElement(bname, "");
2556 fStatus->Add(element);
2557 }
2558 if (realClass) {
2559 element->SetBaddressClassName(realClass->GetName());
2560 }
2561 element->SetBaddressType((UInt_t) datatype);
2562 element->SetBaddressIsPtr(isptr);
2563 element->SetBranchPtr(ptr);
2564
2565 return SetBranchAddress(bname, add, ptr);
2566}
2567
2568////////////////////////////////////////////////////////////////////////////////
2569/// Set branch status to Process or DoNotProcess
2570///
2571/// \param[in] bname is the name of a branch. if bname="*", apply to all branches.
2572/// \param[in] status = 1 branch will be processed,
2573/// = 0 branch will not be processed
2574/// \param[out] found
2575///
2576/// See IMPORTANT REMARKS in TTree::SetBranchStatus and TChain::SetBranchAddress
2577///
2578/// If found is not 0, the number of branch(es) found matching the regular
2579/// expression is returned in *found AND the error message 'unknown branch'
2580/// is suppressed.
2581
2582void TChain::SetBranchStatus(const char* bname, bool status, UInt_t* found)
2583{
2584 // FIXME: We never explicitly set found to zero!
2585
2586 // Check if bname is already in the status list,
2587 // if not create a TChainElement object and set its status.
2588 TChainElement* element = (TChainElement*) fStatus->FindObject(bname);
2589 if (element) {
2590 fStatus->Remove(element);
2591 } else {
2592 element = new TChainElement(bname, "");
2593 }
2594 fStatus->Add(element);
2595 element->SetStatus(status);
2596 // Also set status in current tree.
2597 if (fTreeNumber >= 0) {
2598 fTree->SetBranchStatus(bname, status, found);
2599 } else if (found) {
2600 *found = 1;
2601 }
2602}
2603
2604////////////////////////////////////////////////////////////////////////////////
2605/// Remove reference to this chain from current directory and add
2606/// reference to new directory dir. dir can be 0 in which case the chain
2607/// does not belong to any directory.
2608
2610{
2611 if (fDirectory == dir) return;
2612 if (fDirectory) fDirectory->Remove(this);
2613 fDirectory = dir;
2614 if (fDirectory) {
2615 fDirectory->Append(this);
2617 } else {
2618 fFile = nullptr;
2619 }
2620}
2621
2622////////////////////////////////////////////////////////////////////////////////
2623/// \brief Set the input entry list (processing the entries of the chain will
2624/// then be limited to the entries in the list).
2625///
2626/// \param[in] elist The entry list to be assigned to this chain.
2627/// \param[in] opt An option string. Possible values are:
2628/// - "" (default): both the file names of the chain elements and the file
2629/// names of the TEntryList sublists are expanded to full path name.
2630/// - "ne": the file names are taken as they are and not expanded
2631/// - "sync": the TChain will go through the TEntryList in lockstep with the
2632/// trees in the chain rather than performing a lookup based on
2633/// treename and filename. This is mostly useful when the TEntryList
2634/// has multiple sublists for the same tree and filename.
2635/// \throws std::runtime_error If option "sync" was chosen and either:
2636/// - \p elist doesn't have sub entry lists.
2637/// - the number of sub entry lists in \p elist is different than the
2638/// number of trees in the chain.
2639/// - any of the sub entry lists in \p elist doesn't correspond to the
2640/// tree of the chain with the same index (i.e. it doesn't share the
2641/// same tree name and file name).
2642///
2643/// This function finds correspondence between the sub-lists of the TEntryList
2644/// and the trees of the TChain.
2645
2647{
2648 if (fEntryList){
2649 //check, if the chain is the owner of the previous entry list
2650 //(it happens, if the previous entry list was created from a user-defined
2651 //TEventList in SetEventList() function)
2653 TEntryList *tmp = fEntryList;
2654 fEntryList = nullptr; // Avoid problem with RecursiveRemove.
2655 delete tmp;
2656 } else {
2657 fEntryList = nullptr;
2658 }
2659 }
2660 if (!elist){
2661 fEntryList = nullptr;
2662 fEventList = nullptr;
2663 return;
2664 }
2665 if (!elist->TestBit(kCanDelete)){
2666 //this is a direct call to SetEntryList, not via SetEventList
2667 fEventList = nullptr;
2668 }
2669 if (elist->GetN() == 0){
2670 fEntryList = elist;
2671 return;
2672 }
2673
2674 Int_t ne = fFiles->GetEntries();
2675 Int_t listfound=0;
2676 TString treename, filename;
2677
2678 TEntryList *templist = nullptr;
2679
2680 const auto *subentrylists = elist->GetLists();
2681 if(strcmp(opt, "sync") == 0){
2682 if(!subentrylists){
2683 std::string msg{"In 'TChain::SetEntryList': "};
2684 msg += "the input TEntryList doesn't have sub entry lists. Please make sure too add them through ";
2685 msg += "TEntryList::AddSubList";
2686 throw std::runtime_error(msg);
2687 }
2688 const auto nsubelists = subentrylists->GetEntries();
2689 if(nsubelists != ne){
2690 std::string msg{"In 'TChain::SetEntryList': "};
2691 msg += "the number of sub entry lists in the input TEntryList (";
2692 msg += std::to_string(nsubelists);
2693 msg += ") is not equal to the number of files in the chain (";
2694 msg += std::to_string(ne);
2695 msg += ")";
2696 throw std::runtime_error(msg);
2697 }
2698 }
2699
2700 for (Int_t ie = 0; ie<ne; ie++){
2701 auto chainElement = (TChainElement*)fFiles->UncheckedAt(ie);
2702 treename = chainElement->GetName();
2703 filename = chainElement->GetTitle();
2704
2705 if(strcmp(opt, "sync") == 0){
2706 // If the user asked for "sync" option, there should be a 1:1 mapping
2707 // between trees in the chain and sub entry lists in the argument elist
2708 // We have already checked that the input TEntryList has a number of
2709 // sub entry lists equal to the number of files in the chain.
2710 templist = static_cast<TEntryList*>(subentrylists->At(ie));
2711 auto elisttreename = templist->GetTreeName();
2712 auto elistfilename = templist->GetFileName();
2713
2714 if (strcmp(treename, elisttreename) != 0 || strcmp(filename, elistfilename) != 0){
2715 std::string msg{"In 'TChain::SetEntryList': "};
2716 msg += "the sub entry list at index ";
2717 msg += std::to_string(ie);
2718 msg += " doesn't correspond to treename '";
2719 msg += treename;
2720 msg += "' and filename '";
2721 msg += filename;
2722 msg += "': it has treename '";
2723 msg += elisttreename;
2724 msg += "' and filename '";
2725 msg += elistfilename;
2726 msg += "'";
2727 throw std::runtime_error(msg);
2728 }
2729
2730 }else{
2731 templist = elist->GetEntryList(treename, filename, opt);
2732 }
2733
2734 if (templist) {
2735 listfound++;
2736 templist->SetTreeNumber(ie);
2737 }
2738 }
2739
2740 if (listfound == 0){
2741 Error("SetEntryList", "No list found for the trees in this chain");
2742 fEntryList = nullptr;
2743 return;
2744 }
2745 fEntryList = elist;
2746 TList *elists = elist->GetLists();
2747 bool shift = false;
2748 TIter next(elists);
2749
2750 //check, if there are sub-lists in the entry list, that don't
2751 //correspond to any trees in the chain
2752 while((templist = (TEntryList*)next())){
2753 if (templist->GetTreeNumber() < 0){
2754 shift = true;
2755 break;
2756 }
2757 }
2758 fEntryList->SetShift(shift);
2759
2760}
2761
2762////////////////////////////////////////////////////////////////////////////////
2763/// Set the input entry list (processing the entries of the chain will then be
2764/// limited to the entries in the list). This function creates a special kind
2765/// of entry list (TEntryListFromFile object) that loads lists, corresponding
2766/// to the chain elements, one by one, so that only one list is in memory at a time.
2767///
2768/// If there is an error opening one of the files, this file is skipped and the
2769/// next file is loaded
2770///
2771/// File naming convention:
2772///
2773/// - by default, filename_elist.root is used, where filename is the
2774/// name of the chain element
2775/// - xxx$xxx.root - $ sign is replaced by the name of the chain element
2776///
2777/// If the list name is not specified (by passing filename_elist.root/listname to
2778/// the TChain::SetEntryList() function, the first object of class TEntryList
2779/// in the file is taken.
2780///
2781/// It is assumed, that there are as many list files, as there are elements in
2782/// the chain and they are in the same order
2783
2784void TChain::SetEntryListFile(const char *filename, Option_t * /*opt*/)
2785{
2786
2787 if (fEntryList){
2788 //check, if the chain is the owner of the previous entry list
2789 //(it happens, if the previous entry list was created from a user-defined
2790 //TEventList in SetEventList() function)
2792 TEntryList *tmp = fEntryList;
2793 fEntryList = nullptr; // Avoid problem with RecursiveRemove.
2794 delete tmp;
2795 } else {
2796 fEntryList = nullptr;
2797 }
2798 }
2799
2800 fEventList = nullptr;
2801
2802 TString basename(filename);
2803
2804 Int_t dotslashpos = basename.Index(".root/");
2805 TString behind_dot_root = "";
2806 if (dotslashpos>=0) {
2807 // Copy the list name specification
2808 behind_dot_root = basename(dotslashpos+6,basename.Length()-dotslashpos+6);
2809 // and remove it from basename
2810 basename.Remove(dotslashpos+5);
2811 }
2812 fEntryList = new TEntryListFromFile(basename.Data(), behind_dot_root.Data(), fNtrees);
2814 fEntryList->SetDirectory(nullptr);
2815 ((TEntryListFromFile*)fEntryList)->SetFileNames(fFiles);
2816}
2817
2818////////////////////////////////////////////////////////////////////////////////
2819/// This function transfroms the given TEventList into a TEntryList
2820///
2821/// NOTE, that this function loads all tree headers, because the entry numbers
2822/// in the TEventList are global and have to be recomputed, taking into account
2823/// the number of entries in each tree.
2824///
2825/// The new TEntryList is owned by the TChain and gets deleted when the chain
2826/// is deleted. This TEntryList is returned by GetEntryList() function, and after
2827/// GetEntryList() function is called, the TEntryList is not owned by the chain
2828/// any more and will not be deleted with it.
2829
2831{
2832 fEventList = evlist;
2833 if (fEntryList) {
2835 TEntryList *tmp = fEntryList;
2836 fEntryList = nullptr; // Avoid problem with RecursiveRemove.
2837 delete tmp;
2838 } else {
2839 fEntryList = nullptr;
2840 }
2841 }
2842
2843 if (!evlist) {
2844 fEntryList = nullptr;
2845 fEventList = nullptr;
2846 return;
2847 }
2848
2849 char enlistname[100];
2850 snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
2851 TEntryList *enlist = new TEntryList(enlistname, evlist->GetTitle());
2852 enlist->SetDirectory(nullptr);
2853
2854 Int_t nsel = evlist->GetN();
2855 Long64_t globalentry, localentry;
2856 const char *treename;
2857 const char *filename;
2859 //Load all the tree headers if the tree offsets are not known
2860 //It is assumed here, that loading the last tree will load all
2861 //previous ones
2862 printf("loading trees\n");
2863 (const_cast<TChain*>(this))->LoadTree(evlist->GetEntry(evlist->GetN()-1));
2864 }
2865 for (Int_t i=0; i<nsel; i++){
2866 globalentry = evlist->GetEntry(i);
2867 //add some protection from globalentry<0 here
2868 Int_t treenum = 0;
2869 while (globalentry>=fTreeOffset[treenum])
2870 treenum++;
2871 treenum--;
2872 localentry = globalentry - fTreeOffset[treenum];
2873 // printf("globalentry=%lld, treeoffset=%lld, localentry=%lld\n", globalentry, fTreeOffset[treenum], localentry);
2874 treename = ((TNamed*)fFiles->At(treenum))->GetName();
2875 filename = ((TNamed*)fFiles->At(treenum))->GetTitle();
2876 //printf("entering for tree %s %s\n", treename, filename);
2877 enlist->SetTree(treename, filename);
2878 enlist->Enter(localentry);
2879 }
2880 enlist->SetBit(kCanDelete, true);
2881 enlist->SetReapplyCut(evlist->GetReapplyCut());
2882 SetEntryList(enlist);
2883}
2884
2885////////////////////////////////////////////////////////////////////////////////
2886/// Change the name of this TChain.
2887
2888void TChain::SetName(const char* name)
2889{
2890 if (fGlobalRegistration) {
2891 // Should this be extended to include the call to TTree::SetName?
2892 R__WRITE_LOCKGUARD(ROOT::gCoreMutex); // Take the lock once rather than 3 times.
2893 gROOT->GetListOfCleanups()->Remove(this);
2894 gROOT->GetListOfSpecials()->Remove(this);
2895 gROOT->GetListOfDataSets()->Remove(this);
2896 }
2898 if (fGlobalRegistration) {
2899 // Should this be extended to include the call to TTree::SetName?
2900 R__WRITE_LOCKGUARD(ROOT::gCoreMutex); // Take the lock once rather than 3 times.
2901 gROOT->GetListOfCleanups()->Add(this);
2902 gROOT->GetListOfSpecials()->Add(this);
2903 gROOT->GetListOfDataSets()->Add(this);
2904 }
2905}
2906
2907////////////////////////////////////////////////////////////////////////////////
2908/// Set number of entries per packet for parallel root.
2909
2911{
2912 fPacketSize = size;
2913 TIter next(fFiles);
2914 TChainElement *element;
2915 while ((element = (TChainElement*)next())) {
2916 element->SetPacketSize(size);
2917 }
2918}
2919
2920////////////////////////////////////////////////////////////////////////////////
2921/// Set chain weight.
2922///
2923/// The weight is used by TTree::Draw to automatically weight each
2924/// selected entry in the resulting histogram.
2925/// For example the equivalent of
2926/// ~~~ {.cpp}
2927/// chain.Draw("x","w")
2928/// ~~~
2929/// is
2930/// ~~~ {.cpp}
2931/// chain.SetWeight(w,"global");
2932/// chain.Draw("x");
2933/// ~~~
2934/// By default the weight used will be the weight
2935/// of each Tree in the TChain. However, one can force the individual
2936/// weights to be ignored by specifying the option "global".
2937/// In this case, the TChain global weight will be used for all Trees.
2938
2940{
2941 fWeight = w;
2942 TString opt = option;
2943 opt.ToLower();
2945 if (opt.Contains("global")) {
2947 }
2948}
2949
2950////////////////////////////////////////////////////////////////////////////////
2951/// Stream a class object.
2952
2954{
2955 if (b.IsReading()) {
2956 // Remove using the 'old' name.
2957 {
2959 gROOT->GetListOfCleanups()->Remove(this);
2960 }
2961
2962 UInt_t R__s, R__c;
2963 Version_t R__v = b.ReadVersion(&R__s, &R__c);
2964 if (R__v > 2) {
2965 b.ReadClassBuffer(TChain::Class(), this, R__v, R__s, R__c);
2966 } else {
2967 //====process old versions before automatic schema evolution
2969 b >> fTreeOffsetLen;
2970 b >> fNtrees;
2971 fFiles->Streamer(b);
2972 if (R__v > 1) {
2973 fStatus->Streamer(b);
2975 b.ReadFastArray(fTreeOffset,fTreeOffsetLen);
2976 }
2977 b.CheckByteCount(R__s, R__c, TChain::IsA());
2978 //====end of old versions
2979 }
2980 // Re-add using the new name.
2981 {
2983 gROOT->GetListOfCleanups()->Add(this);
2984 }
2985
2986 } else {
2987 b.WriteClassBuffer(TChain::Class(),this);
2988 }
2989}
2990
2991////////////////////////////////////////////////////////////////////////////////
2992/// Dummy function kept for back compatibility.
2993/// The cache is now activated automatically when processing TTrees/TChain.
2994
2995void TChain::UseCache(Int_t /* maxCacheSize */, Int_t /* pageSize */)
2996{
2997}
2998
2999Int_t TChain::SetBranchAddress(const char *bname, void *addr, TBranch **ptr, TClass *ptrClass, EDataType datatype,
3000 bool isptr, bool suppressMissingBranchError)
3001{
3002 if (!fStatus->FindObject(bname)) {
3003 auto *element = new TChainElement(bname, "");
3004 element->IsDelayed(suppressMissingBranchError);
3005 fStatus->Add(element);
3006 }
3007
3008 return SetBranchAddress(bname, addr, ptr, ptrClass, datatype, isptr);
3009}
#define SafeDelete(p)
Definition RConfig.hxx:507
#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:80
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:132
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:84
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
EDataType
Definition TDataType.h:28
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:139
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:142
int nentries
#define gInterpreter
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:417
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2585
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
#define R__LOCKGUARD(mutex)
#define R__WRITE_LOCKGUARD(mutex)
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
virtual bool GetMakeClass() const
Return whether this branch is in a mode where the object are decomposed or not (Also known as MakeCla...
Definition TBranch.cxx:2115
virtual char * GetAddress() const
Definition TBranch.h:221
void SetCompressionSettings(Int_t settings=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault)
Set compression settings.
Definition TBranch.cxx:2816
virtual void SetAddress(void *add)
Set address of this branch.
Definition TBranch.cxx:2693
virtual void SetAutoDelete(bool autodel=true)
Set the automatic delete bit.
Definition TBranch.cxx:2727
virtual bool SetMakeClass(bool decomposeObj=true)
Set the branch in a mode where the object are decomposed (Also known as MakeClass mode).
Definition TBranch.cxx:2938
virtual void SetBasketSize(Int_t bufsize)
Set the basket size The function makes sure that the basket size is greater than fEntryOffsetlen.
Definition TBranch.cxx:2740
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 SetLoadResult(Int_t result)
virtual void SetBaddressClassName(const char *clname)
virtual Long64_t GetEntries() const
void SetCheckedType(bool m)
virtual void SetPacketSize(Int_t size=100)
Set number of entries per packet for parallel root.
void SetDecomposedObj(bool m)
virtual bool HasBeenLookedUp()
virtual void SetStatus(Int_t status)
virtual void SetLookedUp(bool y=true)
Set/Reset the looked-up bit.
virtual UInt_t GetBaddressType() const
virtual bool GetBaddressIsPtr() const
virtual void SetNumberEntries(Long64_t n)
virtual TBranch ** GetBranchPtr() const
virtual Int_t GetPacketSize() const
virtual void SetBaddress(void *add)
virtual void CreatePackets()
Initialize the packet descriptor string.
virtual void SetBranchPtr(TBranch **ptr)
Int_t GetLoadResult() const
void ls(Option_t *option="") const override
List files in the chain.
virtual Int_t GetStatus() const
void IsDelayed(bool isDelayed)
virtual void * GetBaddress() const
virtual void SetBaddressType(UInt_t type)
bool GetCheckedType() const
virtual const char * GetBaddressClassName() const
virtual void SetBaddressIsPtr(bool isptr)
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:2379
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:2953
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:1171
virtual void SetAutoDelete(bool autodel=true)
Set the global branch kAutoDelete bit.
Definition TChain.cxx:2370
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:2999
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:2646
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:1226
TTree * GetTree() const override
Definition TChain.h:121
void Print(Option_t *option="") const override
Print the header information of each tree in the chain.
Definition TChain.cxx:2176
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:2221
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:173
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:2259
void ResetAfterMerge(TFileMergeInfo *) override
Resets the state of this chain after a merge (keep the customization but forget the data).
Definition TChain.cxx:2281
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:2418
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save TChain as a C++ statements on output stream out.
Definition TChain.cxx:2298
void SetEventList(TEventList *evlist) override
This function transfroms the given TEventList into a TEntryList.
Definition TChain.cxx:2830
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:2355
void SetWeight(Double_t w=1, Option_t *option="") override
Set chain weight.
Definition TChain.cxx:2939
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:2199
void RemoveFriend(TTree *) override
Remove a friend from the list of friends.
Definition TChain.cxx:2240
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:2404
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:2609
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:1841
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:2106
bool InPlaceClone(TDirectory *newdirectory, const char *options="") override
Move content to a new file. (NOT IMPLEMENTED for TChain)
Definition TChain.cxx:1189
Int_t GetNbranches() override
Return the number of branches of the current tree.
Definition TChain.cxx:1142
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:2784
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:2888
void ls(Option_t *option="") const override
List the chain.
Definition TChain.cxx:1808
void SetBranchStatus(const char *bname, bool status=true, UInt_t *found=nullptr) override
Set branch status to Process or DoNotProcess.
Definition TChain.cxx:2582
Long64_t LoadTree(Long64_t entry) override
Find the tree which contains entry, and set it as the current tree.
Definition TChain.cxx:1346
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:1157
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:2995
void InvalidateCurrentTree()
Set the TTree to be reloaded as soon as possible.
Definition TChain.cxx:1208
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:2910
Int_t fTreeNumber
! Current Tree number in fTreeOffset table
Definition TChain.h:38
void Lookup(bool force=false)
Check / locate the files in the chain.
Definition TChain.cxx:1738
Long64_t RefreshFriendAddresses()
Refresh branch/leaf addresses of friend trees.
Definition TChain.cxx:1238
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:2999
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 bool Enter(Long64_t entry, TTree *tree=nullptr)
Add entry #entry to the list.
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 Int_t GetTreeNumber() const
Definition TEntryList.h:81
virtual TList * GetLists() const
Definition TEntryList.h:76
virtual void SetTree(const TTree *tree)
If a list for a tree with such name and filename exists, sets it as the current sublist If not,...
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 SetReapplyCut(bool apply=false)
Definition TEntryList.h:108
virtual void SetTreeNumber(Int_t index)
Definition TEntryList.h:107
virtual void SetDirectory(TDirectory *dir)
Add reference to directory dir. dir can be 0.
virtual const char * GetTreeName() const
Definition TEntryList.h:79
void GetFileName(const char *filename, TString &fn, bool *=nullptr)
To be able to re-localize the entry-list we identify the file by just the name and the anchor,...
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
virtual Long64_t GetEntry(Int_t index) const
Return value of entry at index in the list.
virtual bool GetReapplyCut() const
Definition TEventList.h:57
virtual Int_t GetN() const
Definition TEventList.h:56
Class describing a generic file including meta information.
Definition TFileInfo.h:39
TUrl * GetCurrentUrl() const
Return the current url.
A class to pass information from the TFileMerger to the objects being merged.
virtual Bool_t Matches(const char *s)
Definition TFileStager.h:46
static TFileStager * Open(const char *stager)
Open a stager, after having loaded the relevant plug-in.
virtual Int_t Locate(const char *u, TString &f)
Just check if the file exists locally.
A file, usually with extension .root, that stores data and code in the form of serialized objects in ...
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:2432
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:3802
void Close(Option_t *option="") override
Close a file.
Definition TFile.cxx:992
A TFriendElement TF describes a TTree object TF in a file.
virtual TTree * GetTree()
Return pointer to friend TTree.
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
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:173
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:617
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:1082
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition TObject.cxx:857
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:886
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:548
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1096
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1124
virtual void ls(Option_t *option="") const
The ls function lists the contents of a class on stdout.
Definition TObject.cxx:597
void ResetBit(UInt_t f)
Definition TObject.h:203
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:71
@ kInvalidObject
if object ctor succeeded but object should not be used
Definition TObject.h:81
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:73
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition TROOT.cxx:3059
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition TROOT.cxx:2916
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:137
Ssiz_t Length() const
Definition TString.h:426
void ToLower()
Change string to lower-case.
Definition TString.cxx:1190
TString & Insert(Ssiz_t pos, const char *s)
Definition TString.h:671
void Clear()
Clear string without changing its capacity.
Definition TString.cxx:1242
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition TString.h:704
const char * Data() const
Definition TString.h:385
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:714
Bool_t IsNull() const
Definition TString.h:423
TString & Remove(Ssiz_t pos)
Definition TString.h:695
TString & Append(const char *cs)
Definition TString.h:582
Bool_t MaybeWildcard() const
Returns true if string contains one of the wildcard characters "[]*?".
Definition TString.cxx:972
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:2460
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2438
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:642
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:661
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:1318
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition TSystem.cxx:949
A cache to speed-up the reading of ROOT datasets.
Definition TTreeCache.h:32
virtual void UpdateBranches(TTree *tree)
Update pointer to current Tree and recompute pointers to the branches in the cache.
virtual void ResetCache()
This will simply clear the cache.
Helper class to iterate over cluster of baskets.
Definition TTree.h:328
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition TTree.h:235
A TTree represents a columnar dataset.
Definition TTree.h:95
virtual TFriendElement * AddFriend(const char *treename, const char *filename="")
Add a TFriendElement to the list of friends.
Definition TTree.cxx:1360
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:4971
virtual void SetBranchStatus(const char *bname, bool status=true, UInt_t *found=nullptr)
Set branch status to Process or DoNotProcess.
Definition TTree.cxx:8939
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5459
TList * fFriends
pointer to list of friend elements
Definition TTree.h:146
bool fIMTEnabled
! true if implicit multi-threading is enabled for this tree
Definition TTree.h:158
virtual bool GetBranchStatus(const char *branchname) const
Return status of branch with name branchname.
Definition TTree.cxx:5485
UInt_t fFriendLockStatus
! Record which method is locking the friend recursion
Definition TTree.h:153
TEventList * fEventList
! Pointer to event selection list (if one)
Definition TTree.h:141
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:5747
virtual void SetCircular(Long64_t maxEntries)
Enable/Disable circularity for this tree.
Definition TTree.cxx:9306
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition TTree.cxx:5572
virtual void ResetBranchAddress(TBranch *)
Tell a branch to set its address to zero.
Definition TTree.cxx:8403
bool fCacheUserSet
! true if the cache setting was explicitly given by user
Definition TTree.h:157
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition TTree.cxx:6019
virtual TObjArray * GetListOfLeaves()
Definition TTree.h:590
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition TTree.cxx:5584
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:3760
void Streamer(TBuffer &) override
Stream a class object.
Definition TTree.cxx:9972
TVirtualTreePlayer * GetPlayer()
Load the TTreePlayer (if not already done).
Definition TTree.cxx:6561
virtual Double_t GetWeight() const
Definition TTree.h:645
void Draw(Option_t *opt) override
Default Draw method for all objects.
Definition TTree.h:492
void Print(Option_t *option="") const override
Print a summary of the tree contents.
Definition TTree.cxx:7559
TVirtualTreePlayer * fPlayer
! Pointer to current Tree player
Definition TTree.h:150
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:9602
TDirectory * GetDirectory() const
Definition TTree.h:523
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition TTree.cxx:6574
Long64_t fEntries
Number of entries.
Definition TTree.h:100
TEntryList * fEntryList
! Pointer to event selection list (if one)
Definition TTree.h:142
virtual TVirtualIndex * GetTreeIndex() const
Definition TTree.h:619
TList * fExternalFriends
! List of TFriendsElement pointing to us and need to be notified of LoadTree. Content not owned.
Definition TTree.h:147
virtual void SetMaxVirtualSize(Long64_t size=0)
Definition TTree.h:731
virtual void SetAutoSave(Long64_t autos=-300000000)
In case of a program crash, it will be possible to recover the data in the tree up to the last AutoSa...
Definition TTree.cxx:8694
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:7789
virtual void ResetAfterMerge(TFileMergeInfo *)
Resets the state of this TTree after a merge (keep the customization but forget the data).
Definition TTree.cxx:8372
virtual Long64_t GetEntries() const
Definition TTree.h:524
virtual TTree * CloneTree(Long64_t nentries=-1, Option_t *option="")
Create a clone of this tree and copy nentries.
Definition TTree.cxx:3174
virtual TLeaf * GetLeaf(const char *branchname, const char *leafname)
Searches in this tree and any of its friends for a leaf named leafname in branch branchname ,...
Definition TTree.cxx:6327
virtual void Reset(Option_t *option="")
Reset baskets, buffers and entries count in all branches and leaves.
Definition TTree.cxx:8341
virtual void SetImplicitMT(bool enabled)
Definition TTree.h:727
Long64_t fMaxVirtualSize
Maximum total size of buffers kept in memory.
Definition TTree.h:115
TVirtualPerfStats * fPerfStats
! pointer to the current perf stats object
Definition TTree.h:148
Double_t fWeight
Tree weight (see TTree::SetWeight)
Definition TTree.h:106
virtual Long64_t GetReadEntry() const
Definition TTree.h:610
virtual TObjArray * GetListOfBranches()
Definition TTree.h:589
virtual TTree * GetTree() const
Definition TTree.h:618
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition TTree.cxx:6729
virtual const char * GetAlias(const char *aliasName) const
Returns the expanded value of the alias. Search in the friends if any.
Definition TTree.cxx:5304
virtual void RemoveFriend(TTree *)
Remove a friend from the list of friends.
Definition TTree.cxx:8315
void Browse(TBrowser *) override
Browse content of the TTree.
Definition TTree.cxx:2640
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:6821
Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0) override
Write this object to the current directory.
Definition TTree.cxx:10181
TObject * fNotify
Object to be notified when loading a Tree.
Definition TTree.h:136
virtual TList * GetListOfClones()
Definition TTree.h:588
Long64_t fCacheSize
! Maximum size of file buffers
Definition TTree.h:121
TList * fClones
! List of cloned trees which share our addresses
Definition TTree.h:151
static TClass * Class()
@ kResetBranchAddresses
Definition TTree.h:280
@ kLoadTree
Definition TTree.h:268
virtual void CopyAddresses(TTree *, bool undo=false)
Set branch addresses of passed tree equal to ours.
Definition TTree.cxx:3340
virtual TList * GetListOfFriends() const
Definition TTree.h:591
Long64_t fReadEntry
! Number of the entry being processed
Definition TTree.h:123
virtual Int_t GetNbranches()
Definition TTree.h:603
virtual TLeaf * FindLeaf(const char *name)
Find first leaf containing searchname.
Definition TTree.cxx:4994
TDirectory * fDirectory
! Pointer to directory holding this tree
Definition TTree.h:137
@ kNeedEnableDecomposedObj
Definition TTree.h:302
@ kNoCheck
Definition TTree.h:301
@ kMissingBranch
Definition TTree.h:291
virtual void ResetBranchAddresses()
Tell all of our branches to drop their current objects and allocate new ones.
Definition TTree.cxx:8413
void SetName(const char *name) override
Change the name of this tree.
Definition TTree.cxx:9630
virtual Int_t GetPacketSize() const
Definition TTree.h:606
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache (TTreeCache) in bytes.
Definition TTree.cxx:9092
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:1247
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:2902
virtual Int_t GetFileNumber() const
Definition TTree.h:577
virtual void SetChainOffset(Long64_t offset=0)
Definition TTree.h:710
Int_t fPacketSize
! Number of entries in one packet for parallel root
Definition TTree.h:125
virtual Long64_t GetChainOffset() const
Definition TTree.h:517
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:8451
virtual Long64_t CopyEntries(TTree *tree, Long64_t nentries=-1, Option_t *option="", bool needCopyAddresses=false)
Copy nentries from given tree to this tree.
Definition TTree.cxx:3575
Int_t fMakeClass
! not zero when processing code generated by MakeClass
Definition TTree.h:131
static constexpr Long64_t kMaxEntries
Used as the max value for any TTree range operation.
Definition TTree.h:287
This class represents a WWW compatible URL.
Definition TUrl.h:33
const char * GetAnchor() const
Definition TUrl.h:70
const char * GetUrl(Bool_t withDeflt=kFALSE) const
Return full URL.
Definition TUrl.cxx:395
void SetAnchor(const char *anchor)
Definition TUrl.h:86
const char * GetFileAndOptions() const
Return the file and its options (the string specified behind the ?).
Definition TUrl.cxx:508
const char * GetFile() const
Definition TUrl.h:69
void SetUrl(const char *url, Bool_t defaultIsFile=kFALSE)
Parse url character string and split in its different subcomponents.
Definition TUrl.cxx:107
void SetOptions(const char *opt)
Definition TUrl.h:87
const char * GetOptions() const
Definition TUrl.h:71
const char * GetProtocol() const
Definition TUrl.h:64
virtual void UpdateFormulaLeaves(const TTree *parent)=0
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