TChainIndex.cxx

Go to the documentation of this file.
00001 // @(#)root/tree:$Id: TChainIndex.cxx 35344 2010-09-16 21:34:21Z pcanal $
00002 // Author: Marek Biskup   07/06/2005
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //
00014 // A Chain Index
00015 //
00016 //////////////////////////////////////////////////////////////////////////
00017 
00018 #include "TChainIndex.h"
00019 #include "TChain.h"
00020 #include "TTreeFormula.h"
00021 #include "TTreeIndex.h"
00022 #include "TFile.h"
00023 #include "TError.h"
00024 
00025 ClassImp(TChainIndex)
00026 
00027 //______________________________________________________________________________
00028 TChainIndex::TChainIndex(): TVirtualIndex()
00029 {
00030 // Default constructor for TChainIndex
00031 
00032    fTree = 0;
00033    fMajorFormulaParent = fMinorFormulaParent = 0;
00034 }
00035 
00036 //______________________________________________________________________________
00037 TChainIndex::TChainIndex(const TTree *T, const char *majorname, const char *minorname)
00038            : TVirtualIndex()
00039 {
00040    // Normal constructor for TChainIndex. See TTreeIndex::TTreeIndex for the description of the
00041    // parameters.
00042    // The tree must be a TChain.
00043    // All the index values in the first tree of the chain must be
00044    // less then any index value in the second one, and so on.
00045    // If any of those requirements isn't met the object becomes a zombie.
00046    // If some subtrees don't have indices the indices are created and stored inside this
00047    // TChainIndex.
00048 
00049    fTree = 0;
00050    fMajorFormulaParent = fMinorFormulaParent = 0;
00051 
00052    TChain *chain = dynamic_cast<TChain*>(const_cast<TTree*>(T));
00053    if (!chain) {
00054       MakeZombie();
00055       Error("TChainIndex", "Cannot create a TChainIndex."
00056             " The Tree passed as an argument is not a TChain");
00057       return;
00058    }
00059 
00060    fTree               = (TTree*)T;
00061    fMajorName          = majorname;
00062    fMinorName          = minorname;
00063    Int_t i = 0;
00064 
00065    // Go through all the trees and check if they have indeces. If not then build them.
00066    for (i = 0; i < chain->GetNtrees(); i++) {
00067       chain->LoadTree((chain->GetTreeOffset())[i]);
00068       TVirtualIndex *index = chain->GetTree()->GetTreeIndex();
00069 
00070       TChainIndexEntry entry;
00071       entry.fTreeIndex = 0;
00072 
00073       //if an index already exists, we must check if major/minorname correspond
00074       //to the major/minor names in this function call
00075       if (index) {
00076          if (strcmp(majorname,index->GetMajorName()) || strcmp(minorname,index->GetMinorName())) {
00077             MakeZombie();
00078             Error("TChainIndex","Tree in file %s has an index built with majorname=%s and minorname=%s",chain->GetTree()->GetCurrentFile()->GetName(),index->GetMajorName(),index->GetMinorName());
00079             return;
00080          }
00081       }
00082       if (!index) {
00083          chain->GetTree()->BuildIndex(majorname, minorname);
00084          index = chain->GetTree()->GetTreeIndex();
00085          chain->GetTree()->SetTreeIndex(0);
00086          entry.fTreeIndex = index;
00087       }
00088       if (!index || index->IsZombie() || index->GetN() == 0) {
00089          DeleteIndices();
00090          MakeZombie();
00091          Error("TChainIndex", "Error creating a tree index on a tree in the chain");
00092          return;
00093       }
00094 
00095       TTreeIndex *ti_index = dynamic_cast<TTreeIndex*>(index);
00096       if (ti_index == 0) {
00097          Error("TChainIndex", "The underlying TTree must have a TTreeIndex but has a %s.",
00098                index->IsA()->GetName());
00099          return;
00100       }
00101 
00102       entry.fMinIndexValue = ti_index->GetIndexValues()[0];
00103       entry.fMaxIndexValue = ti_index->GetIndexValues()[index->GetN() - 1];
00104       fEntries.push_back(entry);
00105    }
00106 
00107    // Check if the indices of different trees are in order. If not then return an error.
00108    for (i = 0; i < Int_t(fEntries.size() - 1); i++) {
00109       if (fEntries[i].fMaxIndexValue > fEntries[i+1].fMinIndexValue) {
00110          DeleteIndices();
00111          MakeZombie();
00112          Error("TChainIndex", "The indices in files of this chain aren't sorted.");
00113       }
00114    }
00115 
00116 }
00117 
00118 //______________________________________________________________________________
00119 void TChainIndex::Append(const TVirtualIndex *index, Bool_t delaySort )
00120 {
00121    // add an index to this chain
00122    // if delaySort is kFALSE (default) check if the indices of different trees are in order.
00123    if (index) {
00124       const TTreeIndex *ti_index = dynamic_cast<const TTreeIndex*>(index);
00125       if (ti_index == 0) {
00126          Error("Append", "The given index is not a TTreeIndex but a %s",
00127                index->IsA()->GetName());
00128       }
00129       
00130       TChainIndexEntry entry;
00131       entry.fTreeIndex = 0;
00132       entry.fMinIndexValue = ti_index->GetIndexValues()[0];
00133       entry.fMaxIndexValue = ti_index->GetIndexValues()[index->GetN() - 1];
00134       fEntries.push_back(entry);
00135    }
00136    
00137    if (!delaySort) {
00138       // Check if the indices of different trees are in order. If not then return an error.
00139       for (Int_t i = 0; i < Int_t(fEntries.size() - 1); i++) {
00140          if (fEntries[i].fMaxIndexValue > fEntries[i+1].fMinIndexValue) {
00141             DeleteIndices();
00142             MakeZombie();
00143             Error("Append", "The indices in files of this chain aren't sorted.");
00144          }
00145       }
00146    }
00147 }
00148 
00149 //______________________________________________________________________________
00150 void TChainIndex::DeleteIndices()
00151 {
00152    // Delete all the indices which were built by this object
00153    for (unsigned int i = 0; i < fEntries.size(); i++) {
00154       if (fEntries[i].fTreeIndex) {
00155          if (fTree->GetTree() && fTree->GetTree()->GetTreeIndex() == fEntries[i].fTreeIndex) {
00156             fTree->GetTree()->SetTreeIndex(0);
00157             SafeDelete(fEntries[i].fTreeIndex);
00158          }
00159          SafeDelete(fEntries[i].fTreeIndex);
00160       }
00161    }
00162 }
00163 
00164 //______________________________________________________________________________
00165 TChainIndex::~TChainIndex()
00166 {
00167    // The destructor.
00168    DeleteIndices();
00169    if (fTree && fTree->GetTreeIndex() == this)
00170       fTree->SetTreeIndex(0);
00171 }
00172 
00173 //______________________________________________________________________________
00174 std::pair<TVirtualIndex*, Int_t> TChainIndex::GetSubTreeIndex(Int_t major, Int_t minor) const
00175 {
00176    // returns a TVirtualIndex for a tree which holds the entry with the specified
00177    // major and minor values and the number of that tree.
00178    // If the index for that tree was created by this object it's set to the tree.
00179    // The tree index should be later released using ReleaseSubTreeIndex();
00180 
00181    using namespace std;
00182    if (fEntries.size() == 0) {
00183       Warning("GetSubTreeIndex", "No subindices in the chain. The chain is probably empty");
00184       return make_pair(static_cast<TVirtualIndex*>(0), 0);
00185    }
00186 
00187    Long64_t indexValue = (Long64_t(major) << 31) + minor;
00188 
00189    if (indexValue < fEntries[0].fMinIndexValue) {
00190       Warning("GetSubTreeIndex", "The index value is less than the smallest index values in subtrees");
00191       return make_pair(static_cast<TVirtualIndex*>(0), 0);
00192    }
00193 
00194    Int_t treeNo = fEntries.size() - 1;
00195    for (unsigned int i = 0; i < fEntries.size() - 1; i++) {
00196       if (indexValue < fEntries[i+1].fMinIndexValue) {
00197          treeNo = i;
00198          break;
00199       }
00200    }
00201    TChain* chain = dynamic_cast<TChain*> (fTree);
00202    R__ASSERT(chain);
00203    chain->LoadTree(chain->GetTreeOffset()[treeNo]);
00204    TVirtualIndex* index =  fTree->GetTree()->GetTreeIndex();
00205    if (index)
00206       return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
00207    else {
00208       index = fEntries[treeNo].fTreeIndex;
00209       if (!index) {
00210          Warning("GetSubTreeIndex", "The tree has no index and the chain index"
00211                   " doesn't store an index for that tree");
00212          return make_pair(static_cast<TVirtualIndex*>(0), 0);
00213       }
00214       else {
00215          fTree->GetTree()->SetTreeIndex(index);
00216          return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
00217       }
00218    }
00219 }
00220 
00221 //______________________________________________________________________________
00222 void TChainIndex::ReleaseSubTreeIndex(TVirtualIndex* index, int treeNo) const
00223 {
00224    // Releases the tree index got using GetSubTreeIndex. If the index was
00225    // created by this object it is removed from the current tree, so that it isn't
00226    // deleted in its destructor.
00227 
00228    if (fEntries[treeNo].fTreeIndex == index) {
00229       R__ASSERT(fTree->GetTree()->GetTreeIndex() == index);
00230       fTree->GetTree()->SetTreeIndex(0);
00231    }
00232 }
00233 
00234 //______________________________________________________________________________
00235 Int_t TChainIndex::GetEntryNumberFriend(const TTree *T)
00236 {
00237    // see TTreeIndex::GetEntryNumberFriend for description
00238 
00239    if (!T) return -3;
00240    GetMajorFormulaParent(T);
00241    GetMinorFormulaParent(T);
00242    if (!fMajorFormulaParent || !fMinorFormulaParent) return -1;
00243    if (!fMajorFormulaParent->GetNdim() || !fMinorFormulaParent->GetNdim()) {
00244       // The Tree Index in the friend has a pair majorname,minorname
00245       // not available in the parent Tree T.
00246       // if the friend Tree has less entries than the parent, this is an error
00247       Int_t pentry = T->GetReadEntry();
00248       if (pentry >= (Int_t)fTree->GetEntries()) return -2;
00249       // otherwise we ignore the Tree Index and return the entry number
00250       // in the parent Tree.
00251       return pentry;
00252    }
00253 
00254    // majorname, minorname exist in the parent Tree
00255    // we find the current values pair majorv,minorv in the parent Tree
00256    Double_t majord = fMajorFormulaParent->EvalInstance();
00257    Double_t minord = fMinorFormulaParent->EvalInstance();
00258    Long64_t majorv = (Long64_t)majord;
00259    Long64_t minorv = (Long64_t)minord;
00260    // we check if this pair exist in the index.
00261    // if yes, we return the corresponding entry number
00262    // if not the function returns -1
00263    return fTree->GetEntryNumberWithIndex(majorv,minorv);
00264 }
00265 
00266 //______________________________________________________________________________
00267 Long64_t TChainIndex::GetEntryNumberWithBestIndex(Int_t major, Int_t minor) const
00268 {
00269    // See TTreeIndex::GetEntryNumberWithBestIndex for details.
00270 
00271    std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
00272    if (!indexAndNumber.first) {
00273       Error("GetEntryNumberWithBestIndex","no index found");
00274       return -1;
00275    }
00276    else {
00277       Long64_t rv = indexAndNumber.first->GetEntryNumberWithBestIndex(major, minor);
00278       ReleaseSubTreeIndex(indexAndNumber.first, indexAndNumber.second);
00279       TChain* chain = dynamic_cast<TChain*> (fTree);
00280       R__ASSERT(chain);
00281       return rv + chain->GetTreeOffset()[indexAndNumber.second];
00282    }
00283 }
00284 
00285 //______________________________________________________________________________
00286 Long64_t TChainIndex::GetEntryNumberWithIndex(Int_t major, Int_t minor) const
00287 {
00288    // Returns the entry number with given index values.
00289    // See TTreeIndex::GetEntryNumberWithIndex for details.
00290 
00291    std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
00292    if (!indexAndNumber.first) {
00293       Error("GetEntryNumberWithIndex","no index found");
00294       return -1;
00295    }
00296    else {
00297       Long64_t rv = indexAndNumber.first->GetEntryNumberWithIndex(major, minor);
00298       ReleaseSubTreeIndex(indexAndNumber.first, indexAndNumber.second);
00299       TChain* chain = dynamic_cast<TChain*> (fTree);
00300       R__ASSERT(chain);
00301       return rv + chain->GetTreeOffset()[indexAndNumber.second];
00302    }
00303 }
00304 
00305 //______________________________________________________________________________
00306 TTreeFormula *TChainIndex::GetMajorFormulaParent(const TTree *T)
00307 {
00308    // return a pointer to the TreeFormula corresponding to the majorname in parent tree T
00309 
00310    if (!fMajorFormulaParent) {
00311       fMajorFormulaParent = new TTreeFormula("MajorP",fMajorName.Data(),(TTree*)T);
00312       fMajorFormulaParent->SetQuickLoad(kTRUE);
00313    }
00314    if (fMajorFormulaParent->GetTree() != T) {
00315       fMajorFormulaParent->SetTree((TTree*)T);
00316       fMajorFormulaParent->UpdateFormulaLeaves();
00317    }
00318    return fMajorFormulaParent;
00319 }
00320 
00321 //______________________________________________________________________________
00322 TTreeFormula *TChainIndex::GetMinorFormulaParent(const TTree *T)
00323 {
00324    // return a pointer to the TreeFormula corresponding to the minorname in parent tree T
00325 
00326    if (!fMinorFormulaParent) {
00327       fMinorFormulaParent = new TTreeFormula("MinorP",fMinorName.Data(),(TTree*)T);
00328       fMinorFormulaParent->SetQuickLoad(kTRUE);
00329    }
00330    if (fMinorFormulaParent->GetTree() != T) {
00331       fMinorFormulaParent->SetTree((TTree*)T);
00332       fMinorFormulaParent->UpdateFormulaLeaves();
00333    }
00334 
00335    return fMinorFormulaParent;
00336 }
00337 
00338 //______________________________________________________________________________
00339 void TChainIndex::UpdateFormulaLeaves(const TTree *parent)
00340 {
00341    // Updates the parent formulae.
00342    // Called by TChain::LoadTree when the parent chain changes it's tree.
00343    if (fMajorFormulaParent) { 
00344       if (parent) fMajorFormulaParent->SetTree((TTree*)parent);
00345       fMajorFormulaParent->UpdateFormulaLeaves();
00346    }
00347    if (fMinorFormulaParent) { 
00348       if (parent) fMinorFormulaParent->SetTree((TTree*)parent);
00349       fMinorFormulaParent->UpdateFormulaLeaves();
00350    }
00351 }
00352 
00353 //______________________________________________________________________________
00354 void TChainIndex::SetTree(const TTree *T)
00355 {
00356    // See TTreeIndex::SetTree.
00357 
00358    R__ASSERT(fTree == 0 || fTree == T || T==0);
00359 }
00360 

Generated on Tue Jul 5 15:42:58 2011 for ROOT_528-00b_version by  doxygen 1.5.1