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