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