Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TChainIndex.cxx
Go to the documentation of this file.
1// @(#)root/tree:$Id$
2// Author: Marek Biskup 07/06/2005
3
4/*************************************************************************
5 * Copyright (C) 1995-2004, 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 TChainIndex
13A Chain Index.
14A Chain Index with majorname and minorname.
15It uses tree indices of all the trees in the chain instead of building
16a new index.
17The index values from the first tree should be less then
18all the index values from the second tree, and so on.
19If a tree in the chain doesn't have an index the index will be created
20and kept inside this chain index.
21*/
22
23#include "TChainIndex.h"
24#include "TChain.h"
25#include "TTreeFormula.h"
26#include "TTreeIndex.h"
27#include "TFile.h"
28#include "TError.h"
29
30#include <cstring> // std::strlen
31
32////////////////////////////////////////////////////////////////////////////////
33/// \class TChainIndex::TChainIndexEntry
34/// Holds a description of indices of trees in the chain.
35
37{
38 fMinIndexValue = index->GetIndexValues()[0];
39 fMinIndexValMinor = index->GetIndexValuesMinor()[0];
40 fMaxIndexValue = index->GetIndexValues()[index->GetN() - 1];
41 fMaxIndexValMinor = index->GetIndexValuesMinor()[index->GetN() - 1];
42}
43
45{
46 std::swap(fMinIndexValue, other.fMinIndexValue);
47 std::swap(fMinIndexValMinor, other.fMinIndexValMinor);
48 std::swap(fMaxIndexValue, other.fMaxIndexValue);
49 std::swap(fMaxIndexValMinor, other.fMaxIndexValMinor);
50 std::swap(fTreeIndex, other.fTreeIndex);
51}
52
54{
55 fMinIndexValue = other.fMinIndexValue;
56 fMinIndexValMinor = other.fMinIndexValMinor;
57 fMaxIndexValue = other.fMaxIndexValue;
58 fMaxIndexValMinor = other.fMaxIndexValMinor;
59 fTreeIndex = (other.fTreeIndex ? static_cast<TVirtualIndex *>(other.fTreeIndex->Clone()) : nullptr);
60}
61
63
64////////////////////////////////////////////////////////////////////////////////
65/// Default constructor for TChainIndex
66
72
73////////////////////////////////////////////////////////////////////////////////
74/// Normal constructor for TChainIndex. See TTreeIndex::TTreeIndex for the description of the
75/// parameters.
76/// The tree must be a TChain.
77/// All the index values in the first tree of the chain must be
78/// less then any index value in the second one, and so on.
79/// If any of those requirements isn't met the object becomes a zombie.
80/// If some subtrees don't have indices the indices are created and stored inside this
81/// TChainIndex.
82/// In some cases, a warning is printed about unsorted indices in the TChain files. Note
83/// that unsorted indices lead to a significant performance degradation, not only when building the index itself,
84/// but also later on when performing the joining with other datasets. Thus, in general, it is not recommended to
85/// ignore this warning except for special cases with prior knowledge that sorting the files and/or entries is actually
86/// more expensive, or just not possible.
87
88TChainIndex::TChainIndex(const TTree *T, const char *majorname, const char *minorname, bool long64major, bool long64minor)
90{
91 fTree = nullptr;
93
94 TChain *chain = dynamic_cast<TChain*>(const_cast<TTree*>(T));
95 if (!chain) {
96 MakeZombie();
97 Error("TChainIndex", "Cannot create a TChainIndex."
98 " The Tree passed as an argument is not a TChain");
99 return;
100 }
101
102 fTree = (TTree*)T;
105 Int_t i = 0;
106
107 // Go through all the trees and check if they have indices. If not then build them.
108 for (i = 0; i < chain->GetNtrees(); i++) {
109 chain->LoadTree((chain->GetTreeOffset())[i]);
110 TVirtualIndex *index = chain->GetTree()->GetTreeIndex();
111
113 entry.fTreeIndex = nullptr;
114
115 //if an index already exists, we must check if major/minorname correspond
116 //to the major/minor names in this function call
117 if (index) {
118 if (strcmp(majorname,index->GetMajorName()) || strcmp(minorname,index->GetMinorName())) {
119 MakeZombie();
120 Error("TChainIndex","Tree in file %s has an index built with majorname=%s and minorname=%s",chain->GetTree()->GetCurrentFile()->GetName(),index->GetMajorName(),index->GetMinorName());
121 return;
122 }
123 }
124 if (!index) {
125 chain->GetTree()->BuildIndex(majorname, minorname, long64major, long64minor);
126 index = chain->GetTree()->GetTreeIndex();
127 chain->GetTree()->SetTreeIndex(nullptr);
128 entry.fTreeIndex = index;
129 }
130 if (!index || index->IsZombie() || index->GetN() == 0) {
132 MakeZombie();
133 Error("TChainIndex", "Error creating a tree index on a tree in the chain");
134 return;
135 }
136
137 TTreeIndex *ti_index = dynamic_cast<TTreeIndex*>(index);
138 if (ti_index == nullptr) {
139 Error("TChainIndex", "The underlying TTree must have a TTreeIndex but has a %s.",
140 index->IsA()->GetName());
141 return;
142 }
143
144 entry.SetMinMaxFrom(ti_index);
145 fEntries.push_back(entry);
146 }
147
148 // Check if the indices of different trees are in order. If not then return an error.
149 for (i = 0; i < Int_t(fEntries.size() - 1); i++) {
150 if( fEntries[i].GetMaxIndexValPair() > fEntries[i+1].GetMinIndexValPair() ) {
152 MakeZombie();
153 Warning("TChainIndex", "The indices in files of this chain aren't sorted.");
154 }
155 }
156}
157
158////////////////////////////////////////////////////////////////////////////////
159/// Add an index to this chain.
160/// if delaySort is false (default) check if the indices of different trees are in order.
161
163{
164 if (index) {
165 const TTreeIndex *ti_index = dynamic_cast<const TTreeIndex*>(index);
166 if (ti_index == nullptr) {
167 Error("Append", "The given index is not a TTreeIndex but a %s",
168 index->IsA()->GetName());
169 }
170
172 entry.fTreeIndex = nullptr;
173 entry.SetMinMaxFrom(ti_index);
174 fEntries.push_back(entry);
175 }
176
177 if (!delaySort) {
178 // Check if the indices of different trees are in order. If not then return an error.
179 for (Int_t i = 0; i < Int_t(fEntries.size() - 1); i++) {
180 if( fEntries[i].GetMaxIndexValPair() > fEntries[i+1].GetMinIndexValPair() ) {
182 MakeZombie();
183 Error("Append", "The indices in files of this chain aren't sorted.");
184 }
185 }
186 }
187}
188
189////////////////////////////////////////////////////////////////////////////////
190/// Delete all the indices which were built by this object.
191
193{
194 for (unsigned int i = 0; i < fEntries.size(); i++) {
195 if (fEntries[i].fTreeIndex) {
196 if (fTree->GetTree() && fTree->GetTree()->GetTreeIndex() == fEntries[i].fTreeIndex) {
197 fTree->GetTree()->SetTreeIndex(nullptr);
198 SafeDelete(fEntries[i].fTreeIndex);
199 }
200 SafeDelete(fEntries[i].fTreeIndex);
201 }
202 }
203}
204
205////////////////////////////////////////////////////////////////////////////////
206/// The destructor.
207
209{
210 if (fTree) {
212 if (fTree->GetTreeIndex() == this)
213 fTree->SetTreeIndex(nullptr);
214 }
215}
216
217////////////////////////////////////////////////////////////////////////////////
218/// Returns a TVirtualIndex for a tree which holds the entry with the specified
219/// major and minor values and the number of that tree.
220/// If the index for that tree was created by this object it's set to the tree.
221/// The tree index should be later released using ReleaseSubTreeIndex();
222
223std::pair<TVirtualIndex*, Int_t> TChainIndex::GetSubTreeIndex(Long64_t major, Long64_t minor) const
224{
225 using std::make_pair;
226 if (fEntries.empty()) {
227 Warning("GetSubTreeIndex", "No subindices in the chain. The chain is probably empty");
228 return make_pair(static_cast<TVirtualIndex*>(nullptr), 0);
229 }
230
232
233 if( indexValue < fEntries[0].GetMinIndexValPair() ) {
234 Warning("GetSubTreeIndex", "The index value is less than the smallest index values in subtrees");
235 return make_pair(static_cast<TVirtualIndex*>(nullptr), 0);
236 }
237
238 Int_t treeNo = fEntries.size() - 1;
239 for (unsigned int i = 0; i < fEntries.size() - 1; i++) {
240 if( indexValue < fEntries[i+1].GetMinIndexValPair() ) {
241 treeNo = i;
242 break;
243 }
244 }
245 // Double check we found the right range.
246 if( indexValue > fEntries[treeNo].GetMaxIndexValPair() ) {
247 return make_pair(static_cast<TVirtualIndex*>(nullptr), 0);
248 }
249 TChain* chain = dynamic_cast<TChain*> (fTree);
250 R__ASSERT(chain);
251 chain->LoadTree(chain->GetTreeOffset()[treeNo]);
252 TVirtualIndex* index = fTree->GetTree()->GetTreeIndex();
253 if (index)
254 return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
255 else {
256 index = fEntries[treeNo].fTreeIndex;
257 if (!index) {
258 Warning("GetSubTreeIndex", "The tree has no index and the chain index"
259 " doesn't store an index for that tree");
260 return make_pair(static_cast<TVirtualIndex*>(nullptr), 0);
261 }
262 else {
263 fTree->GetTree()->SetTreeIndex(index);
264 return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
265 }
266 }
267}
268
269////////////////////////////////////////////////////////////////////////////////
270/// Releases the tree index got using GetSubTreeIndex. If the index was
271/// created by this object it is removed from the current tree, so that it isn't
272/// deleted in its destructor.
273
275{
276 if (fEntries[treeNo].fTreeIndex == index) {
277 R__ASSERT(fTree->GetTree()->GetTreeIndex() == index);
278 fTree->GetTree()->SetTreeIndex(nullptr);
279 }
280}
281
282////////////////////////////////////////////////////////////////////////////////
283/// See TTreeIndex::GetEntryNumberFriend for description
284
286{
287 if (!parent) return -3;
288 GetMajorFormulaParent(parent);
289 GetMinorFormulaParent(parent);
290 if (!fMajorFormulaParent || !fMinorFormulaParent) return -1;
292 // The Tree Index in the friend has a pair majorname,minorname
293 // not available in the parent Tree T.
294 // if the friend Tree has less entries than the parent, this is an error
295 Long64_t pentry = parent->GetReadEntry();
296 if (pentry >= fTree->GetEntries()) return -2;
297 // otherwise we ignore the Tree Index and return the entry number
298 // in the parent Tree.
299 return pentry;
300 }
301
302 // majorname, minorname exist in the parent Tree
303 // we find the current values pair majorv,minorv in the parent Tree
308 // we check if this pair exist in the index.
309 // if yes, we return the corresponding entry number
310 // if not the function returns -1
312}
313
314////////////////////////////////////////////////////////////////////////////////
315/// See TTreeIndex::GetEntryNumberWithBestIndex for details.
316
318{
319 std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
320 if (!indexAndNumber.first) {
321 // Error("GetEntryNumberWithBestIndex","no index found");
322 return -1;
323 }
324 else {
325 Long64_t rv = indexAndNumber.first->GetEntryNumberWithBestIndex(major, minor);
327 TChain* chain = dynamic_cast<TChain*> (fTree);
328 R__ASSERT(chain);
329 return rv + chain->GetTreeOffset()[indexAndNumber.second];
330 }
331}
332
333////////////////////////////////////////////////////////////////////////////////
334/// Returns the entry number with given index values.
335/// See TTreeIndex::GetEntryNumberWithIndex for details.
336
338{
339 std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
340 if (!indexAndNumber.first) {
341 // Error("GetEntryNumberWithIndex","no index found");
342 return -1;
343 }
344 else {
345 Long64_t rv = indexAndNumber.first->GetEntryNumberWithIndex(major, minor);
347 TChain* chain = dynamic_cast<TChain*> (fTree);
348 R__ASSERT(chain);
349 if (rv >= 0) {
350 return rv + chain->GetTreeOffset()[indexAndNumber.second];
351 } else {
352 return rv;
353 }
354 }
355}
356
357////////////////////////////////////////////////////////////////////////////////
358/// Return a pointer to the TreeFormula corresponding to the majorname in parent tree T.
359
373
374////////////////////////////////////////////////////////////////////////////////
375/// Return a pointer to the TreeFormula corresponding to the minorname in parent tree T.
376
378{
379 if (!fMinorFormulaParent) {
380 // Prevent TTreeFormula from finding any of the branches in our TTree even if it
381 // is a friend of the parent TTree.
383 fMinorFormulaParent = new TTreeFormula("MinorP",fMinorName.Data(),const_cast<TTree*>(parent));
385 }
386 if (fMinorFormulaParent->GetTree() != parent) {
387 fMinorFormulaParent->SetTree(const_cast<TTree*>(parent));
389 }
390
391 return fMinorFormulaParent;
392}
393
394////////////////////////////////////////////////////////////////////////////////
395/// Return true if index can be applied to the TTree
396
398{
399 auto *majorFormula = GetMajorFormulaParent(parent);
400 auto *minorFormula = GetMinorFormulaParent(parent);
401 if ((majorFormula == nullptr || majorFormula->GetNdim() == 0) ||
402 (minorFormula == nullptr || minorFormula->GetNdim() == 0))
403 return false;
404 return true;
405}
406
407////////////////////////////////////////////////////////////////////////////////
408/// Updates the parent formulae.
409/// Called by TChain::LoadTree when the parent chain changes it's tree.
410
412{
414 // Prevent TTreeFormula from finding any of the branches in our TTree even if it
415 // is a friend of the parent TTree.
417 if (parent) fMajorFormulaParent->SetTree((TTree*)parent);
419 }
421 if (parent) fMinorFormulaParent->SetTree((TTree*)parent);
423 }
424}
425
426////////////////////////////////////////////////////////////////////////////////
427/// See TTreeIndex::SetTree.
428
430{
431 R__ASSERT(fTree == nullptr || fTree == T || T==nullptr);
432 fTree = T;
433}
434
435////////////////////////////////////////////////////////////////////////////////
436/// \brief Create a deep copy of the TChainIndex
437/// \param[in] newname A new name for the index
438///
439/// The new index is allocated on the heap without being managed. Also, it is
440/// not attached to any tree. It is the responsibility of the caller to manage
441/// its lifetime and attach it to a tree if necessary.
443{
444 auto index = new TChainIndex();
445 index->SetName(newname && std::strlen(newname) ? newname : GetName());
446 index->SetTitle(GetTitle());
447
448 // Note that the TTreeFormula * data members are not cloned since they would
449 // need the attached tree data member to function properly.
450 index->fMajorName = fMajorName;
451 index->fMinorName = fMinorName;
452
453 index->fEntries = fEntries;
454
455 return index;
456}
#define SafeDelete(p)
Definition RConfig.hxx:533
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:83
#define ClassImp(name)
Definition Rtypes.h:376
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
virtual Int_t GetNdim() const
Definition TFormula.h:238
Holds a description of indices of trees in the chain.
Definition TChainIndex.h:43
std::pair< Long64_t, Long64_t > IndexValPair_t
Definition TChainIndex.h:56
void Swap(TChainIndexEntry &other)
void SetMinMaxFrom(const TTreeIndex *index)
A Chain Index.
Definition TChainIndex.h:40
std::vector< TChainIndexEntry > fEntries
Pointer to minor TreeFormula in Parent tree (if any)
Definition TChainIndex.h:75
TTreeFormula * fMinorFormulaParent
Pointer to major TreeFormula in Parent tree (if any)
Definition TChainIndex.h:74
~TChainIndex() override
The destructor.
TString fMinorName
Definition TChainIndex.h:72
bool IsValidFor(const TTree *parent) override
Return true if index can be applied to the TTree.
TObject * Clone(const char *newname="") const override
Create a deep copy of the TChainIndex.
void Append(const TVirtualIndex *, bool delaySort=false) override
Add an index to this chain.
std::pair< TVirtualIndex *, Int_t > GetSubTreeIndex(Long64_t major, Long64_t minor) const
Returns a TVirtualIndex for a tree which holds the entry with the specified major and minor values an...
Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor) const override
Returns the entry number with given index values.
void ReleaseSubTreeIndex(TVirtualIndex *index, Int_t treeNo) const
Releases the tree index got using GetSubTreeIndex.
Long64_t GetEntryNumberWithBestIndex(Long64_t major, Long64_t minor) const override
See TTreeIndex::GetEntryNumberWithBestIndex for details.
void UpdateFormulaLeaves(const TTree *parent) override
Updates the parent formulae.
TChainIndex()
Default constructor for TChainIndex.
void DeleteIndices()
Delete all the indices which were built by this object.
TString fMajorName
Definition TChainIndex.h:71
TTreeFormula * fMajorFormulaParent
Definition TChainIndex.h:73
Long64_t GetEntryNumberFriend(const TTree *parent) override
See TTreeIndex::GetEntryNumberFriend for description.
TTreeFormula * GetMajorFormulaParent(const TTree *parent)
Return a pointer to the TreeFormula corresponding to the majorname in parent tree T.
void SetTree(TTree *T) override
See TTreeIndex::SetTree.
TTreeFormula * GetMinorFormulaParent(const TTree *parent)
Return a pointer to the TreeFormula corresponding to the minorname in parent tree T.
A chain is a collection of files containing TTree objects.
Definition TChain.h:33
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
Mother of all ROOT objects.
Definition TObject.h:41
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1058
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1072
void MakeZombie()
Definition TObject.h:53
const char * Data() const
Definition TString.h:384
Used to pass a selection expression to the Tree drawing routine.
virtual void SetTree(TTree *tree)
T EvalInstance(Int_t i=0, const char *stringStack[]=nullptr)
Evaluate this treeformula.
void SetQuickLoad(bool quick)
virtual void UpdateFormulaLeaves()
This function is called TTreePlayer::UpdateFormulaLeaves, itself called by TChain::LoadTree when a ne...
virtual TTree * GetTree() const
A Tree Index with majorname and minorname.
Definition TTreeIndex.h:29
Helper class to prevent infinite recursion in the usage of TTree Friends.
Definition TTree.h:221
A TTree represents a columnar dataset.
Definition TTree.h:89
virtual Long64_t GetEntryNumberWithIndex(Long64_t major, Long64_t minor=0) const
Return entry number corresponding to major and minor number.
Definition TTree.cxx:5991
virtual TVirtualIndex * GetTreeIndex() const
Definition TTree.h:595
virtual Long64_t GetEntries() const
Definition TTree.h:500
virtual Long64_t GetReadEntry() const
Definition TTree.h:586
virtual TTree * GetTree() const
Definition TTree.h:594
@ kFindBranch
Definition TTree.h:245
@ kFindLeaf
Definition TTree.h:246
@ kGetBranch
Definition TTree.h:248
@ kGetLeaf
Definition TTree.h:253
virtual void SetTreeIndex(TVirtualIndex *index)
The current TreeIndex is replaced by the new index.
Definition TTree.cxx:9565
Abstract interface for Tree Index.