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
62
63////////////////////////////////////////////////////////////////////////////////
64/// Default constructor for TChainIndex
65
71
72////////////////////////////////////////////////////////////////////////////////
73/// Normal constructor for TChainIndex. See TTreeIndex::TTreeIndex for the description of the
74/// parameters.
75/// The tree must be a TChain.
76/// All the index values in the first tree of the chain must be
77/// less then any index value in the second one, and so on.
78/// If any of those requirements isn't met the object becomes a zombie.
79/// If some subtrees don't have indices the indices are created and stored inside this
80/// TChainIndex.
81/// In some cases, a warning is printed about unsorted indices in the TChain files. Note
82/// that unsorted indices lead to a significant performance degradation, not only when building the index itself,
83/// but also later on when performing the joining with other datasets. Thus, in general, it is not recommended to
84/// ignore this warning except for special cases with prior knowledge that sorting the files and/or entries is actually
85/// more expensive, or just not possible.
86
87TChainIndex::TChainIndex(const TTree *T, const char *majorname, const char *minorname, bool long64major, bool long64minor)
89{
90 fTree = nullptr;
92
93 TChain *chain = dynamic_cast<TChain*>(const_cast<TTree*>(T));
94 if (!chain) {
95 MakeZombie();
96 Error("TChainIndex", "Cannot create a TChainIndex."
97 " The Tree passed as an argument is not a TChain");
98 return;
99 }
100
101 fTree = (TTree*)T;
104 Int_t i = 0;
105
106 // Go through all the trees and check if they have indices. If not then build them.
107 for (i = 0; i < chain->GetNtrees(); i++) {
108 chain->LoadTree((chain->GetTreeOffset())[i]);
109 TVirtualIndex *index = chain->GetTree()->GetTreeIndex();
110
112 entry.fTreeIndex = nullptr;
113
114 //if an index already exists, we must check if major/minorname correspond
115 //to the major/minor names in this function call
116 if (index) {
117 if (strcmp(majorname,index->GetMajorName()) || strcmp(minorname,index->GetMinorName())) {
118 MakeZombie();
119 Error("TChainIndex","Tree in file %s has an index built with majorname=%s and minorname=%s",chain->GetTree()->GetCurrentFile()->GetName(),index->GetMajorName(),index->GetMinorName());
120 return;
121 }
122 }
123 if (!index) {
124 chain->GetTree()->BuildIndex(majorname, minorname, long64major, long64minor);
125 index = chain->GetTree()->GetTreeIndex();
126 chain->GetTree()->SetTreeIndex(nullptr);
127 entry.fTreeIndex = index;
128 }
129 if (!index || index->IsZombie() || index->GetN() == 0) {
131 MakeZombie();
132 Error("TChainIndex", "Error creating a tree index on a tree in the chain");
133 return;
134 }
135
136 TTreeIndex *ti_index = dynamic_cast<TTreeIndex*>(index);
137 if (ti_index == nullptr) {
138 Error("TChainIndex", "The underlying TTree must have a TTreeIndex but has a %s.",
139 index->IsA()->GetName());
140 return;
141 }
142
143 entry.SetMinMaxFrom(ti_index);
144 fEntries.push_back(entry);
145 }
146
147 // Check if the indices of different trees are in order. If not then return an error.
148 for (i = 0; i < Int_t(fEntries.size() - 1); i++) {
149 if( fEntries[i].GetMaxIndexValPair() > fEntries[i+1].GetMinIndexValPair() ) {
151 MakeZombie();
152 Warning("TChainIndex", "The indices in files of this chain aren't sorted.");
153 }
154 }
155}
156
157////////////////////////////////////////////////////////////////////////////////
158/// Add an index to this chain.
159/// if delaySort is false (default) check if the indices of different trees are in order.
160
162{
163 if (index) {
164 const TTreeIndex *ti_index = dynamic_cast<const TTreeIndex*>(index);
165 if (ti_index == nullptr) {
166 Error("Append", "The given index is not a TTreeIndex but a %s",
167 index->IsA()->GetName());
168 }
169
171 entry.fTreeIndex = nullptr;
172 entry.SetMinMaxFrom(ti_index);
173 fEntries.push_back(entry);
174 }
175
176 if (!delaySort) {
177 // Check if the indices of different trees are in order. If not then return an error.
178 for (Int_t i = 0; i < Int_t(fEntries.size() - 1); i++) {
179 if( fEntries[i].GetMaxIndexValPair() > fEntries[i+1].GetMinIndexValPair() ) {
181 MakeZombie();
182 Error("Append", "The indices in files of this chain aren't sorted.");
183 }
184 }
185 }
186}
187
188////////////////////////////////////////////////////////////////////////////////
189/// Delete all the indices which were built by this object.
190
192{
193 for (unsigned int i = 0; i < fEntries.size(); i++) {
194 if (fEntries[i].fTreeIndex) {
195 if (fTree->GetTree() && fTree->GetTree()->GetTreeIndex() == fEntries[i].fTreeIndex) {
196 fTree->GetTree()->SetTreeIndex(nullptr);
197 SafeDelete(fEntries[i].fTreeIndex);
198 }
199 SafeDelete(fEntries[i].fTreeIndex);
200 }
201 }
202}
203
204////////////////////////////////////////////////////////////////////////////////
205/// The destructor.
206
208{
209 if (fTree) {
211 if (fTree->GetTreeIndex() == this)
212 fTree->SetTreeIndex(nullptr);
213 }
214}
215
216////////////////////////////////////////////////////////////////////////////////
217/// Returns a TVirtualIndex for a tree which holds the entry with the specified
218/// major and minor values and the number of that tree.
219/// If the index for that tree was created by this object it's set to the tree.
220/// The tree index should be later released using ReleaseSubTreeIndex();
221
222std::pair<TVirtualIndex*, Int_t> TChainIndex::GetSubTreeIndex(Long64_t major, Long64_t minor) const
223{
224 using std::make_pair;
225 if (fEntries.empty()) {
226 Warning("GetSubTreeIndex", "No subindices in the chain. The chain is probably empty");
227 return make_pair(static_cast<TVirtualIndex*>(nullptr), 0);
228 }
229
231
232 if( indexValue < fEntries[0].GetMinIndexValPair() ) {
233 Warning("GetSubTreeIndex", "The index value is less than the smallest index values in subtrees");
234 return make_pair(static_cast<TVirtualIndex*>(nullptr), 0);
235 }
236
237 Int_t treeNo = fEntries.size() - 1;
238 for (unsigned int i = 0; i < fEntries.size() - 1; i++) {
239 if( indexValue < fEntries[i+1].GetMinIndexValPair() ) {
240 treeNo = i;
241 break;
242 }
243 }
244 // Double check we found the right range.
245 if( indexValue > fEntries[treeNo].GetMaxIndexValPair() ) {
246 return make_pair(static_cast<TVirtualIndex*>(nullptr), 0);
247 }
248 TChain* chain = dynamic_cast<TChain*> (fTree);
249 R__ASSERT(chain);
250 chain->LoadTree(chain->GetTreeOffset()[treeNo]);
251 TVirtualIndex* index = fTree->GetTree()->GetTreeIndex();
252 if (index)
253 return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
254 else {
255 index = fEntries[treeNo].fTreeIndex;
256 if (!index) {
257 Warning("GetSubTreeIndex", "The tree has no index and the chain index"
258 " doesn't store an index for that tree");
259 return make_pair(static_cast<TVirtualIndex*>(nullptr), 0);
260 }
261 else {
262 fTree->GetTree()->SetTreeIndex(index);
263 return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
264 }
265 }
266}
267
268////////////////////////////////////////////////////////////////////////////////
269/// Releases the tree index got using GetSubTreeIndex. If the index was
270/// created by this object it is removed from the current tree, so that it isn't
271/// deleted in its destructor.
272
274{
275 if (fEntries[treeNo].fTreeIndex == index) {
276 R__ASSERT(fTree->GetTree()->GetTreeIndex() == index);
277 fTree->GetTree()->SetTreeIndex(nullptr);
278 }
279}
280
281////////////////////////////////////////////////////////////////////////////////
282/// See TTreeIndex::GetEntryNumberFriend for description
283
285{
286 if (!parent) return -3;
287 GetMajorFormulaParent(parent);
288 GetMinorFormulaParent(parent);
289 if (!fMajorFormulaParent || !fMinorFormulaParent) return -1;
291 // The Tree Index in the friend has a pair majorname,minorname
292 // not available in the parent Tree T.
293 // if the friend Tree has less entries than the parent, this is an error
294 Long64_t pentry = parent->GetReadEntry();
295 if (pentry >= fTree->GetEntries()) return -2;
296 // otherwise we ignore the Tree Index and return the entry number
297 // in the parent Tree.
298 return pentry;
299 }
300
301 // majorname, minorname exist in the parent Tree
302 // we find the current values pair majorv,minorv in the parent Tree
307 // we check if this pair exist in the index.
308 // if yes, we return the corresponding entry number
309 // if not the function returns -1
311}
312
313////////////////////////////////////////////////////////////////////////////////
314/// See TTreeIndex::GetEntryNumberWithBestIndex for details.
315
317{
318 std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
319 if (!indexAndNumber.first) {
320 // Error("GetEntryNumberWithBestIndex","no index found");
321 return -1;
322 }
323 else {
324 Long64_t rv = indexAndNumber.first->GetEntryNumberWithBestIndex(major, minor);
326 TChain* chain = dynamic_cast<TChain*> (fTree);
327 R__ASSERT(chain);
328 return rv + chain->GetTreeOffset()[indexAndNumber.second];
329 }
330}
331
332////////////////////////////////////////////////////////////////////////////////
333/// Returns the entry number with given index values.
334/// See TTreeIndex::GetEntryNumberWithIndex for details.
335
337{
338 std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
339 if (!indexAndNumber.first) {
340 // Error("GetEntryNumberWithIndex","no index found");
341 return -1;
342 }
343 else {
344 Long64_t rv = indexAndNumber.first->GetEntryNumberWithIndex(major, minor);
346 TChain* chain = dynamic_cast<TChain*> (fTree);
347 R__ASSERT(chain);
348 if (rv >= 0) {
349 return rv + chain->GetTreeOffset()[indexAndNumber.second];
350 } else {
351 return rv;
352 }
353 }
354}
355
356////////////////////////////////////////////////////////////////////////////////
357/// Return a pointer to the TreeFormula corresponding to the majorname in parent tree T.
358
372
373////////////////////////////////////////////////////////////////////////////////
374/// Return a pointer to the TreeFormula corresponding to the minorname in parent tree T.
375
377{
378 if (!fMinorFormulaParent) {
379 // Prevent TTreeFormula from finding any of the branches in our TTree even if it
380 // is a friend of the parent TTree.
382 fMinorFormulaParent = new TTreeFormula("MinorP",fMinorName.Data(),const_cast<TTree*>(parent));
384 }
385 if (fMinorFormulaParent->GetTree() != parent) {
386 fMinorFormulaParent->SetTree(const_cast<TTree*>(parent));
388 }
389
390 return fMinorFormulaParent;
391}
392
393////////////////////////////////////////////////////////////////////////////////
394/// Return true if index can be applied to the TTree
395
397{
398 auto *majorFormula = GetMajorFormulaParent(parent);
399 auto *minorFormula = GetMinorFormulaParent(parent);
400 if ((majorFormula == nullptr || majorFormula->GetNdim() == 0) ||
401 (minorFormula == nullptr || minorFormula->GetNdim() == 0))
402 return false;
403 return true;
404}
405
406////////////////////////////////////////////////////////////////////////////////
407/// Updates the parent formulae.
408/// Called by TChain::LoadTree when the parent chain changes it's tree.
409
411{
413 // Prevent TTreeFormula from finding any of the branches in our TTree even if it
414 // is a friend of the parent TTree.
416 if (parent) fMajorFormulaParent->SetTree((TTree*)parent);
418 }
420 if (parent) fMinorFormulaParent->SetTree((TTree*)parent);
422 }
423}
424
425////////////////////////////////////////////////////////////////////////////////
426/// See TTreeIndex::SetTree.
427
429{
430 R__ASSERT(fTree == nullptr || fTree == T || T==nullptr);
431 fTree = T;
432}
433
434////////////////////////////////////////////////////////////////////////////////
435/// \brief Create a deep copy of the TChainIndex
436/// \param[in] newname A new name for the index
437///
438/// The new index is allocated on the heap without being managed. Also, it is
439/// not attached to any tree. It is the responsibility of the caller to manage
440/// its lifetime and attach it to a tree if necessary.
442{
443 auto index = new TChainIndex();
444 index->SetName(newname && std::strlen(newname) ? newname : GetName());
445 index->SetTitle(GetTitle());
446
447 // Note that the TTreeFormula * data members are not cloned since they would
448 // need the attached tree data member to function properly.
449 index->fMajorName = fMajorName;
450 index->fMinorName = fMinorName;
451
452 index->fEntries = fEntries;
453
454 return index;
455}
#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
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)
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:1057
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
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:5990
virtual TVirtualIndex * GetTreeIndex() const
Definition TTree.h:597
virtual Long64_t GetEntries() const
Definition TTree.h:502
virtual Long64_t GetReadEntry() const
Definition TTree.h:588
virtual TTree * GetTree() const
Definition TTree.h:596
@ 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:9564
Abstract interface for Tree Index.