TEntryListFromFile.cxx

Go to the documentation of this file.
00001 // @(#)root/tree:$Id: TEntryListFromFile.cxx 20882 2007-11-19 11:31:26Z rdm $
00002 // Author: Anna Kreshuk 17/03/2007
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2007, 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 // TEntryListFromFile
00014 //
00015 // Manages entry lists from different files, when they are not loaded
00016 // in memory at the same time. 
00017 //
00018 // This entry list should only be used when processing a TChain (see
00019 // TChain::SetEntryList() function). File naming convention:
00020 // - by default, filename_elist.root is used, where filename is the
00021 //   name of the chain element.
00022 // - xxx$xxx.root - $ sign is replaced by the name of the chain element
00023 // If the list name is not specified (by passing filename_elist.root/listname to
00024 // the TChain::SetEntryList() function, the first object of class TEntryList
00025 // in the file is taken.
00026 // It is assumed that there are as many lists, as there are chain elements,
00027 // and they are in the same order.
00028 //
00029 // If one of the list files can't be opened, or there is an error reading a list
00030 // from the file, this list is skipped and the entry loop continues on the next
00031 // list.
00032 
00033 
00034 #include "TEntryListFromFile.h"
00035 #include "TObjArray.h"
00036 #include "TFile.h"
00037 #include "TKey.h"
00038 
00039 ClassImp(TEntryListFromFile)
00040 
00041 TEntryListFromFile::TEntryListFromFile():TEntryList()
00042 {
00043 // default c-tor
00044 
00045    fListFileName ="";
00046    fNFiles = 0;
00047    fFile = 0;
00048 }
00049 
00050 //______________________________________________________________________________
00051 TEntryListFromFile::TEntryListFromFile(const char *filename, const char *listname, Int_t nfiles):TEntryList()
00052 {
00053 // File naming convention:
00054 // - by default, filename_elist.root is used, where filename is the
00055 //   name of the chain element
00056 // - xxx$xxx.root - $ sign is replaced by the name of the chain element
00057 // The TObjArray of chain elements is set by the TEntryListFromFile::SetFileNames()
00058 // function.
00059 // If the list name is not specified, the first object of class TEntryList
00060 // in the file is taken.  
00061 // nfiles is the total number of files to process
00062 
00063    fListFileName = filename;
00064    fListName = listname;
00065    fNFiles = nfiles;
00066    fListOffset = new Long64_t[fNFiles+1];
00067    fListOffset[0]=0;
00068    for (Int_t i=1; i<fNFiles+1; i++){
00069       fListOffset[i]=kBigNumber;
00070    }
00071    fN = kBigNumber;
00072    fFile = 0;
00073 }
00074 
00075 //______________________________________________________________________________
00076 TEntryListFromFile::~TEntryListFromFile()
00077 {
00078 // d-tor
00079 
00080    delete [] fListOffset;
00081    fListOffset = 0;
00082    delete fFile;
00083    fFile = 0;
00084 
00085 }
00086 
00087 //______________________________________________________________________________
00088 Long64_t TEntryListFromFile::GetEntry(Int_t index)
00089 {
00090    //returns entry #index
00091    //See also Next() for a faster alternative
00092    
00093    if (index<0) return -1;
00094 
00095    if (index > fListOffset[fNFiles] && fListOffset[fNFiles]!=kBigNumber){
00096       Error("GetEntry", "Index value is too large\n");
00097       return -1;
00098    }
00099 
00100    if (index==fLastIndexQueried+1)
00101       return Next();
00102    
00103    Int_t itree =0;
00104    while (!fCurrent && itree<fNFiles){
00105       LoadList(itree);
00106       itree++;
00107    }
00108    if (itree == fNFiles){
00109       Error("GetEntry", "All lists are empty\n");
00110       return -1;
00111    }
00112 
00113    if (index < fListOffset[fTreeNumber]) {
00114       //this entry is in one of previously opened lists
00115       itree=0;
00116       for (itree=0; itree<fTreeNumber; itree++){
00117          if (index >= fListOffset[itree] && fListOffset[itree]!=fListOffset[itree+1])
00118             break;
00119       }
00120       LoadList(itree);  
00121    }
00122    else if (index >= fListOffset[fTreeNumber+1]){
00123       //this entry is in one of following lists
00124       itree = fTreeNumber;
00125       while (itree < fNFiles){
00126          itree++;
00127          if (fListOffset[itree+1]==kBigNumber){
00128             //this list hasn't been loaded yet
00129             LoadList(itree);
00130          }
00131          if (index < fListOffset[itree+1]){
00132             //the entry is in this list
00133             break;
00134          }
00135       }
00136       if (fTreeNumber == fNFiles){
00137          Error("GetEntry", "Entry number is too big\n");
00138          return -1;
00139       }
00140       if (fTreeNumber!=itree)
00141          LoadList(itree);
00142    }
00143    //now the entry is in the currently opened list
00144    Long64_t localentry = index - fListOffset[fTreeNumber];
00145    Long64_t retentry = fCurrent->GetEntry(localentry);
00146    fLastIndexQueried = index;
00147    fLastIndexReturned = retentry;
00148    return retentry;
00149    
00150 }
00151 
00152 //______________________________________________________________________________
00153 Long64_t TEntryListFromFile::GetEntryAndTree(Int_t index, Int_t &treenum)
00154 {
00155    //return the entry corresponding to the index parameter and the
00156    //number of the tree, where this entry is
00157 
00158    Long64_t result = GetEntry(index);
00159    treenum = fTreeNumber;
00160    return result;
00161 }
00162 
00163 //______________________________________________________________________________
00164 Long64_t TEntryListFromFile::GetEntries()
00165 {
00166    //Returns the total number of entries in the list.
00167    //If some lists have not been loaded, loads them.
00168 
00169    if (fN==kBigNumber){
00170       for (Int_t i=0; i<fNFiles; i++){
00171          if (fListOffset[i+1]==kBigNumber){
00172             LoadList(i);
00173          }
00174       }
00175    }
00176    fN = fListOffset[fNFiles];
00177    fLastIndexQueried = -3;
00178    return fN;
00179 }
00180 
00181 //______________________________________________________________________________
00182 Long64_t TEntryListFromFile::Next()
00183 {
00184    //Returns the next entry in the list.
00185    //Faster than GetEntry()   
00186 
00187    Int_t itree =0;
00188    while (!fCurrent && itree<fNFiles){
00189       LoadList(itree);
00190       itree++;
00191    }
00192    if (itree == fNFiles){
00193       Error("Next", "All lists are empty\n");
00194       return -1;
00195    }
00196 
00197    Long64_t retentry = fCurrent->Next();
00198    if (retentry<0){
00199       if (fLastIndexQueried == fListOffset[fTreeNumber+1]-1){
00200          //requested entry is in the next list
00201          if (fTreeNumber == fNFiles -1){
00202             // Error("Next", "No more entries, last list\n");
00203             return -1;
00204          }
00205          do{
00206             //load the next non-empty list. fTreeNumber is changed by LoadList()
00207             fTreeNumber++;
00208             LoadList(fTreeNumber);
00209          } while (fListOffset[fTreeNumber+1]==fListOffset[fTreeNumber] && fTreeNumber<fNFiles-1);
00210          if (fTreeNumber == fNFiles -1 && fListOffset[fTreeNumber+1]==fListOffset[fTreeNumber]){
00211             //no more lists
00212             return -1;
00213          }
00214          retentry = fCurrent->Next();
00215       } else {
00216          Error("Next", "Something wrong with reading the current list, even though thefile #%d and the list exist\n", fTreeNumber);
00217          return -1;
00218       }
00219       
00220    }
00221 
00222    fLastIndexQueried++;
00223    fLastIndexReturned = retentry;
00224    return retentry;
00225    
00226 }
00227 
00228 //______________________________________________________________________________
00229 Int_t TEntryListFromFile::LoadList(Int_t listnumber)
00230 {
00231    //Loads the list #listnumber
00232    //This is the only function that can modify fCurrent and fFile data members
00233 
00234    //first close the current list
00235    if (fCurrent){
00236       if (fFile) {
00237          delete fFile;
00238          fFile = 0;
00239          fCurrent = 0;
00240       }
00241    }
00242    
00243    //find the right name
00244    //get the name of the corresponding chain element (with the treenumber=listnumber)
00245    TNamed *nametitle = (TNamed*)fFileNames->At(listnumber);
00246    TString filename_short = nametitle->GetTitle();
00247    if (filename_short.Contains(".root")){
00248       filename_short.Remove(filename_short.Length()-5, 5);
00249    }
00250    if (!strcmp(fListFileName.Data(), "")){
00251       //no name supplied, use the one of the chain file
00252       filename_short.Append("_elist.root");
00253       //printf("filename: %s\n", filename_short.Data());
00254       fFile = TFile::Open(filename_short.Data());
00255    } else {
00256       TString filename = fListFileName;
00257       filename.ReplaceAll("$", filename_short);
00258       //printf("filename: %s\n", filename.Data());
00259       fFile = TFile::Open(filename.Data());
00260    }
00261 
00262    if (!fFile || fFile->IsZombie()){
00263       if (fFile) {
00264          delete fFile;
00265          fFile = 0;
00266       }
00267       fCurrent = 0;
00268       fListOffset[listnumber+1]=fListOffset[listnumber];
00269       return -1;
00270    }
00271 
00272    if (!strcmp(fListName.Data(), "")){
00273       TKey *key;
00274       TIter nextkey(fFile->GetListOfKeys());
00275       while ((key=(TKey*)nextkey())){
00276          if (strcmp("TEntryList", key->GetClassName())==0){
00277             //found an object of class TEntryList
00278             fCurrent = (TEntryList*)key->ReadObj();
00279          }
00280       }
00281    } else {
00282       fCurrent = (TEntryList*)fFile->Get(fListName.Data());
00283    }
00284 
00285    if (!fCurrent){
00286       Error("LoadList", "List %s not found in the file\n", fListName.Data());
00287       fCurrent = 0;
00288       fListOffset[listnumber+1]=fListOffset[listnumber];
00289       return -1;
00290    }
00291    fTreeNumber = listnumber;
00292    Long64_t nentries = fCurrent->GetN();
00293    if (fListOffset[fTreeNumber+1] != (fListOffset[fTreeNumber] + nentries)) {
00294       fListOffset[fTreeNumber+1] = fListOffset[fTreeNumber] + nentries;
00295       fN = fListOffset[fNFiles];
00296    }
00297    
00298    return 1;
00299 }
00300 
00301 //______________________________________________________________________________
00302 void TEntryListFromFile::Print(const Option_t* option) const
00303 {
00304    //Print info about this list  
00305    printf("total number of files: %d\n", fNFiles);
00306    TFile *f;
00307    TEntryList *el=0;
00308    for (Int_t listnumber=0; listnumber<fNFiles; listnumber++){
00309       TNamed *nametitle = (TNamed*)fFileNames->At(listnumber);
00310       TString filename_short = nametitle->GetTitle();
00311       if (filename_short.Contains(".root")){
00312          filename_short.Remove(filename_short.Length()-5, 5);
00313       }
00314       if (!strcmp(fListFileName.Data(), "")){
00315       //no name supplied, use the one of the chain file
00316          filename_short.Append("_elist.root");
00317          //printf("filename: %s\n", filename_short.Data());
00318          f = TFile::Open(filename_short.Data());
00319       } else {
00320          TString filename = fListFileName;
00321          filename.ReplaceAll("$", filename_short);
00322          //printf("filename: %s\n", filename.Data());
00323          f = TFile::Open(filename.Data());
00324       }
00325       if (f && !f->IsZombie()){
00326          if (!strcmp(fListName.Data(), "")){
00327             TKey *key;
00328             TIter nextkey(f->GetListOfKeys());
00329             while ((key=(TKey*)nextkey())){
00330                if (strcmp("TEntryList", key->GetClassName())==0){
00331                   //found an object of class TEntryList
00332                   el = (TEntryList*)key->ReadObj();
00333                }
00334             }
00335          } else {
00336             el = (TEntryList*)f->Get(fListName.Data());
00337          }
00338          if (el) 
00339             el->Print(option);
00340       }
00341    }
00342 
00343 }

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