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/// This second mode is interesting in case the number of entries in
460/// the file is already stored in a run database for example.
461///
462/// C. If nentries == TTree::kMaxEntries (default), the file is not opened.
463/// The number of entries in each file will be read only when the file
464/// is opened to read an entry. This option is the default and very
465/// efficient if one processes the chain sequentially. Note that in
466/// case GetEntry(entry) is called and entry refers to an entry in the
467/// third file, for example, this forces the tree headers in the first
468/// and second file to be read to find the number of entries in those
469/// files. Note that if one calls GetEntriesFast() after having created
470/// a chain with this default, GetEntriesFast() will return TTree::kMaxEntries!
471/// Using the GetEntries() function instead will force all of the tree
472/// headers in the chain to be read to read the number of entries in
473/// each tree.
474///
475/// D. The TChain data structure
476/// Each TChainElement has a name equal to the tree name of this TChain
477/// and a title equal to the file name. So, to loop over the
478/// TFiles that have been added to this chain:
479/// ~~~ {.cpp}
480/// TObjArray *fileElements=chain->GetListOfFiles();
481/// TIter next(fileElements);
482/// TChainElement *chEl=0;
483/// while (( chEl=(TChainElement*)next() )) {
484/// TFile f(chEl->GetTitle());
485/// ... do something with f ...
486/// }
487/// ~~~
488/// The function returns 1 if the file is successfully connected, 0 otherwise.
489
490Int_t TChain::AddFile(const char* name, Long64_t nentries /* = TTree::kMaxEntries */, const char* tname /* = "" */)
491{
492 if(name==nullptr || name[0]=='\0') {
493 Error("AddFile", "No file name; no files connected");
494 return 0;
495 }
496
497 const char *treename = GetName();
498 if (tname && strlen(tname) > 0) treename = tname;
499
500 TString basename, tn, query, suffix;
501 ParseTreeFilename(name, basename, tn, query, suffix);
502
503 if (!tn.IsNull()) {
504 treename = tn.Data();
505 }
506
507 Int_t nch = basename.Length() + query.Length();
508 char *filename = new char[nch+1];
509 strlcpy(filename,basename.Data(),nch+1);
510 strlcat(filename,query.Data(),nch+1);
511
512 //Check enough space in fTreeOffset
513 if (fNtrees+1 >= fTreeOffsetLen) {
514 fTreeOffsetLen *= 2;
515 Long64_t *trees = new Long64_t[fTreeOffsetLen];
516 for (Int_t i=0;i<=fNtrees;i++) trees[i] = fTreeOffset[i];
517 delete [] fTreeOffset;
518 fTreeOffset = trees;
519 }
520
521 // Open the file to get the number of entries.
522 Int_t pksize = 0;
523 if (nentries <= 0) {
524 TFile* file;
525 {
527 const char *option = fGlobalRegistration ? "READ" : "READ_WITHOUT_GLOBALREGISTRATION";
528 file = TFile::Open(filename, option);
529 }
530 if (!file || file->IsZombie()) {
531 delete file;
532 file = nullptr;
533 delete[] filename;
534 filename = nullptr;
535 return 0;
536 }
537
538 // Check that tree with the right name exists in the file.
539 // Note: We are not the owner of obj, the file is!
540 TObject* obj = file->Get(treename);
541 if (!obj || !obj->InheritsFrom(TTree::Class())) {
542 Error("AddFile", "cannot find tree with name %s in file %s", treename, filename);
543 delete file;
544 file = nullptr;
545 delete[] filename;
546 filename = nullptr;
547 return 0;
548 }
549 TTree* tree = (TTree*) obj;
550 nentries = tree->GetEntries();
551 pksize = tree->GetPacketSize();
552 // Note: This deletes the tree we fetched.
553 delete file;
554 file = nullptr;
555 }
556
557 if (nentries > 0) {
561 } else {
564 }
565 fNtrees++;
566
567 TChainElement* element = new TChainElement(treename, filename);
568 element->SetPacketSize(pksize);
569 element->SetNumberEntries(nentries);
570 fFiles->Add(element);
571 } else {
572 Warning("AddFile", "Adding tree with no entries from file: %s", filename);
573 }
574
575 delete [] filename;
576 if (fProofChain)
577 // This updates the proxy chain when we will really use PROOF
579
580 return 1;
581}
582
583////////////////////////////////////////////////////////////////////////////////
584/// Add all files referenced in the list to the chain. The object type in the
585/// list must be either TFileInfo or TObjString or TUrl .
586/// The function return 1 if successful, 0 otherwise.
587
588Int_t TChain::AddFileInfoList(TCollection* filelist, Long64_t nfiles /* = TTree::kMaxEntries */)
589{
590 if (!filelist)
591 return 0;
592 TIter next(filelist);
593
594 TObject *o = nullptr;
595 Long64_t cnt=0;
596 while ((o = next())) {
597 // Get the url
598 TString cn = o->ClassName();
599 const char *url = nullptr;
600 if (cn == "TFileInfo") {
601 TFileInfo *fi = (TFileInfo *)o;
602 url = (fi->GetCurrentUrl()) ? fi->GetCurrentUrl()->GetUrl() : nullptr;
603 if (!url) {
604 Warning("AddFileInfoList", "found TFileInfo with empty Url - ignoring");
605 continue;
606 }
607 } else if (cn == "TUrl") {
608 url = ((TUrl*)o)->GetUrl();
609 } else if (cn == "TObjString") {
610 url = ((TObjString*)o)->GetName();
611 }
612 if (!url) {
613 Warning("AddFileInfoList", "object is of type %s : expecting TFileInfo, TUrl"
614 " or TObjString - ignoring", o->ClassName());
615 continue;
616 }
617 // Good entry
618 cnt++;
619 AddFile(url);
620 if (cnt >= nfiles)
621 break;
622 }
623 if (fProofChain) {
624 // This updates the proxy chain when we will really use PROOF
626 }
627
628 return 1;
629}
630
631////////////////////////////////////////////////////////////////////////////////
632/// Add a TFriendElement to the list of friends of this chain.
633///
634/// A TChain has a list of friends similar to a tree (see TTree::AddFriend).
635/// You can add a friend to a chain with the TChain::AddFriend method, and you
636/// can retrieve the list of friends with TChain::GetListOfFriends.
637/// This example has four chains each has 20 ROOT trees from 20 ROOT files.
638/// ~~~ {.cpp}
639/// TChain ch("t"); // a chain with 20 trees from 20 files
640/// TChain ch1("t1");
641/// TChain ch2("t2");
642/// TChain ch3("t3");
643/// ~~~
644/// Now we can add the friends to the first chain.
645/// ~~~ {.cpp}
646/// ch.AddFriend("t1")
647/// ch.AddFriend("t2")
648/// ch.AddFriend("t3")
649/// ~~~
650/// \image html tchain_friend.png
651///
652///
653/// The parameter is the name of friend chain (the name of a chain is always
654/// the name of the tree from which it was created).
655/// The original chain has access to all variable in its friends.
656/// We can use the TChain::Draw method as if the values in the friends were
657/// in the original chain.
658/// To specify the chain to use in the Draw method, use the syntax:
659/// ~~~ {.cpp}
660/// <chainname>.<branchname>.<varname>
661/// ~~~
662/// If the variable name is enough to uniquely identify the variable, you can
663/// leave out the chain and/or branch name.
664/// For example, this generates a 3-d scatter plot of variable "var" in the
665/// TChain ch versus variable v1 in TChain t1 versus variable v2 in TChain t2.
666/// ~~~ {.cpp}
667/// ch.Draw("var:t1.v1:t2.v2");
668/// ~~~
669/// When a TChain::Draw is executed, an automatic call to TTree::AddFriend
670/// connects the trees in the chain. When a chain is deleted, its friend
671/// elements are also deleted.
672///
673/// The number of entries in the friend must be equal or greater to the number
674/// of entries of the original chain. If the friend has fewer entries a warning
675/// is given and the resulting histogram will have missing entries.
676/// For additional information see TTree::AddFriend.
677
678TFriendElement* TChain::AddFriend(const char* chain, const char* dummy /* = "" */)
679{
680 if (!fFriends) {
681 fFriends = new TList();
682 }
683 TFriendElement* fe = new TFriendElement(this, chain, dummy);
684
685 R__ASSERT(fe); // There used to be a "if (fe)" test ... Keep this assert until we are sure that fe is never null
686
687 fFriends->Add(fe);
688
689 if (fProofChain)
690 // This updates the proxy chain when we will really use PROOF
692
693 // We need to invalidate the loading of the current tree because its list
694 // of real friends is now obsolete. It is repairable only from LoadTree.
696
697 TTree* tree = fe->GetTree();
698 if (!tree) {
699 Warning("AddFriend", "Unknown TChain %s", chain);
700 }
701 return fe;
702}
703
704////////////////////////////////////////////////////////////////////////////////
705/// Add the whole chain or tree as a friend of this chain.
706
707TFriendElement* TChain::AddFriend(const char* chain, TFile* dummy)
708{
709 if (!fFriends) fFriends = new TList();
710 TFriendElement *fe = new TFriendElement(this,chain,dummy);
711
712 R__ASSERT(fe); // There used to be a "if (fe)" test ... Keep this assert until we are sure that fe is never null
713
714 fFriends->Add(fe);
715
716 if (fProofChain)
717 // This updates the proxy chain when we will really use PROOF
719
720 // We need to invalidate the loading of the current tree because its list
721 // of real friend is now obsolete. It is repairable only from LoadTree
723
724 TTree *t = fe->GetTree();
725 if (!t) {
726 Warning("AddFriend","Unknown TChain %s",chain);
727 }
728 return fe;
729}
730
731////////////////////////////////////////////////////////////////////////////////
732/// Add the whole chain or tree as a friend of this chain.
733
734TFriendElement* TChain::AddFriend(TTree* chain, const char* alias, bool /* warn = false */)
735{
736 if (!chain) return nullptr;
737 if (!fFriends) fFriends = new TList();
738 TFriendElement *fe = new TFriendElement(this,chain,alias);
739 R__ASSERT(fe);
740
741 fFriends->Add(fe);
742
743 if (fProofChain)
744 // This updates the proxy chain when we will really use PROOF
746
747 // We need to invalidate the loading of the current tree because its list
748 // of real friend is now obsolete. It is repairable only from LoadTree
750
751 TTree *t = fe->GetTree();
752 if (!t) {
753 Warning("AddFriend","Unknown TChain %s",chain->GetName());
754 }
755 return fe;
756}
757
758////////////////////////////////////////////////////////////////////////////////
759/// Browse the contents of the chain.
760
762{
764}
765
766////////////////////////////////////////////////////////////////////////////////
767/// When closing a file during the chain processing, the file
768/// may be closed with option "R" if flag is set to true.
769/// by default flag is true.
770/// When closing a file with option "R", all TProcessIDs referenced by this
771/// file are deleted.
772/// Calling TFile::Close("R") might be necessary in case one reads a long list
773/// of files having TRef, writing some of the referenced objects or TRef
774/// to a new file. If the TRef or referenced objects of the file being closed
775/// will not be referenced again, it is possible to minimize the size
776/// of the TProcessID data structures in memory by forcing a delete of
777/// the unused TProcessID.
778
779void TChain::CanDeleteRefs(bool flag /* = true */)
780{
781 fCanDeleteRefs = flag;
782}
783
784////////////////////////////////////////////////////////////////////////////////
785/// Initialize the packet descriptor string.
786
788{
789 TIter next(fFiles);
790 TChainElement* element = nullptr;
791 while ((element = (TChainElement*) next())) {
792 element->CreatePackets();
793 }
794}
795
796////////////////////////////////////////////////////////////////////////////////
797/// Override the TTree::DirectoryAutoAdd behavior:
798/// we never auto add.
799
801{
802}
803
804////////////////////////////////////////////////////////////////////////////////
805/// Draw expression varexp for selected entries.
806/// Returns -1 in case of error or number of selected events in case of success.
807///
808/// This function accepts TCut objects as arguments.
809/// Useful to use the string operator +, example:
810/// ~~~{.cpp}
811/// ntuple.Draw("x",cut1+cut2+cut3);
812/// ~~~
813///
814
815Long64_t TChain::Draw(const char* varexp, const TCut& selection,
817{
818 if (fProofChain) {
819 // Make sure the element list is up to date
821 SetProof(true, true);
824 return fProofChain->Draw(varexp, selection, option, nentries, firstentry);
825 }
826
827 return TChain::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
828}
829
830////////////////////////////////////////////////////////////////////////////////
831/// Process all entries in this chain and draw histogram corresponding to
832/// expression varexp.
833/// Returns -1 in case of error or number of selected events in case of success.
834
835Long64_t TChain::Draw(const char* varexp, const char* selection,
837{
838 if (fProofChain) {
839 // Make sure the element list is up to date
841 SetProof(true, true);
844 return fProofChain->Draw(varexp, selection, option, nentries, firstentry);
845 }
846 GetPlayer();
847 if (LoadTree(firstentry) < 0) return 0;
848 return TTree::Draw(varexp,selection,option,nentries,firstentry);
849}
850
851////////////////////////////////////////////////////////////////////////////////
852/// See TTree::GetReadEntry().
853
854TBranch* TChain::FindBranch(const char* branchname)
855{
857 // Make sure the element list is up to date
859 SetProof(true, true);
860 return fProofChain->FindBranch(branchname);
861 }
862 if (fTree) {
863 return fTree->FindBranch(branchname);
864 }
865 LoadTree(0);
866 if (fTree) {
867 return fTree->FindBranch(branchname);
868 }
869 return nullptr;
870}
871
872////////////////////////////////////////////////////////////////////////////////
873/// See TTree::GetReadEntry().
874
875TLeaf* TChain::FindLeaf(const char* searchname)
876{
878 // Make sure the element list is up to date
880 SetProof(true, true);
881 return fProofChain->FindLeaf(searchname);
882 }
883 if (fTree) {
884 return fTree->FindLeaf(searchname);
885 }
886 LoadTree(0);
887 if (fTree) {
888 return fTree->FindLeaf(searchname);
889 }
890 return nullptr;
891}
892
893////////////////////////////////////////////////////////////////////////////////
894/// Returns the expanded value of the alias. Search in the friends if any.
895
896const char* TChain::GetAlias(const char* aliasName) const
897{
898 const char* alias = TTree::GetAlias(aliasName);
899 if (alias) {
900 return alias;
901 }
902 if (fTree) {
903 return fTree->GetAlias(aliasName);
904 }
905 const_cast<TChain*>(this)->LoadTree(0);
906 if (fTree) {
907 return fTree->GetAlias(aliasName);
908 }
909 return nullptr;
910}
911
912////////////////////////////////////////////////////////////////////////////////
913/// Return pointer to the branch name in the current tree.
914
916{
918 // Make sure the element list is up to date
920 SetProof(true, true);
921 return fProofChain->GetBranch(name);
922 }
923 if (fTree) {
924 return fTree->GetBranch(name);
925 }
926 LoadTree(0);
927 if (fTree) {
928 return fTree->GetBranch(name);
929 }
930 return nullptr;
931}
932
933////////////////////////////////////////////////////////////////////////////////
934/// See TTree::GetReadEntry().
935
936bool TChain::GetBranchStatus(const char* branchname) const
937{
939 // Make sure the element list is up to date
941 Warning("GetBranchStatus", "PROOF proxy not up-to-date:"
942 " run TChain::SetProof(true, true) first");
943 return fProofChain->GetBranchStatus(branchname);
944 }
945 return TTree::GetBranchStatus(branchname);
946}
947
948////////////////////////////////////////////////////////////////////////////////
949/// Return an iterator over the cluster of baskets starting at firstentry.
950///
951/// This iterator is not yet supported for TChain object.
952
954{
955 Fatal("GetClusterIterator","TChain objects are not supported");
956 return TTree::GetClusterIterator(-1);
957}
958
959////////////////////////////////////////////////////////////////////////////////
960/// Return absolute entry number in the chain.
961/// The input parameter entry is the entry number in
962/// the current tree of this chain.
963
965{
966 return entry + fTreeOffset[fTreeNumber];
967}
968
969////////////////////////////////////////////////////////////////////////////////
970/// Return the total number of entries in the chain.
971/// In case the number of entries in each tree is not yet known,
972/// the offset table is computed.
973
975{
977 // Make sure the element list is up to date
979 Warning("GetEntries", "PROOF proxy not up-to-date:"
980 " run TChain::SetProof(true, true) first");
981 return fProofChain->GetEntries();
982 }
984 const_cast<TChain*>(this)->LoadTree(TTree::kMaxEntries-1);
985 }
986 return fEntries;
987}
988
989////////////////////////////////////////////////////////////////////////////////
990/// Get entry from the file to memory.
991///
992/// - getall = 0 : get only active branches
993/// - getall = 1 : get all branches
994///
995/// Return the total number of bytes read,
996/// 0 bytes read indicates a failure.
997
999{
1000 Long64_t treeReadEntry = LoadTree(entry);
1001 if (treeReadEntry < 0) {
1002 return 0;
1003 }
1004 if (!fTree) {
1005 return 0;
1006 }
1007 return fTree->GetEntry(treeReadEntry, getall);
1008}
1009
1010////////////////////////////////////////////////////////////////////////////////
1011/// Return entry number corresponding to entry.
1012///
1013/// if no TEntryList set returns entry
1014/// else returns entry \#entry from this entry list and
1015/// also computes the global entry number (loads all tree headers)
1016
1018{
1019
1020 if (fEntryList){
1021 Int_t treenum = 0;
1022 Long64_t localentry = fEntryList->GetEntryAndTree(entry, treenum);
1023 //find the global entry number
1024 //same const_cast as in the GetEntries() function
1025 if (localentry<0) return -1;
1026 if (treenum != fTreeNumber){
1027 if (fTreeOffset[treenum]==TTree::kMaxEntries){
1028 for (Int_t i=0; i<=treenum; i++){
1030 (const_cast<TChain*>(this))->LoadTree(fTreeOffset[i-1]);
1031 }
1032 }
1033 //(const_cast<TChain*>(this))->LoadTree(fTreeOffset[treenum]);
1034 }
1035 Long64_t globalentry = fTreeOffset[treenum] + localentry;
1036 return globalentry;
1037 }
1038 return entry;
1039}
1040
1041////////////////////////////////////////////////////////////////////////////////
1042/// Return entry corresponding to major and minor number.
1043///
1044/// The function returns the total number of bytes read.
1045/// If the Tree has friend trees, the corresponding entry with
1046/// the index values (major,minor) is read. Note that the master Tree
1047/// and its friend may have different entry serial numbers corresponding
1048/// to (major,minor).
1049
1051{
1052 Long64_t serial = GetEntryNumberWithIndex(major, minor);
1053 if (serial < 0) return -1;
1054 return GetEntry(serial);
1055}
1056
1057////////////////////////////////////////////////////////////////////////////////
1058/// Return a pointer to the current file.
1059/// If no file is connected, the first file is automatically loaded.
1060
1062{
1063 if (fFile) {
1064 return fFile;
1065 }
1066 // Force opening the first file in the chain.
1067 const_cast<TChain*>(this)->LoadTree(0);
1068 return fFile;
1069}
1070
1071////////////////////////////////////////////////////////////////////////////////
1072/// Return a pointer to the leaf name in the current tree.
1073
1074TLeaf* TChain::GetLeaf(const char* branchname, const char *leafname)
1075{
1077 // Make sure the element list is up to date
1078 if (!TestBit(kProofUptodate))
1079 SetProof(true, true);
1080 return fProofChain->GetLeaf(branchname, leafname);
1081 }
1082 if (fTree) {
1083 return fTree->GetLeaf(branchname, leafname);
1084 }
1085 LoadTree(0);
1086 if (fTree) {
1087 return fTree->GetLeaf(branchname, leafname);
1088 }
1089 return nullptr;
1090}
1091
1092////////////////////////////////////////////////////////////////////////////////
1093/// Return a pointer to the leaf name in the current tree.
1094
1096{
1098 // Make sure the element list is up to date
1099 if (!TestBit(kProofUptodate))
1100 SetProof(true, true);
1101 return fProofChain->GetLeaf(name);
1102 }
1103 if (fTree) {
1104 return fTree->GetLeaf(name);
1105 }
1106 LoadTree(0);
1107 if (fTree) {
1108 return fTree->GetLeaf(name);
1109 }
1110 return nullptr;
1111}
1112
1113////////////////////////////////////////////////////////////////////////////////
1114/// Return a pointer to the list of branches of the current tree.
1115///
1116/// Warning: If there is no current TTree yet, this routine will open the
1117/// first in the chain.
1118///
1119/// Returns 0 on failure.
1120
1122{
1124 // Make sure the element list is up to date
1125 if (!TestBit(kProofUptodate))
1126 SetProof(true, true);
1128 }
1129 if (fTree) {
1130 return fTree->GetListOfBranches();
1131 }
1132 LoadTree(0);
1133 if (fTree) {
1134 return fTree->GetListOfBranches();
1135 }
1136 return nullptr;
1137}
1138
1139////////////////////////////////////////////////////////////////////////////////
1140/// Return a pointer to the list of leaves of the current tree.
1141///
1142/// Warning: May set the current tree!
1143
1145{
1147 // Make sure the element list is up to date
1148 if (!TestBit(kProofUptodate))
1149 SetProof(true, true);
1150 return fProofChain->GetListOfLeaves();
1151 }
1152 if (fTree) {
1153 return fTree->GetListOfLeaves();
1154 }
1155 LoadTree(0);
1156 if (fTree) {
1157 return fTree->GetListOfLeaves();
1158 }
1159 return nullptr;
1160}
1161
1162////////////////////////////////////////////////////////////////////////////////
1163/// Return maximum of column with name columname.
1164
1165Double_t TChain::GetMaximum(const char* columname)
1166{
1167 Double_t theMax = -DBL_MAX;
1168 for (Int_t file = 0; file < fNtrees; file++) {
1169 Long64_t first = fTreeOffset[file];
1170 LoadTree(first);
1171 Double_t curmax = fTree->GetMaximum(columname);
1172 if (curmax > theMax) {
1173 theMax = curmax;
1174 }
1175 }
1176 return theMax;
1177}
1178
1179////////////////////////////////////////////////////////////////////////////////
1180/// Return minimum of column with name columname.
1181
1182Double_t TChain::GetMinimum(const char* columname)
1183{
1184 Double_t theMin = DBL_MAX;
1185 for (Int_t file = 0; file < fNtrees; file++) {
1186 Long64_t first = fTreeOffset[file];
1187 LoadTree(first);
1188 Double_t curmin = fTree->GetMinimum(columname);
1189 if (curmin < theMin) {
1190 theMin = curmin;
1191 }
1192 }
1193 return theMin;
1194}
1195
1196////////////////////////////////////////////////////////////////////////////////
1197/// Return the number of branches of the current tree.
1198///
1199/// Warning: May set the current tree!
1200
1202{
1203 if (fTree) {
1204 return fTree->GetNbranches();
1205 }
1206 LoadTree(0);
1207 if (fTree) {
1208 return fTree->GetNbranches();
1209 }
1210 return 0;
1211}
1212
1213////////////////////////////////////////////////////////////////////////////////
1214/// See TTree::GetReadEntry().
1215
1217{
1219 // Make sure the element list is up to date
1220 if (!TestBit(kProofUptodate))
1221 Warning("GetBranchStatus", "PROOF proxy not up-to-date:"
1222 " run TChain::SetProof(true, true) first");
1223 return fProofChain->GetReadEntry();
1224 }
1225 return TTree::GetReadEntry();
1226}
1227
1228////////////////////////////////////////////////////////////////////////////////
1229/// Return the chain weight.
1230///
1231/// By default the weight is the weight of the current tree.
1232/// However, if the weight has been set in TChain::SetWeight()
1233/// with the option "global", then that weight will be returned.
1234///
1235/// Warning: May set the current tree!
1236
1238{
1239 if (TestBit(kGlobalWeight)) {
1240 return fWeight;
1241 } else {
1242 if (fTree) {
1243 return fTree->GetWeight();
1244 }
1245 const_cast<TChain*>(this)->LoadTree(0);
1246 if (fTree) {
1247 return fTree->GetWeight();
1248 }
1249 return 0;
1250 }
1251}
1252
1253////////////////////////////////////////////////////////////////////////////////
1254/// Move content to a new file. (NOT IMPLEMENTED for TChain)
1255bool TChain::InPlaceClone(TDirectory * /* new directory */, const char * /* options */)
1256{
1257 Error("InPlaceClone", "not implemented");
1258 return false;
1259}
1260
1261////////////////////////////////////////////////////////////////////////////////
1262/// Set the TTree to be reloaded as soon as possible. In particular this
1263/// is needed when adding a Friend.
1264///
1265/// If the tree has clones, copy them into the chain
1266/// clone list so we can change their branch addresses
1267/// when necessary.
1268///
1269/// This is to support the syntax:
1270/// ~~~ {.cpp}
1271/// TTree* clone = chain->GetTree()->CloneTree(0);
1272/// ~~~
1273
1275{
1276 if (fTree && fTree->GetListOfClones()) {
1277 for (TObjLink* lnk = fTree->GetListOfClones()->FirstLink(); lnk; lnk = lnk->Next()) {
1278 TTree* clone = (TTree*) lnk->GetObject();
1279 AddClone(clone);
1280 }
1281 }
1282 fTreeNumber = -1;
1283 fTree = nullptr;
1284}
1285
1286////////////////////////////////////////////////////////////////////////////////
1287/// Dummy function.
1288/// It could be implemented and load all baskets of all trees in the chain.
1289/// For the time being use TChain::Merge and TTree::LoadBasket
1290/// on the resulting tree.
1291
1293{
1294 Error("LoadBaskets", "Function not yet implemented for TChain.");
1295 return 0;
1296}
1297
1298////////////////////////////////////////////////////////////////////////////////
1299/// Find the tree which contains entry, and set it as the current tree.
1300///
1301/// Returns the entry number in that tree.
1302///
1303/// The input argument entry is the entry serial number in the whole chain.
1304///
1305/// In case of error, LoadTree returns a negative number:
1306/// * -1: The chain is empty.
1307/// * -2: The requested entry number is less than zero or too large for the chain.
1308/// * -3: The file corresponding to the entry could not be correctly open
1309/// * -4: The TChainElement corresponding to the entry is missing or
1310/// the TTree is missing from the file.
1311/// * -5: Internal error, please report the circumstance when this happen
1312/// as a ROOT issue.
1313/// * -6: An error occurred within the notify callback.
1314///
1315/// Calls fNotify->Notify() (if fNotify is not null) when starting the processing of a new sub-tree.
1316/// See TNotifyLink for more information on the notification mechanism.
1317///
1318/// \note This is the only routine which sets the value of fTree to a non-zero pointer.
1319///
1321{
1322 // We already have been visited while recursively looking
1323 // through the friends tree, let's return.
1325 return 0;
1326 }
1327
1328 if (!fNtrees) {
1329 // -- The chain is empty.
1330 return -1;
1331 }
1332
1333 if ((entry < 0) || ((entry > 0) && (entry >= fEntries && entry!=(TTree::kMaxEntries-1) ))) {
1334 // -- Invalid entry number.
1335 if (fTree) fTree->LoadTree(-1);
1336 fReadEntry = -1;
1337 return -2;
1338 }
1339
1340 // Find out which tree in the chain contains the passed entry.
1341 Int_t treenum = fTreeNumber;
1342 if ((fTreeNumber == -1) || (entry < fTreeOffset[fTreeNumber]) || (entry >= fTreeOffset[fTreeNumber+1]) || (entry==TTree::kMaxEntries-1)) {
1343 // -- Entry is *not* in the chain's current tree.
1344 // Do a linear search of the tree offset array.
1345 // FIXME: We could be smarter by starting at the
1346 // current tree number and going forwards,
1347 // then wrapping around at the end.
1348 for (treenum = 0; treenum < fNtrees; treenum++) {
1349 if (entry < fTreeOffset[treenum+1]) {
1350 break;
1351 }
1352 }
1353 }
1354
1355 // Calculate the entry number relative to the found tree.
1356 Long64_t treeReadEntry = entry - fTreeOffset[treenum];
1357 fReadEntry = entry;
1358
1359 // If entry belongs to the current tree return entry.
1360 if (fTree && treenum == fTreeNumber) {
1361 // First set the entry the tree on its owns friends
1362 // (the friends of the chain will be updated in the
1363 // next loop).
1364 fTree->LoadTree(treeReadEntry);
1365
1366 if (fFriends) {
1367 // The current tree has not changed but some of its friends might.
1368 //
1369 TIter next(fFriends);
1370 TFriendLock lock(this, kLoadTree);
1371 TFriendElement* fe = nullptr;
1372 while ((fe = (TFriendElement*) next())) {
1373 TTree* at = fe->GetTree();
1374 // If the tree is a
1375 // direct friend of the chain, it should be scanned
1376 // used the chain entry number and NOT the tree entry
1377 // number (treeReadEntry) hence we do:
1378 at->LoadTreeFriend(entry, this);
1379 }
1380 bool needUpdate = false;
1381 if (fTree->GetListOfFriends()) {
1383 if (fetree->IsUpdated()) {
1384 needUpdate = true;
1385 fetree->ResetUpdated();
1386 }
1387 }
1388 }
1389 if (needUpdate) {
1390 // Update the branch/leaf addresses and
1391 // the list of leaves in all TTreeFormula of the TTreePlayer (if any).
1392
1393 // Set the branch statuses for the newly opened file.
1394 TChainElement *frelement;
1395 TIter fnext(fStatus);
1396 while ((frelement = (TChainElement*) fnext())) {
1397 Int_t status = frelement->GetStatus();
1398 fTree->SetBranchStatus(frelement->GetName(), status);
1399 }
1400
1401 // Set the branch addresses for the newly opened file.
1402 fnext.Reset();
1403 while ((frelement = (TChainElement*) fnext())) {
1404 void* addr = frelement->GetBaddress();
1405 if (addr) {
1406 TBranch* br = fTree->GetBranch(frelement->GetName());
1407 TBranch** pp = frelement->GetBranchPtr();
1408 if (pp) {
1409 // FIXME: What if br is zero here?
1410 *pp = br;
1411 }
1412 if (br) {
1413 if (!frelement->GetCheckedType()) {
1415 (EDataType) frelement->GetBaddressType(), frelement->GetBaddressIsPtr());
1416 if ((res & kNeedEnableDecomposedObj) && !br->GetMakeClass()) {
1417 br->SetMakeClass(true);
1418 }
1419 frelement->SetDecomposedObj(br->GetMakeClass());
1420 frelement->SetCheckedType(true);
1421 }
1422 // FIXME: We may have to tell the branch it should
1423 // not be an owner of the object pointed at.
1424 br->SetAddress(addr);
1425 if (TestBit(kAutoDelete)) {
1426 br->SetAutoDelete(true);
1427 }
1428 }
1429 }
1430 }
1431 if (fPlayer) {
1433 }
1434 // Notify user if requested.
1435 if (fNotify) {
1436 if(!fNotify->Notify()) return -6;
1437 }
1438 }
1439 }
1440 return treeReadEntry;
1441 }
1442
1443 if (fExternalFriends) {
1445 external_fe->MarkUpdated();
1446 }
1447 }
1448
1449 // Delete the current tree and open the new tree.
1450 TTreeCache* tpf = nullptr;
1451 // Delete file unless the file owns this chain!
1452 // FIXME: The "unless" case here causes us to leak memory.
1453 if (fFile) {
1454 if (!fDirectory->GetList()->FindObject(this)) {
1455 if (fTree) {
1456 // (fFile != 0 && fTree == 0) can happen when
1457 // InvalidateCurrentTree is called (for example from
1458 // AddFriend). Having fTree === 0 is necessary in that
1459 // case because in some cases GetTree is used as a check
1460 // to see if a TTree is already loaded.
1461 // However, this prevent using the following to reuse
1462 // the TTreeCache object.
1463 tpf = fTree->GetReadCache(fFile);
1464 if (tpf) {
1465 tpf->ResetCache();
1466 }
1467
1468 fFile->SetCacheRead(nullptr, fTree);
1469 // If the tree has clones, copy them into the chain
1470 // clone list so we can change their branch addresses
1471 // when necessary.
1472 //
1473 // This is to support the syntax:
1474 //
1475 // TTree* clone = chain->GetTree()->CloneTree(0);
1476 //
1477 // We need to call the invalidate exactly here, since
1478 // we no longer need the value of fTree and it is
1479 // about to be deleted.
1481 }
1482
1483 if (fCanDeleteRefs) {
1484 fFile->Close("R");
1485 }
1486 delete fFile;
1487 fFile = nullptr;
1488 } else {
1489 // If the tree has clones, copy them into the chain
1490 // clone list so we can change their branch addresses
1491 // when necessary.
1492 //
1493 // This is to support the syntax:
1494 //
1495 // TTree* clone = chain->GetTree()->CloneTree(0);
1496 //
1498 }
1499 }
1500
1501 TChainElement* element = (TChainElement*) fFiles->At(treenum);
1502 if (!element) {
1503 if (treeReadEntry) {
1504 return -4;
1505 }
1506 // Last attempt, just in case all trees in the chain have 0 entries.
1507 element = (TChainElement*) fFiles->At(0);
1508 if (!element) {
1509 return -4;
1510 }
1511 }
1512
1513 // FIXME: We leak memory here, we've just lost the open file
1514 // if we did not delete it above.
1515 {
1517 const char *option = fGlobalRegistration ? "READ" : "READ_WITHOUT_GLOBALREGISTRATION";
1518 fFile = TFile::Open(element->GetTitle(), option);
1521 }
1522
1523 // ----- Begin of modifications by MvL
1524 Int_t returnCode = 0;
1525 if (!fFile || fFile->IsZombie()) {
1526 if (fFile) {
1527 delete fFile;
1528 fFile = nullptr;
1529 }
1530 // Note: We do *not* own fTree.
1531 fTree = nullptr;
1532 returnCode = -3;
1533 } else {
1534 if (fPerfStats)
1536
1537 // Note: We do *not* own fTree after this, the file does!
1538 fTree = dynamic_cast<TTree*>(fFile->Get(element->GetName()));
1539 if (!fTree) {
1540 // Now that we do not check during the addition, we need to check here!
1541 Error("LoadTree", "Cannot find tree with name %s in file %s", element->GetName(), element->GetTitle());
1542 delete fFile;
1543 fFile = nullptr;
1544 // We do not return yet so that 'fEntries' can be updated with the
1545 // sum of the entries of all the other trees.
1546 returnCode = -4;
1547 } else if (!fGlobalRegistration) {
1549 }
1550 // Propagate the IMT settings
1551 if (fTree) {
1553 }
1554 }
1555
1556 fTreeNumber = treenum;
1557 // FIXME: We own fFile, we must be careful giving away a pointer to it!
1558 // FIXME: We may set fDirectory to zero here!
1559 fDirectory = fFile;
1560
1561 // Reuse cache from previous file (if any).
1562 if (tpf) {
1563 if (fFile) {
1564 // FIXME: fTree may be zero here.
1565 tpf->UpdateBranches(fTree);
1566 tpf->ResetCache();
1567 fFile->SetCacheRead(tpf, fTree);
1568 } else {
1569 // FIXME: One of the file in the chain is missing
1570 // we have no place to hold the pointer to the
1571 // TTreeCache.
1572 delete tpf;
1573 tpf = nullptr;
1574 }
1575 } else {
1576 if (fCacheUserSet) {
1577 this->SetCacheSize(fCacheSize);
1578 }
1579 }
1580
1581 // Check if fTreeOffset has really been set.
1582 Long64_t nentries = 0;
1583 if (fTree) {
1585 }
1586
1590 element->SetNumberEntries(nentries);
1591 // Below we must test >= in case the tree has no entries.
1592 if (entry >= fTreeOffset[fTreeNumber+1]) {
1593 if ((fTreeNumber < (fNtrees - 1)) && (entry < fTreeOffset[fTreeNumber+2])) {
1594 // The request entry is not in the tree 'fTreeNumber' we will need
1595 // to look further.
1596
1597 // Before moving on, let's record the result.
1598 element->SetLoadResult(returnCode);
1599
1600 // Before trying to read the file file/tree, notify the user
1601 // that we have switched trees if requested; the user might need
1602 // to properly account for the number of files/trees even if they
1603 // have no entries.
1604 if (fNotify) {
1605 if(!fNotify->Notify()) return -6;
1606 }
1607
1608 // Load the next TTree.
1609 return LoadTree(entry);
1610 } else {
1611 treeReadEntry = fReadEntry = -2;
1612 }
1613 }
1614 }
1615
1616
1617 if (!fTree) {
1618 // The Error message already issued. However if we reach here
1619 // we need to make sure that we do not use fTree.
1620 //
1621 // Force a reload of the tree next time.
1622 fTreeNumber = -1;
1623
1624 element->SetLoadResult(returnCode);
1625 return returnCode;
1626 }
1627 // ----- End of modifications by MvL
1628
1629 // Copy the chain's clone list into the new tree's
1630 // clone list so that branch addresses stay synchronized.
1631 if (fClones) {
1632 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
1633 TTree* clone = (TTree*) lnk->GetObject();
1634 ((TChain*) fTree)->TTree::AddClone(clone);
1635 }
1636 }
1637
1638 // Since some of the friends of this chain might simple trees
1639 // (i.e., not really chains at all), we need to execute this
1640 // before calling LoadTree(entry) on the friends (so that
1641 // they use the correct read entry number).
1642
1643 // Change the new current tree to the new entry.
1644 Long64_t loadResult = fTree->LoadTree(treeReadEntry);
1645 if (loadResult == treeReadEntry) {
1646 element->SetLoadResult(0);
1647 } else {
1648 // This is likely to be an internal error, if treeReadEntry was not in range
1649 // (or intentionally -2 for TChain::GetEntries) then something happened
1650 // that is very odd/surprising.
1651 element->SetLoadResult(-5);
1652 }
1653
1654
1655 // Change the chain friends to the new entry.
1656 if (fFriends) {
1657 // An alternative would move this code to each of the function
1658 // calling LoadTree (and to overload a few more).
1659 TIter next(fFriends);
1660 TFriendLock lock(this, kLoadTree);
1661 TFriendElement* fe = nullptr;
1662 while ((fe = (TFriendElement*) next())) {
1663 TTree* t = fe->GetTree();
1664 if (!t) continue;
1665 if (t->GetTreeIndex()) {
1666 t->GetTreeIndex()->UpdateFormulaLeaves(nullptr);
1667 }
1668 if (t->GetTree() && t->GetTree()->GetTreeIndex()) {
1670 }
1671 if (treeReadEntry == -2) {
1672 // an entry after the end of the chain was requested (it usually happens when GetEntries is called)
1673 t->LoadTree(entry);
1674 } else {
1675 t->LoadTreeFriend(entry, this);
1676 }
1677 TTree* friend_t = t->GetTree();
1678 if (friend_t) {
1679 auto localfe = fTree->AddFriend(t, fe->GetName());
1681 }
1682 }
1683 }
1684
1687
1690
1691 // Set the branch statuses for the newly opened file.
1692 TIter next(fStatus);
1693 while ((element = (TChainElement*) next())) {
1694 Int_t status = element->GetStatus();
1695 fTree->SetBranchStatus(element->GetName(), status);
1696 }
1697
1698 // Set the branch addresses for the newly opened file.
1699 next.Reset();
1700 while ((element = (TChainElement*) next())) {
1701 void* addr = element->GetBaddress();
1702 if (addr) {
1703 TBranch* br = fTree->GetBranch(element->GetName());
1704 TBranch** pp = element->GetBranchPtr();
1705 if (pp) {
1706 // FIXME: What if br is zero here?
1707 *pp = br;
1708 }
1709 if (br) {
1710 if (!element->GetCheckedType()) {
1712 (EDataType) element->GetBaddressType(), element->GetBaddressIsPtr());
1713 if ((res & kNeedEnableDecomposedObj) && !br->GetMakeClass()) {
1714 br->SetMakeClass(true);
1715 }
1716 element->SetDecomposedObj(br->GetMakeClass());
1717 element->SetCheckedType(true);
1718 }
1719 // FIXME: We may have to tell the branch it should
1720 // not be an owner of the object pointed at.
1721 br->SetAddress(addr);
1722 if (TestBit(kAutoDelete)) {
1723 br->SetAutoDelete(true);
1724 }
1725 }
1726 }
1727 }
1728
1729 // Update the addresses of the chain's cloned trees, if any.
1730 if (fClones) {
1731 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
1732 TTree* clone = (TTree*) lnk->GetObject();
1734 }
1735 }
1736
1737 // Update list of leaves in all TTreeFormula's of the TTreePlayer (if any).
1738 if (fPlayer) {
1740 }
1741
1742 // Notify user we have switched trees if requested.
1743 if (fNotify) {
1744 if(!fNotify->Notify()) return -6;
1745 }
1746
1747 // Return the new local entry number.
1748 return treeReadEntry;
1749}
1750
1751////////////////////////////////////////////////////////////////////////////////
1752/// Check / locate the files in the chain.
1753/// By default only the files not yet looked up are checked.
1754/// Use force = true to check / re-check every file.
1755
1756void TChain::Lookup(bool force)
1757{
1758 TIter next(fFiles);
1759 TChainElement* element = nullptr;
1760 Int_t nelements = fFiles->GetEntries();
1761 printf("\n");
1762 printf("TChain::Lookup - Looking up %d files .... \n", nelements);
1763 Int_t nlook = 0;
1764 TFileStager *stg = nullptr;
1765 while ((element = (TChainElement*) next())) {
1766 // Do not do it more than needed
1767 if (element->HasBeenLookedUp() && !force) continue;
1768 // Count
1769 nlook++;
1770 // Get the Url
1771 TUrl elemurl(element->GetTitle(), true);
1772 // Save current options and anchor
1773 TString anchor = elemurl.GetAnchor();
1774 TString options = elemurl.GetOptions();
1775 // Reset options and anchor
1776 elemurl.SetOptions("");
1777 elemurl.SetAnchor("");
1778 // Locate the file
1779 TString eurl(elemurl.GetUrl());
1780 if (!stg || !stg->Matches(eurl)) {
1781 SafeDelete(stg);
1782 {
1784 stg = TFileStager::Open(eurl);
1785 }
1786 if (!stg) {
1787 Error("Lookup", "TFileStager instance cannot be instantiated");
1788 break;
1789 }
1790 }
1791 Int_t n1 = (nelements > 100) ? (Int_t) nelements / 100 : 1;
1792 if (stg->Locate(eurl.Data(), eurl) == 0) {
1793 if (nlook > 0 && !(nlook % n1)) {
1794 printf("Lookup | %3d %% finished\r", 100 * nlook / nelements);
1795 fflush(stdout);
1796 }
1797 // Get the effective end-point Url
1798 elemurl.SetUrl(eurl);
1799 // Restore original options and anchor, if any
1800 elemurl.SetOptions(options);
1801 elemurl.SetAnchor(anchor);
1802 // Save it into the element
1803 element->SetTitle(elemurl.GetUrl());
1804 // Remember
1805 element->SetLookedUp();
1806 } else {
1807 // Failure: remove
1808 fFiles->Remove(element);
1809 if (gSystem->AccessPathName(eurl))
1810 Error("Lookup", "file %s does not exist\n", eurl.Data());
1811 else
1812 Error("Lookup", "file %s cannot be read\n", eurl.Data());
1813 }
1814 }
1815 if (nelements > 0)
1816 printf("Lookup | %3d %% finished\n", 100 * nlook / nelements);
1817 else
1818 printf("\n");
1819 fflush(stdout);
1820 SafeDelete(stg);
1821}
1822
1823////////////////////////////////////////////////////////////////////////////////
1824/// Loop on nentries of this chain starting at firstentry. (NOT IMPLEMENTED)
1825
1827{
1828 Error("Loop", "Function not yet implemented");
1829
1830 if (option || nentries || firstentry) { } // keep warnings away
1831
1832#if 0
1833 if (LoadTree(firstentry) < 0) return;
1834
1835 if (firstentry < 0) firstentry = 0;
1836 Long64_t lastentry = firstentry + nentries -1;
1837 if (lastentry > fEntries-1) {
1838 lastentry = fEntries -1;
1839 }
1840
1841 GetPlayer();
1842 GetSelector();
1843 fSelector->Start(option);
1844
1845 Long64_t entry = firstentry;
1846 Int_t tree,e0,en;
1847 for (tree=0;tree<fNtrees;tree++) {
1848 e0 = fTreeOffset[tree];
1849 en = fTreeOffset[tree+1] - 1;
1850 if (en > lastentry) en = lastentry;
1851 if (entry > en) continue;
1852
1853 LoadTree(entry);
1854 fSelector->BeginFile();
1855
1856 while (entry <= en) {
1857 fSelector->Execute(fTree, entry - e0);
1858 entry++;
1859 }
1860 fSelector->EndFile();
1861 }
1862
1863 fSelector->Finish(option);
1864#endif
1865}
1866
1867////////////////////////////////////////////////////////////////////////////////
1868/// List the chain.
1869
1871{
1873 TIter next(fFiles);
1874 TChainElement* file = nullptr;
1876 while ((file = (TChainElement*)next())) {
1877 file->ls(option);
1878 }
1880}
1881
1882////////////////////////////////////////////////////////////////////////////////
1883/// Merge all the entries in the chain into a new tree in a new file.
1884///
1885/// See important note in the following function Merge().
1886///
1887/// If the chain is expecting the input tree inside a directory,
1888/// this directory is NOT created by this routine.
1889///
1890/// So in a case where we have:
1891/// ~~~ {.cpp}
1892/// TChain ch("mydir/mytree");
1893/// ch.Merge("newfile.root");
1894/// ~~~
1895/// The resulting file will have not subdirectory. To recreate
1896/// the directory structure do:
1897/// ~~~ {.cpp}
1898/// TFile* file = TFile::Open("newfile.root", "RECREATE");
1899/// file->mkdir("mydir")->cd();
1900/// ch.Merge(file, 0);
1901/// ~~~
1902
1904{
1905 TFile *file = TFile::Open(name, "recreate", "chain files", 1);
1906 return Merge(file, 0, option);
1907}
1908
1909////////////////////////////////////////////////////////////////////////////////
1910/// Merge all chains in the collection. (NOT IMPLEMENTED)
1911
1912Long64_t TChain::Merge(TCollection* /* list */, Option_t* /* option */ )
1913{
1914 Error("Merge", "not implemented");
1915 return -1;
1916}
1917
1918////////////////////////////////////////////////////////////////////////////////
1919/// Merge all chains in the collection. (NOT IMPLEMENTED)
1920
1922{
1923 Error("Merge", "not implemented");
1924 return -1;
1925}
1926
1927////////////////////////////////////////////////////////////////////////////////
1928/// Merge all the entries in the chain into a new tree in the current file.
1929///
1930/// Note: The "file" parameter is *not* the file where the new
1931/// tree will be inserted. The new tree is inserted into
1932/// gDirectory, which is usually the most recently opened
1933/// file, or the directory most recently cd()'d to.
1934///
1935/// If option = "C" is given, the compression level for all branches
1936/// in the new Tree is set to the file compression level. By default,
1937/// the compression level of all branches is the original compression
1938/// level in the old trees.
1939///
1940/// If basketsize > 1000, the basket size for all branches of the
1941/// new tree will be set to basketsize.
1942///
1943/// Example using the file generated in $ROOTSYS/test/Event
1944/// merge two copies of Event.root
1945/// ~~~ {.cpp}
1946/// gSystem.Load("libEvent");
1947/// TChain ch("T");
1948/// ch.Add("Event1.root");
1949/// ch.Add("Event2.root");
1950/// ch.Merge("all.root");
1951/// ~~~
1952/// If the chain is expecting the input tree inside a directory,
1953/// this directory is NOT created by this routine.
1954///
1955/// So if you do:
1956/// ~~~ {.cpp}
1957/// TChain ch("mydir/mytree");
1958/// ch.Merge("newfile.root");
1959/// ~~~
1960/// The resulting file will not have subdirectories. In order to
1961/// preserve the directory structure do the following instead:
1962/// ~~~ {.cpp}
1963/// TFile* file = TFile::Open("newfile.root", "RECREATE");
1964/// file->mkdir("mydir")->cd();
1965/// ch.Merge(file, 0);
1966/// ~~~
1967/// If 'option' contains the word 'fast' the merge will be done without
1968/// unzipping or unstreaming the baskets (i.e., a direct copy of the raw
1969/// bytes on disk).
1970///
1971/// When 'fast' is specified, 'option' can also contains a
1972/// sorting order for the baskets in the output file.
1973///
1974/// There is currently 3 supported sorting order:
1975/// ~~~ {.cpp}
1976/// SortBasketsByOffset (the default)
1977/// SortBasketsByBranch
1978/// SortBasketsByEntry
1979/// ~~~
1980/// When using SortBasketsByOffset the baskets are written in
1981/// the output file in the same order as in the original file
1982/// (i.e. the basket are sorted on their offset in the original
1983/// file; Usually this also means that the baskets are sorted
1984/// on the index/number of the _last_ entry they contain)
1985///
1986/// When using SortBasketsByBranch all the baskets of each
1987/// individual branches are stored contiguously. This tends to
1988/// optimize reading speed when reading a small number (1->5) of
1989/// branches, since all their baskets will be clustered together
1990/// instead of being spread across the file. However it might
1991/// decrease the performance when reading more branches (or the full
1992/// entry).
1993///
1994/// When using SortBasketsByEntry the baskets with the lowest
1995/// starting entry are written first. (i.e. the baskets are
1996/// sorted on the index/number of the first entry they contain).
1997/// This means that on the file the baskets will be in the order
1998/// in which they will be needed when reading the whole tree
1999/// sequentially.
2000///
2001/// ## IMPORTANT Note 1: AUTOMATIC FILE OVERFLOW
2002///
2003/// When merging many files, it may happen that the resulting file
2004/// reaches a size > TTree::fgMaxTreeSize (default = 100 GBytes).
2005/// In this case the current file is automatically closed and a new
2006/// file started. If the name of the merged file was "merged.root",
2007/// the subsequent files will be named "merged_1.root", "merged_2.root",
2008/// etc. fgMaxTreeSize may be modified via the static function
2009/// TTree::SetMaxTreeSize.
2010/// When in fast mode, the check and switch is only done in between each
2011/// input file.
2012///
2013/// ## IMPORTANT Note 2: The output file is automatically closed and deleted.
2014///
2015/// This is required because in general the automatic file overflow described
2016/// above may happen during the merge.
2017/// If only the current file is produced (the file passed as first argument),
2018/// one can instruct Merge to not close and delete the file by specifying
2019/// the option "keep".
2020///
2021/// The function returns the total number of files produced.
2022/// To check that all files have been merged use something like:
2023/// ~~~ {.cpp}
2024/// if (newchain->GetEntries()!=oldchain->GetEntries()) {
2025/// ... not all the file have been copied ...
2026/// }
2027/// ~~~
2028
2030{
2031 // We must have been passed a file, we will use it
2032 // later to reset the compression level of the branches.
2033 if (!file) {
2034 // FIXME: We need an error message here.
2035 return 0;
2036 }
2037
2038 // Options
2039 bool fastClone = false;
2040 TString opt = option;
2041 opt.ToLower();
2042 if (opt.Contains("fast")) {
2043 fastClone = true;
2044 }
2045
2046 // The chain tree must have a list of branches
2047 // because we may try to change their basket
2048 // size later.
2049 TObjArray* lbranches = GetListOfBranches();
2050 if (!lbranches) {
2051 // FIXME: We need an error message here.
2052 return 0;
2053 }
2054
2055 // The chain must have a current tree because
2056 // that is the one we will clone.
2057 if (!fTree) {
2058 // -- LoadTree() has not yet been called, no current tree.
2059 // FIXME: We need an error message here.
2060 return 0;
2061 }
2062
2063 // Copy the chain's current tree without
2064 // copying any entries, we will do that later.
2065 TTree* newTree = CloneTree(0);
2066 if (!newTree) {
2067 // FIXME: We need an error message here.
2068 return 0;
2069 }
2070
2071 // Strip out the (potential) directory name.
2072 // FIXME: The merged chain may or may not have the
2073 // same name as the original chain. This is
2074 // bad because the chain name determines the
2075 // names of the trees in the chain by default.
2076 newTree->SetName(gSystem->BaseName(GetName()));
2077
2078 // FIXME: Why do we do this?
2079 newTree->SetAutoSave(2000000000);
2080
2081 // Circularity is incompatible with merging, it may
2082 // force us to throw away entries, which is not what
2083 // we are supposed to do.
2084 newTree->SetCircular(0);
2085
2086 // Reset the compression level of the branches.
2087 if (opt.Contains("c")) {
2088 TBranch* branch = nullptr;
2089 TIter nextb(newTree->GetListOfBranches());
2090 while ((branch = (TBranch*) nextb())) {
2092 }
2093 }
2094
2095 // Reset the basket size of the branches.
2096 if (basketsize > 1000) {
2097 TBranch* branch = nullptr;
2098 TIter nextb(newTree->GetListOfBranches());
2099 while ((branch = (TBranch*) nextb())) {
2100 branch->SetBasketSize(basketsize);
2101 }
2102 }
2103
2104 // Copy the entries.
2105 if (fastClone) {
2106 if ( newTree->CopyEntries( this, -1, option ) < 0 ) {
2107 // There was a problem!
2108 Error("Merge", "TTree has not been cloned\n");
2109 }
2110 } else {
2111 newTree->CopyEntries( this, -1, option );
2112 }
2113
2114 // Write the new tree header.
2115 newTree->Write();
2116
2117 // Get our return value.
2118 Int_t nfiles = newTree->GetFileNumber() + 1;
2119
2120 // Close and delete the current file of the new tree.
2121 if (!opt.Contains("keep")) {
2122 // Delete the currentFile and the TTree object.
2123 delete newTree->GetCurrentFile();
2124 }
2125 return nfiles;
2126}
2127
2128////////////////////////////////////////////////////////////////////////////////
2129/// Get the tree url or filename and other information from the name
2130///
2131/// A treename and a url's query section is split off from name. The
2132/// splitting depends on whether the resulting filename is to be
2133/// subsequently treated for wildcards or not, since the question mark is
2134/// both the url query identifier and a wildcard. Wildcard matching is not
2135/// done in this method itself.
2136/// ~~~ {.cpp}
2137/// [xxx://host]/a/path/file_name[?query[#treename]]
2138/// ~~~
2139///
2140/// The following way to specify the treename is still supported with the
2141/// constrain that the file name contains the sub-string '.root'.
2142/// This is now deprecated and will be removed in future versions.
2143/// ~~~ {.cpp}
2144/// [xxx://host]/a/path/file.root[.oext][/treename]
2145/// [xxx://host]/a/path/file.root[.oext][/treename][?query]
2146/// ~~~
2147///
2148/// Note that in a case like this
2149/// ~~~ {.cpp}
2150/// [xxx://host]/a/path/file#treename
2151/// ~~~
2152/// i.e. anchor but no options (query), the filename will be the full path, as
2153/// the anchor may be the internal file name of an archive. Use '?#%treename' to
2154/// pass the treename if the query field is empty.
2155///
2156/// \param[in] name is the original name
2157/// \param[out] filename the url or filename to be opened or matched
2158/// \param[out] treename the treename, which may be found in a url fragment section
2159/// as a trailing part of the name (deprecated).
2160/// If not found this will be empty.
2161/// Exception: a fragment containing the '=' character is _not_
2162/// interpreted as a treename
2163/// \param[out] query is the url query section, including the leading question
2164/// mark. If not found or the query section is only followed by
2165/// a fragment this will be empty.
2166/// \param[out] suffix the portion of name which was removed to from filename.
2167
2168void TChain::ParseTreeFilename(const char *name, TString &filename, TString &treename, TString &query,
2169 TString &suffix) const
2170{
2171 Ssiz_t pIdx = kNPOS;
2172 filename.Clear();
2173 treename.Clear();
2174 query.Clear();
2175 suffix.Clear();
2176
2177 // General case
2178 TUrl url(name, true);
2179 filename = (strcmp(url.GetProtocol(), "file")) ? url.GetUrl() : url.GetFileAndOptions();
2180
2181 TString fn = url.GetFile();
2182 // Extract query, if any
2183 if (url.GetOptions() && (strlen(url.GetOptions()) > 0))
2184 query.Form("?%s", url.GetOptions());
2185 // The treename can be passed as anchor
2186 const char *anchor = url.GetAnchor();
2187 if (anchor && anchor[0] != '\0') {
2188 // Support "?#tree_name" and "?query#tree_name"
2189 // "#tree_name" (no '?' is for tar archives)
2190 // If the treename would contain a '=', treat the anchor as part of the query instead. This makes sure
2191 // that Davix parameters are passed.
2192 if (!query.IsNull() || strstr(name, "?#")) {
2193 if (strstr(anchor, "=")) {
2194 query.Append("#");
2195 query.Append(anchor);
2196 } else {
2197 treename = anchor;
2198 }
2199 } else {
2200 // The anchor is part of the file name
2201 fn = url.GetFileAndOptions();
2202 }
2203 }
2204 // Suffix
2205 suffix = url.GetFileAndOptions();
2206 // Get options from suffix by removing the file name
2207 suffix.Replace(suffix.Index(fn), fn.Length(), "");
2208 // Remove the options suffix from the original file name
2209 filename.Replace(filename.Index(suffix), suffix.Length(), "");
2210
2211 // Special case: [...]file.root/treename
2212 static const char *dotr = ".root";
2213 static Ssiz_t dotrl = strlen(dotr);
2214 // Find the last one
2215 Ssiz_t js = filename.Index(dotr);
2216 while (js != kNPOS) {
2217 pIdx = js;
2218 js = filename.Index(dotr, js + 1);
2219 }
2220 if (pIdx != kNPOS) {
2221 static const char *slash = "/";
2222 static Ssiz_t slashl = strlen(slash);
2223 // Find the last one
2224 Ssiz_t ppIdx = filename.Index(slash, pIdx + dotrl);
2225 if (ppIdx != kNPOS) {
2226 // Good treename with the old recipe
2227 treename = filename(ppIdx + slashl, filename.Length());
2228 filename.Remove(ppIdx + slashl - 1);
2229 suffix.Insert(0, TString::Format("/%s", treename.Data()));
2230 }
2231 }
2232}
2233
2234////////////////////////////////////////////////////////////////////////////////
2235/// Print the header information of each tree in the chain.
2236/// See TTree::Print for a list of options.
2237
2239{
2240 TIter next(fFiles);
2241 TChainElement *element;
2242 while ((element = (TChainElement*)next())) {
2243 Printf("******************************************************************************");
2244 Printf("*Chain :%-10s: %-54s *", GetName(), element->GetTitle());
2245 Printf("******************************************************************************");
2246 TFile *file = TFile::Open(element->GetTitle());
2247 if (file && !file->IsZombie()) {
2248 TTree *tree = (TTree*)file->Get(element->GetName());
2249 if (tree) tree->Print(option);
2250 }
2251 delete file;
2252 }
2253}
2254
2255////////////////////////////////////////////////////////////////////////////////
2256/// Process all entries in this chain, calling functions in filename.
2257/// The return value is -1 in case of error and TSelector::GetStatus() in
2258/// in case of success.
2259/// See TTree::Process.
2260
2262{
2263 if (fProofChain) {
2264 // Make sure the element list is up to date
2265 if (!TestBit(kProofUptodate))
2266 SetProof(true, true);
2269 return fProofChain->Process(filename, option, nentries, firstentry);
2270 }
2271
2272 if (LoadTree(firstentry) < 0) {
2273 return 0;
2274 }
2275 return TTree::Process(filename, option, nentries, firstentry);
2276}
2277
2278////////////////////////////////////////////////////////////////////////////////
2279/// Process this chain executing the code in selector.
2280/// The return value is -1 in case of error and TSelector::GetStatus() in
2281/// in case of success.
2282
2284{
2285 if (fProofChain) {
2286 // Make sure the element list is up to date
2287 if (!TestBit(kProofUptodate))
2288 SetProof(true, true);
2291 return fProofChain->Process(selector, option, nentries, firstentry);
2292 }
2293
2294 return TTree::Process(selector, option, nentries, firstentry);
2295}
2296
2297////////////////////////////////////////////////////////////////////////////////
2298/// Make sure that obj (which is being deleted or will soon be) is no
2299/// longer referenced by this TTree.
2300
2302{
2303 if (fFile == obj) {
2304 fFile = nullptr;
2305 fDirectory = nullptr;
2306 fTree = nullptr;
2307 }
2308 if (fDirectory == obj) {
2309 fDirectory = nullptr;
2310 fTree = nullptr;
2311 }
2312 if (fTree == obj) {
2313 fTree = nullptr;
2314 }
2315}
2316
2317////////////////////////////////////////////////////////////////////////////////
2318/// Remove a friend from the list of friends.
2319
2321{
2322 // We already have been visited while recursively looking
2323 // through the friends tree, let return
2324
2325 if (!fFriends) {
2326 return;
2327 }
2328
2329 TTree::RemoveFriend(oldFriend);
2330
2331 if (fProofChain)
2332 // This updates the proxy chain when we will really use PROOF
2334
2335 // We need to invalidate the loading of the current tree because its list
2336 // of real friends is now obsolete. It is repairable only from LoadTree.
2338}
2339
2340////////////////////////////////////////////////////////////////////////////////
2341/// Resets the state of this chain.
2342
2344{
2345 delete fFile;
2346 fFile = nullptr;
2347 fNtrees = 0;
2348 fTreeNumber = -1;
2349 fTree = nullptr;
2350 fFile = nullptr;
2351 fFiles->Delete();
2352 fStatus->Delete();
2353 fTreeOffset[0] = 0;
2354 TChainElement* element = new TChainElement("*", "");
2355 fStatus->Add(element);
2356 fDirectory = nullptr;
2357
2358 TTree::Reset();
2359}
2360
2361////////////////////////////////////////////////////////////////////////////////
2362/// Resets the state of this chain after a merge (keep the customization but
2363/// forget the data).
2364
2366{
2367 fNtrees = 0;
2368 fTreeNumber = -1;
2369 fTree = nullptr;
2370 fFile = nullptr;
2371 fFiles->Delete();
2372 fTreeOffset[0] = 0;
2373
2375}
2376
2377////////////////////////////////////////////////////////////////////////////////
2378/// Save TChain as a C++ statements on output stream out.
2379/// With the option "friend" save the description of all the
2380/// TChain's friend trees or chains as well.
2381
2382void TChain::SavePrimitive(std::ostream &out, Option_t *option)
2383{
2384 static Int_t chCounter = 0;
2385
2386 TString chName = gInterpreter->MapCppName(GetName());
2387 if (chName.IsNull())
2388 chName = "_chain";
2389 ++chCounter;
2390 chName += chCounter;
2391
2392 TString opt = option;
2393 opt.ToLower();
2394
2395 out << " TChain *" << chName.Data() << " = new TChain(\"" << GetName() << "\");" << std::endl;
2396
2397 if (opt.Contains("friend")) {
2398 opt.ReplaceAll("friend", "");
2399 for (TObject *frel : *fFriends) {
2400 TTree *frtree = ((TFriendElement *)frel)->GetTree();
2401 if (dynamic_cast<TChain *>(frtree)) {
2402 if (strcmp(frtree->GetName(), GetName()) != 0)
2403 --chCounter; // make friends get the same chain counter
2404 frtree->SavePrimitive(out, opt.Data());
2405 out << " " << chName.Data() << "->AddFriend(\"" << frtree->GetName() << "\");" << std::endl;
2406 } else { // ordinary friend TTree
2407 TDirectory *file = frtree->GetDirectory();
2408 if (file && dynamic_cast<TFile *>(file))
2409 out << " " << chName.Data() << "->AddFriend(\"" << frtree->GetName() << "\", \"" << file->GetName()
2410 << "\");" << std::endl;
2411 }
2412 }
2413 }
2414 out << std::endl;
2415
2416 for (TObject *el : *fFiles) {
2417 TChainElement *chel = (TChainElement *)el;
2418 // Save tree file if it is really loaded to the chain
2419 if (chel->GetLoadResult() == 0 && chel->GetEntries() != 0) {
2420 if (chel->GetEntries() == TTree::kMaxEntries) // tree number of entries is not yet known
2421 out << " " << chName.Data() << "->AddFile(\"" << chel->GetTitle() << "\");" << std::endl;
2422 else
2423 out << " " << chName.Data() << "->AddFile(\"" << chel->GetTitle() << "\"," << chel->GetEntries() << ");"
2424 << std::endl;
2425 }
2426 }
2427 out << std::endl;
2428
2429 SaveMarkerAttributes(out, chName.Data(), 1, 1, 1);
2430}
2431
2432////////////////////////////////////////////////////////////////////////////////
2433/// Loop on tree and print entries passing selection.
2434/// - If varexp is 0 (or "") then print only first 8 columns.
2435/// - If varexp = "*" print all columns.
2436/// - Otherwise a columns selection can be made using "var1:var2:var3".
2437/// See TTreePlayer::Scan for more information.
2438
2439Long64_t TChain::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
2440{
2441 if (LoadTree(firstentry) < 0) {
2442 return 0;
2443 }
2444 return TTree::Scan(varexp, selection, option, nentries, firstentry);
2445}
2446
2447////////////////////////////////////////////////////////////////////////////////
2448/// Set the global branch kAutoDelete bit.
2449///
2450/// When LoadTree loads a new Tree, the branches for which
2451/// the address is set will have the option AutoDelete set
2452/// For more details on AutoDelete, see TBranch::SetAutoDelete.
2453
2454void TChain::SetAutoDelete(bool autodelete)
2455{
2456 if (autodelete) {
2457 SetBit(kAutoDelete, true);
2458 } else {
2459 SetBit(kAutoDelete, false);
2460 }
2461}
2462
2464{
2465 // Set the cache size of the underlying TTree,
2466 // See TTree::SetCacheSize.
2467 // Returns 0 cache state ok (exists or not, as appropriate)
2468 // -1 on error
2469
2470 Int_t res = 0;
2471
2472 // remember user has requested this cache setting
2473 fCacheUserSet = true;
2474
2475 if (fTree) {
2476 res = fTree->SetCacheSize(cacheSize);
2477 } else {
2478 // If we don't have a TTree yet only record the cache size wanted
2479 res = 0;
2480 }
2481 fCacheSize = cacheSize; // Record requested size.
2482 return res;
2483}
2484
2485////////////////////////////////////////////////////////////////////////////////
2486/// Reset the addresses of the branch.
2487
2489{
2490 TChainElement* element = (TChainElement*) fStatus->FindObject(branch->GetName());
2491 if (element) {
2492 element->SetBaddress(nullptr);
2493 }
2494 if (fTree) {
2495 fTree->ResetBranchAddress(branch);
2496 }
2497}
2498
2499////////////////////////////////////////////////////////////////////////////////
2500/// Reset the addresses of the branches.
2501
2503{
2504 TIter next(fStatus);
2505 TChainElement* element = nullptr;
2506 while ((element = (TChainElement*) next())) {
2507 element->SetBaddress(nullptr);
2508 }
2509 if (fTree) {
2511 }
2512}
2513
2514////////////////////////////////////////////////////////////////////////////////
2515/// Set branch address.
2516///
2517/// \param[in] bname is the name of a branch.
2518/// \param[in] add is the address of the branch.
2519/// \param[in] ptr
2520///
2521/// Note: See the comments in TBranchElement::SetAddress() for a more
2522/// detailed discussion of the meaning of the add parameter.
2523///
2524/// IMPORTANT REMARK:
2525///
2526/// In case TChain::SetBranchStatus is called, it must be called
2527/// BEFORE calling this function.
2528///
2529/// See TTree::CheckBranchAddressType for the semantic of the return value.
2530
2531Int_t TChain::SetBranchAddress(const char *bname, void* add, TBranch** ptr)
2532{
2533 Int_t res = kNoCheck;
2534
2535 // Check if bname is already in the status list.
2536 // If not, create a TChainElement object and set its address.
2537 TChainElement* element = (TChainElement*) fStatus->FindObject(bname);
2538 if (!element) {
2539 element = new TChainElement(bname, "");
2540 fStatus->Add(element);
2541 }
2542 element->SetBaddress(add);
2543 element->SetBranchPtr(ptr);
2544 // Also set address in current tree.
2545 // FIXME: What about the chain clones?
2546 if (fTreeNumber >= 0) {
2547 TBranch* branch = fTree->GetBranch(bname);
2548 if (ptr) {
2549 *ptr = branch;
2550 }
2551 if (branch) {
2553 if ((res & kNeedEnableDecomposedObj) && !branch->GetMakeClass()) {
2554 branch->SetMakeClass(true);
2555 }
2556 element->SetDecomposedObj(branch->GetMakeClass());
2557 element->SetCheckedType(true);
2558 if (fClones) {
2559 void* oldAdd = branch->GetAddress();
2560 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
2561 TTree* clone = (TTree*) lnk->GetObject();
2562 TBranch* cloneBr = clone->GetBranch(bname);
2563 if (cloneBr && (cloneBr->GetAddress() == oldAdd)) {
2564 // the clone's branch is still pointing to us
2565 cloneBr->SetAddress(add);
2566 if ((res & kNeedEnableDecomposedObj) && !cloneBr->GetMakeClass()) {
2567 cloneBr->SetMakeClass(true);
2568 }
2569 }
2570 }
2571 }
2572
2573 branch->SetAddress(add);
2574 } else {
2575 Error("SetBranchAddress", "unknown branch -> %s", bname);
2576 return kMissingBranch;
2577 }
2578 } else {
2579 if (ptr) {
2580 *ptr = nullptr;
2581 }
2582 }
2583 return res;
2584}
2585
2586////////////////////////////////////////////////////////////////////////////////
2587/// Check if bname is already in the status list, and if not, create a TChainElement object and set its address.
2588/// See TTree::CheckBranchAddressType for the semantic of the return value.
2589///
2590/// Note: See the comments in TBranchElement::SetAddress() for a more
2591/// detailed discussion of the meaning of the add parameter.
2592
2593Int_t TChain::SetBranchAddress(const char* bname, void* add, TClass* realClass, EDataType datatype, bool isptr)
2594{
2595 return SetBranchAddress(bname, add, nullptr, realClass, datatype, isptr);
2596}
2597
2598////////////////////////////////////////////////////////////////////////////////
2599/// Check if bname is already in the status list, and if not, create a TChainElement object and set its address.
2600/// See TTree::CheckBranchAddressType for the semantic of the return value.
2601///
2602/// Note: See the comments in TBranchElement::SetAddress() for a more
2603/// detailed discussion of the meaning of the add parameter.
2604
2605Int_t TChain::SetBranchAddress(const char* bname, void* add, TBranch** ptr, TClass* realClass, EDataType datatype, bool isptr)
2606{
2607 TChainElement* element = (TChainElement*) fStatus->FindObject(bname);
2608 if (!element) {
2609 element = new TChainElement(bname, "");
2610 fStatus->Add(element);
2611 }
2612 if (realClass) {
2613 element->SetBaddressClassName(realClass->GetName());
2614 }
2615 element->SetBaddressType((UInt_t) datatype);
2616 element->SetBaddressIsPtr(isptr);
2617 element->SetBranchPtr(ptr);
2618 return SetBranchAddress(bname, add, ptr);
2619}
2620
2621////////////////////////////////////////////////////////////////////////////////
2622/// Set branch status to Process or DoNotProcess
2623///
2624/// \param[in] bname is the name of a branch. if bname="*", apply to all branches.
2625/// \param[in] status = 1 branch will be processed,
2626/// = 0 branch will not be processed
2627/// \param[out] found
2628///
2629/// See IMPORTANT REMARKS in TTree::SetBranchStatus and TChain::SetBranchAddress
2630///
2631/// If found is not 0, the number of branch(es) found matching the regular
2632/// expression is returned in *found AND the error message 'unknown branch'
2633/// is suppressed.
2634
2635void TChain::SetBranchStatus(const char* bname, bool status, UInt_t* found)
2636{
2637 // FIXME: We never explicitly set found to zero!
2638
2639 // Check if bname is already in the status list,
2640 // if not create a TChainElement object and set its status.
2641 TChainElement* element = (TChainElement*) fStatus->FindObject(bname);
2642 if (element) {
2643 fStatus->Remove(element);
2644 } else {
2645 element = new TChainElement(bname, "");
2646 }
2647 fStatus->Add(element);
2648 element->SetStatus(status);
2649 // Also set status in current tree.
2650 if (fTreeNumber >= 0) {
2651 fTree->SetBranchStatus(bname, status, found);
2652 } else if (found) {
2653 *found = 1;
2654 }
2655}
2656
2657////////////////////////////////////////////////////////////////////////////////
2658/// Remove reference to this chain from current directory and add
2659/// reference to new directory dir. dir can be 0 in which case the chain
2660/// does not belong to any directory.
2661
2663{
2664 if (fDirectory == dir) return;
2665 if (fDirectory) fDirectory->Remove(this);
2666 fDirectory = dir;
2667 if (fDirectory) {
2668 fDirectory->Append(this);
2670 } else {
2671 fFile = nullptr;
2672 }
2673}
2674
2675////////////////////////////////////////////////////////////////////////////////
2676/// \brief Set the input entry list (processing the entries of the chain will
2677/// then be limited to the entries in the list).
2678///
2679/// \param[in] elist The entry list to be assigned to this chain.
2680/// \param[in] opt An option string. Possible values are:
2681/// - "" (default): both the file names of the chain elements and the file
2682/// names of the TEntryList sublists are expanded to full path name.
2683/// - "ne": the file names are taken as they are and not expanded
2684/// - "sync": the TChain will go through the TEntryList in lockstep with the
2685/// trees in the chain rather than performing a lookup based on
2686/// treename and filename. This is mostly useful when the TEntryList
2687/// has multiple sublists for the same tree and filename.
2688/// \throws std::runtime_error If option "sync" was chosen and either:
2689/// - \p elist doesn't have sub entry lists.
2690/// - the number of sub entry lists in \p elist is different than the
2691/// number of trees in the chain.
2692/// - any of the sub entry lists in \p elist doesn't correspond to the
2693/// tree of the chain with the same index (i.e. it doesn't share the
2694/// same tree name and file name).
2695///
2696/// This function finds correspondence between the sub-lists of the TEntryList
2697/// and the trees of the TChain.
2698
2700{
2701 if (fEntryList){
2702 //check, if the chain is the owner of the previous entry list
2703 //(it happens, if the previous entry list was created from a user-defined
2704 //TEventList in SetEventList() function)
2706 TEntryList *tmp = fEntryList;
2707 fEntryList = nullptr; // Avoid problem with RecursiveRemove.
2708 delete tmp;
2709 } else {
2710 fEntryList = nullptr;
2711 }
2712 }
2713 if (!elist){
2714 fEntryList = nullptr;
2715 fEventList = nullptr;
2716 return;
2717 }
2718 if (!elist->TestBit(kCanDelete)){
2719 //this is a direct call to SetEntryList, not via SetEventList
2720 fEventList = nullptr;
2721 }
2722 if (elist->GetN() == 0){
2723 fEntryList = elist;
2724 return;
2725 }
2726 if (fProofChain){
2727 //for processing on proof, event list and entry list can't be
2728 //set at the same time.
2729 fEventList = nullptr;
2730 fEntryList = elist;
2731 return;
2732 }
2733
2734 Int_t ne = fFiles->GetEntries();
2735 Int_t listfound=0;
2736 TString treename, filename;
2737
2738 TEntryList *templist = nullptr;
2739
2740 const auto *subentrylists = elist->GetLists();
2741 if(strcmp(opt, "sync") == 0){
2742 if(!subentrylists){
2743 std::string msg{"In 'TChain::SetEntryList': "};
2744 msg += "the input TEntryList doesn't have sub entry lists. Please make sure too add them through ";
2745 msg += "TEntryList::AddSubList";
2746 throw std::runtime_error(msg);
2747 }
2748 const auto nsubelists = subentrylists->GetEntries();
2749 if(nsubelists != ne){
2750 std::string msg{"In 'TChain::SetEntryList': "};
2751 msg += "the number of sub entry lists in the input TEntryList (";
2752 msg += std::to_string(nsubelists);
2753 msg += ") is not equal to the number of files in the chain (";
2754 msg += std::to_string(ne);
2755 msg += ")";
2756 throw std::runtime_error(msg);
2757 }
2758 }
2759
2760 for (Int_t ie = 0; ie<ne; ie++){
2761 auto chainElement = (TChainElement*)fFiles->UncheckedAt(ie);
2762 treename = chainElement->GetName();
2763 filename = chainElement->GetTitle();
2764
2765 if(strcmp(opt, "sync") == 0){
2766 // If the user asked for "sync" option, there should be a 1:1 mapping
2767 // between trees in the chain and sub entry lists in the argument elist
2768 // We have already checked that the input TEntryList has a number of
2769 // sub entry lists equal to the number of files in the chain.
2770 templist = static_cast<TEntryList*>(subentrylists->At(ie));
2771 auto elisttreename = templist->GetTreeName();
2772 auto elistfilename = templist->GetFileName();
2773
2774 if (strcmp(treename, elisttreename) != 0 || strcmp(filename, elistfilename) != 0){
2775 std::string msg{"In 'TChain::SetEntryList': "};
2776 msg += "the sub entry list at index ";
2777 msg += std::to_string(ie);
2778 msg += " doesn't correspond to treename '";
2779 msg += treename;
2780 msg += "' and filename '";
2781 msg += filename;
2782 msg += "': it has treename '";
2783 msg += elisttreename;
2784 msg += "' and filename '";
2785 msg += elistfilename;
2786 msg += "'";
2787 throw std::runtime_error(msg);
2788 }
2789
2790 }else{
2791 templist = elist->GetEntryList(treename, filename, opt);
2792 }
2793
2794 if (templist) {
2795 listfound++;
2796 templist->SetTreeNumber(ie);
2797 }
2798 }
2799
2800 if (listfound == 0){
2801 Error("SetEntryList", "No list found for the trees in this chain");
2802 fEntryList = nullptr;
2803 return;
2804 }
2805 fEntryList = elist;
2806 TList *elists = elist->GetLists();
2807 bool shift = false;
2808 TIter next(elists);
2809
2810 //check, if there are sub-lists in the entry list, that don't
2811 //correspond to any trees in the chain
2812 while((templist = (TEntryList*)next())){
2813 if (templist->GetTreeNumber() < 0){
2814 shift = true;
2815 break;
2816 }
2817 }
2818 fEntryList->SetShift(shift);
2819
2820}
2821
2822////////////////////////////////////////////////////////////////////////////////
2823/// Set the input entry list (processing the entries of the chain will then be
2824/// limited to the entries in the list). This function creates a special kind
2825/// of entry list (TEntryListFromFile object) that loads lists, corresponding
2826/// to the chain elements, one by one, so that only one list is in memory at a time.
2827///
2828/// If there is an error opening one of the files, this file is skipped and the
2829/// next file is loaded
2830///
2831/// File naming convention:
2832///
2833/// - by default, filename_elist.root is used, where filename is the
2834/// name of the chain element
2835/// - xxx$xxx.root - $ sign is replaced by the name of the chain element
2836///
2837/// If the list name is not specified (by passing filename_elist.root/listname to
2838/// the TChain::SetEntryList() function, the first object of class TEntryList
2839/// in the file is taken.
2840///
2841/// It is assumed, that there are as many list files, as there are elements in
2842/// the chain and they are in the same order
2843
2844void TChain::SetEntryListFile(const char *filename, Option_t * /*opt*/)
2845{
2846
2847 if (fEntryList){
2848 //check, if the chain is the owner of the previous entry list
2849 //(it happens, if the previous entry list was created from a user-defined
2850 //TEventList in SetEventList() function)
2852 TEntryList *tmp = fEntryList;
2853 fEntryList = nullptr; // Avoid problem with RecursiveRemove.
2854 delete tmp;
2855 } else {
2856 fEntryList = nullptr;
2857 }
2858 }
2859
2860 fEventList = nullptr;
2861
2862 TString basename(filename);
2863
2864 Int_t dotslashpos = basename.Index(".root/");
2865 TString behind_dot_root = "";
2866 if (dotslashpos>=0) {
2867 // Copy the list name specification
2868 behind_dot_root = basename(dotslashpos+6,basename.Length()-dotslashpos+6);
2869 // and remove it from basename
2870 basename.Remove(dotslashpos+5);
2871 }
2872 fEntryList = new TEntryListFromFile(basename.Data(), behind_dot_root.Data(), fNtrees);
2874 fEntryList->SetDirectory(nullptr);
2875 ((TEntryListFromFile*)fEntryList)->SetFileNames(fFiles);
2876}
2877
2878////////////////////////////////////////////////////////////////////////////////
2879/// This function transfroms the given TEventList into a TEntryList
2880///
2881/// NOTE, that this function loads all tree headers, because the entry numbers
2882/// in the TEventList are global and have to be recomputed, taking into account
2883/// the number of entries in each tree.
2884///
2885/// The new TEntryList is owned by the TChain and gets deleted when the chain
2886/// is deleted. This TEntryList is returned by GetEntryList() function, and after
2887/// GetEntryList() function is called, the TEntryList is not owned by the chain
2888/// any more and will not be deleted with it.
2889
2891{
2892 fEventList = evlist;
2893 if (fEntryList) {
2895 TEntryList *tmp = fEntryList;
2896 fEntryList = nullptr; // Avoid problem with RecursiveRemove.
2897 delete tmp;
2898 } else {
2899 fEntryList = nullptr;
2900 }
2901 }
2902
2903 if (!evlist) {
2904 fEntryList = nullptr;
2905 fEventList = nullptr;
2906 return;
2907 }
2908
2909 if(fProofChain) {
2910 //on proof, fEventList and fEntryList shouldn't be set at the same time
2911 if (fEntryList){
2912 //check, if the chain is the owner of the previous entry list
2913 //(it happens, if the previous entry list was created from a user-defined
2914 //TEventList in SetEventList() function)
2916 TEntryList *tmp = fEntryList;
2917 fEntryList = nullptr; // Avoid problem with RecursiveRemove.
2918 delete tmp;
2919 } else {
2920 fEntryList = nullptr;
2921 }
2922 }
2923 return;
2924 }
2925
2926 char enlistname[100];
2927 snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
2928 TEntryList *enlist = new TEntryList(enlistname, evlist->GetTitle());
2929 enlist->SetDirectory(nullptr);
2930
2931 Int_t nsel = evlist->GetN();
2932 Long64_t globalentry, localentry;
2933 const char *treename;
2934 const char *filename;
2936 //Load all the tree headers if the tree offsets are not known
2937 //It is assumed here, that loading the last tree will load all
2938 //previous ones
2939 printf("loading trees\n");
2940 (const_cast<TChain*>(this))->LoadTree(evlist->GetEntry(evlist->GetN()-1));
2941 }
2942 for (Int_t i=0; i<nsel; i++){
2943 globalentry = evlist->GetEntry(i);
2944 //add some protection from globalentry<0 here
2945 Int_t treenum = 0;
2946 while (globalentry>=fTreeOffset[treenum])
2947 treenum++;
2948 treenum--;
2949 localentry = globalentry - fTreeOffset[treenum];
2950 // printf("globalentry=%lld, treeoffset=%lld, localentry=%lld\n", globalentry, fTreeOffset[treenum], localentry);
2951 treename = ((TNamed*)fFiles->At(treenum))->GetName();
2952 filename = ((TNamed*)fFiles->At(treenum))->GetTitle();
2953 //printf("entering for tree %s %s\n", treename, filename);
2954 enlist->SetTree(treename, filename);
2955 enlist->Enter(localentry);
2956 }
2957 enlist->SetBit(kCanDelete, true);
2958 enlist->SetReapplyCut(evlist->GetReapplyCut());
2959 SetEntryList(enlist);
2960}
2961
2962////////////////////////////////////////////////////////////////////////////////
2963/// Change the name of this TChain.
2964
2965void TChain::SetName(const char* name)
2966{
2967 if (fGlobalRegistration) {
2968 // Should this be extended to include the call to TTree::SetName?
2969 R__WRITE_LOCKGUARD(ROOT::gCoreMutex); // Take the lock once rather than 3 times.
2970 gROOT->GetListOfCleanups()->Remove(this);
2971 gROOT->GetListOfSpecials()->Remove(this);
2972 gROOT->GetListOfDataSets()->Remove(this);
2973 }
2975 if (fGlobalRegistration) {
2976 // Should this be extended to include the call to TTree::SetName?
2977 R__WRITE_LOCKGUARD(ROOT::gCoreMutex); // Take the lock once rather than 3 times.
2978 gROOT->GetListOfCleanups()->Add(this);
2979 gROOT->GetListOfSpecials()->Add(this);
2980 gROOT->GetListOfDataSets()->Add(this);
2981 }
2982}
2983
2984////////////////////////////////////////////////////////////////////////////////
2985/// Set number of entries per packet for parallel root.
2986
2988{
2989 fPacketSize = size;
2990 TIter next(fFiles);
2991 TChainElement *element;
2992 while ((element = (TChainElement*)next())) {
2993 element->SetPacketSize(size);
2994 }
2995}
2996
2997////////////////////////////////////////////////////////////////////////////////
2998/// Enable/Disable PROOF processing on the current default Proof (gProof).
2999///
3000/// "Draw" and "Processed" commands will be handled by PROOF.
3001/// The refresh and gettreeheader are meaningful only if on == true.
3002/// If refresh is true the underlying fProofChain (chain proxy) is always
3003/// rebuilt (even if already existing).
3004/// If gettreeheader is true the header of the tree will be read from the
3005/// PROOF cluster: this is only needed for browsing and should be used with
3006/// care because it may take a long time to execute.
3007
3008void TChain::SetProof(bool on, bool refresh, bool gettreeheader)
3009{
3010 if (!on) {
3011 // Disable
3013 // Reset related bit
3015 } else {
3016 if (fProofChain && !refresh &&
3017 (!gettreeheader || (gettreeheader && fProofChain->GetTree()))) {
3018 return;
3019 }
3022
3023 // Make instance of TChainProof via the plugin manager
3025 if ((h = gROOT->GetPluginManager()->FindHandler("TChain", "proof"))) {
3026 if (h->LoadPlugin() == -1)
3027 return;
3028 if (!(fProofChain = reinterpret_cast<TChain *>(h->ExecPlugin(2, this, gettreeheader))))
3029 Error("SetProof", "creation of TProofChain failed");
3030 // Set related bits
3032 }
3033 }
3034}
3035
3036////////////////////////////////////////////////////////////////////////////////
3037/// Set chain weight.
3038///
3039/// The weight is used by TTree::Draw to automatically weight each
3040/// selected entry in the resulting histogram.
3041/// For example the equivalent of
3042/// ~~~ {.cpp}
3043/// chain.Draw("x","w")
3044/// ~~~
3045/// is
3046/// ~~~ {.cpp}
3047/// chain.SetWeight(w,"global");
3048/// chain.Draw("x");
3049/// ~~~
3050/// By default the weight used will be the weight
3051/// of each Tree in the TChain. However, one can force the individual
3052/// weights to be ignored by specifying the option "global".
3053/// In this case, the TChain global weight will be used for all Trees.
3054
3056{
3057 fWeight = w;
3058 TString opt = option;
3059 opt.ToLower();
3061 if (opt.Contains("global")) {
3063 }
3064}
3065
3066////////////////////////////////////////////////////////////////////////////////
3067/// Stream a class object.
3068
3070{
3071 if (b.IsReading()) {
3072 // Remove using the 'old' name.
3073 {
3075 gROOT->GetListOfCleanups()->Remove(this);
3076 }
3077
3078 UInt_t R__s, R__c;
3079 Version_t R__v = b.ReadVersion(&R__s, &R__c);
3080 if (R__v > 2) {
3081 b.ReadClassBuffer(TChain::Class(), this, R__v, R__s, R__c);
3082 } else {
3083 //====process old versions before automatic schema evolution
3085 b >> fTreeOffsetLen;
3086 b >> fNtrees;
3087 fFiles->Streamer(b);
3088 if (R__v > 1) {
3089 fStatus->Streamer(b);
3091 b.ReadFastArray(fTreeOffset,fTreeOffsetLen);
3092 }
3093 b.CheckByteCount(R__s, R__c, TChain::IsA());
3094 //====end of old versions
3095 }
3096 // Re-add using the new name.
3097 {
3099 gROOT->GetListOfCleanups()->Add(this);
3100 }
3101
3102 } else {
3103 b.WriteClassBuffer(TChain::Class(),this);
3104 }
3105}
3106
3107////////////////////////////////////////////////////////////////////////////////
3108/// Dummy function kept for back compatibility.
3109/// The cache is now activated automatically when processing TTrees/TChain.
3110
3111void TChain::UseCache(Int_t /* maxCacheSize */, Int_t /* pageSize */)
3112{
3113}
#define SafeDelete(p)
Definition RConfig.hxx:525
#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)
Definition TError.h:118
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:406
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:875
Int_t SetCacheSize(Long64_t cacheSize=-1) override
Set maximum size of the file cache .
Definition TChain.cxx:2463
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:779
TObjArray * GetListOfBranches() override
Return a pointer to the list of branches of the current tree.
Definition TChain.cxx:1121
void Streamer(TBuffer &) override
Stream a class object.
Definition TChain.cxx:3069
Long64_t GetEntryNumber(Long64_t entry) const override
Return entry number corresponding to entry.
Definition TChain.cxx:1017
Double_t GetWeight() const override
Return the chain weight.
Definition TChain.cxx:1237
virtual void SetAutoDelete(bool autodel=true)
Set the global branch kAutoDelete bit.
Definition TChain.cxx:2454
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:2699
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:678
void DirectoryAutoAdd(TDirectory *) override
Override the TTree::DirectoryAutoAdd behavior: we never auto add.
Definition TChain.cxx:800
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:1292
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:2238
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:2301
const char * GetAlias(const char *aliasName) const override
Returns the expanded value of the alias. Search in the friends if any.
Definition TChain.cxx:896
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:3008
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:490
void Reset(Option_t *option="") override
Resets the state of this chain.
Definition TChain.cxx:2343
void ResetAfterMerge(TFileMergeInfo *) override
Resets the state of this chain after a merge (keep the customization but forget the data).
Definition TChain.cxx:2365
Long64_t * fTreeOffset
[fTreeOffsetLen] Array of variables
Definition TChain.h:39
TBranch * FindBranch(const char *name) override
See TTree::GetReadEntry().
Definition TChain.cxx:854
void ResetBranchAddresses() override
Reset the addresses of the branches.
Definition TChain.cxx:2502
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save TChain as a C++ statements on output stream out.
Definition TChain.cxx:2382
void SetEventList(TEventList *evlist) override
This function transfroms the given TEventList into a TEntryList.
Definition TChain.cxx:2890
TObjArray * GetListOfLeaves() override
Return a pointer to the list of leaves of the current tree.
Definition TChain.cxx:1144
bool GetBranchStatus(const char *branchname) const override
See TTree::GetReadEntry().
Definition TChain.cxx:936
TBranch * GetBranch(const char *name) override
Return pointer to the branch name in the current tree.
Definition TChain.cxx:915
Int_t GetEntryWithIndex(Int_t major, Int_t minor=0) override
Return entry corresponding to major and minor number.
Definition TChain.cxx:1050
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:2439
Double_t GetMaximum(const char *columname) override
Return maximum of column with name columname.
Definition TChain.cxx:1165
void SetWeight(Double_t w=1, Option_t *option="") override
Set chain weight.
Definition TChain.cxx:3055
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:1826
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:2531
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:2261
void RemoveFriend(TTree *) override
Remove a friend from the list of friends.
Definition TChain.cxx:2320
virtual Int_t AddFileInfoList(TCollection *list, Long64_t nfiles=TTree::kMaxEntries)
Add all files referenced in the list to the chain.
Definition TChain.cxx:588
virtual void CreatePackets()
Initialize the packet descriptor string.
Definition TChain.cxx:787
void ResetBranchAddress(TBranch *) override
Reset the addresses of the branch.
Definition TChain.cxx:2488
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:2662
Double_t GetMinimum(const char *columname) override
Return minimum of column with name columname.
Definition TChain.cxx:1182
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:1903
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:2168
bool InPlaceClone(TDirectory *newdirectory, const char *options="") override
Move content to a new file. (NOT IMPLEMENTED for TChain)
Definition TChain.cxx:1255
Int_t GetNbranches() override
Return the number of branches of the current tree.
Definition TChain.cxx:1201
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:815
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:2844
Long64_t GetChainEntryNumber(Long64_t entry) const override
Return absolute entry number in the chain.
Definition TChain.cxx:964
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:2965
void ls(Option_t *option="") const override
List the chain.
Definition TChain.cxx:1870
void SetBranchStatus(const char *bname, bool status=true, UInt_t *found=nullptr) override
Set branch status to Process or DoNotProcess.
Definition TChain.cxx:2635
Long64_t LoadTree(Long64_t entry) override
Find the tree which contains entry, and set it as the current tree.
Definition TChain.cxx:1320
TClusterIterator GetClusterIterator(Long64_t firstentry) override
Return an iterator over the cluster of baskets starting at firstentry.
Definition TChain.cxx:953
void Browse(TBrowser *) override
Browse the contents of the chain.
Definition TChain.cxx:761
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:1216
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:3111
void InvalidateCurrentTree()
Set the TTree to be reloaded as soon as possible.
Definition TChain.cxx:1274
Long64_t GetEntries() const override
Return the total number of entries in the chain.
Definition TChain.cxx:974
TFile * GetFile() const
Return a pointer to the current file.
Definition TChain.cxx:1061
Int_t GetEntry(Long64_t entry=0, Int_t getall=0) override
Get entry from the file to memory.
Definition TChain.cxx:998
virtual void SetPacketSize(Int_t size=100)
Set number of entries per packet for parallel root.
Definition TChain.cxx:2987
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:1756
TLeaf * GetLeaf(const char *branchname, const char *leafname) override
Return a pointer to the leaf name in the current tree.
Definition TChain.cxx:1074
@ 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
<div class="legacybox"><h2>Legacy Code</h2> TEventList is a legacy interface: there will be no bug fi...
Definition TEventList.h:31
virtual Long64_t GetEntry(Int_t index) const
Return value of entry at index in the list.
virtual bool GetReapplyCut() const
Definition TEventList.h:57
virtual Int_t GetN() const
Definition TEventList.h:56
Class describing a generic file including meta information.
Definition TFileInfo.h:39
TUrl * GetCurrentUrl() const
Return the current url.
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:594
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:525
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:574
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:2883
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:8529
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:8882
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:9535
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:9167
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:8337
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:9743
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:9195
virtual Int_t SetCacheSize(Long64_t cachesize=-1)
Set maximum size of the file cache .
Definition TTree.cxx:8676
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:8094
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