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];
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
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;
102 fMajorName = majorname;
103 fMinorName = minorname;
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
111 TChainIndexEntry entry;
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
161void TChainIndex::Append(const TVirtualIndex *index, bool delaySort )
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
170 TChainIndexEntry entry;
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
230 const TChainIndexEntry::IndexValPair_t indexValue(major, minor);
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;
290 if (!fMajorFormulaParent->GetNdim() || !fMinorFormulaParent->GetNdim()) {
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
303 Double_t majord = fMajorFormulaParent->EvalInstance();
304 Double_t minord = fMinorFormulaParent->EvalInstance();
305 Long64_t majorv = (Long64_t)majord;
306 Long64_t minorv = (Long64_t)minord;
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
310 return fTree->GetEntryNumberWithIndex(majorv,minorv);
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);
325 ReleaseSubTreeIndex(indexAndNumber.first, indexAndNumber.second);
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);
345 ReleaseSubTreeIndex(indexAndNumber.first, indexAndNumber.second);
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
360{
361 if (!fMajorFormulaParent) {
363 fMajorFormulaParent = new TTreeFormula("MajorP",fMajorName.Data(),const_cast<TTree*>(parent));
364 fMajorFormulaParent->SetQuickLoad(true);
365 }
366 if (fMajorFormulaParent->GetTree() != parent) {
367 fMajorFormulaParent->SetTree(const_cast<TTree*>(parent));
368 fMajorFormulaParent->UpdateFormulaLeaves();
369 }
370 return fMajorFormulaParent;
371}
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));
383 fMinorFormulaParent->SetQuickLoad(true);
384 }
385 if (fMinorFormulaParent->GetTree() != parent) {
386 fMinorFormulaParent->SetTree(const_cast<TTree*>(parent));
387 fMinorFormulaParent->UpdateFormulaLeaves();
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);
417 fMajorFormulaParent->UpdateFormulaLeaves();
418 }
420 if (parent) fMinorFormulaParent->SetTree((TTree*)parent);
421 fMinorFormulaParent->UpdateFormulaLeaves();
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.
441TObject *TChainIndex::Clone(const char *newname) const
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:525
int Int_t
Signed integer 4 bytes (int).
Definition RtypesCore.h:59
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:83
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
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
Definition TChainIndex.h:75
TTreeFormula * fMinorFormulaParent
! Pointer to minor 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
! Pointer to major TreeFormula in Parent tree (if any)
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
TObject * Clone(const char *newname="") const override
Make a clone of an object using the Streamer facility.
Definition TNamed.cxx:73
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
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1084
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1098
void MakeZombie()
Definition TObject.h:55
TObject()
TObject constructor.
Definition TObject.h:259
Bool_t IsZombie() const
Definition TObject.h:161
Used to pass a selection expression to the Tree drawing routine.
A Tree Index with majorname and minorname.
Definition TTreeIndex.h:29
virtual Long64_t * GetIndexValues() const
Definition TTreeIndex.h:60
virtual Long64_t * GetIndexValuesMinor() const
Long64_t GetN() const override
Definition TTreeIndex.h:64
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 GetReadEntry() 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 const char * GetMajorName() const =0
TVirtualIndex()
Default constructor for TVirtualIndex.
virtual const char * GetMinorName() const =0
virtual Long64_t GetN() const =0
TClass * IsA() const override
TTree * fTree
! pointer to Tree