TEntryList.cxx

Go to the documentation of this file.
00001 // @(#)root/tree:$Id: TEntryList.cxx 35745 2010-09-26 16:49:05Z pcanal $
00002 // Author: Anna Kreshuk 27/10/2006
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2006, 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 /* Begin_Html
00014 <center><h2>TEntryList: a List of entry numbers in a TTree or TChain</h2></center>
00015 
00016 There are two types of entry lists:
00017 <ol>
00018 <li> for a TTree (fBlocks data member is non-zero)
00019   Entry numbers are stored in TEntryListBlocks, which, in their turn, are stored
00020   in the TObjArray fBlocks. The range of the entry numbers is cut into intervals
00021   of kBlockSize entries (currently 64000), so that the first block contains
00022   information which entries out of the first 64000 pass the selection, the second
00023   block - which entries out of the 64000-127999 interval pass the selection, etc.
00024   Some blocks, obviously, might be empty. The internal representation of entry
00025   numbers in the blocks is described in the TEntryListBlock class description, and
00026   this representation might be changed by calling OptimizeStorage() function
00027   (when the list is filled via the Enter() function, this is done automatically,
00028   except for the last block).
00029   Individual entry lists can be merged (functions Merge() and Add())
00030   to make an entry list for a TChain of corresponding TTrees.
00031 End_Html
00032 Begin_Macro(source)
00033 entrylist_figure1.C
00034 End_Macro
00035 
00036 Begin_Html
00037  
00038 <li> for a TChain (fLists data member is non-zero)
00039   It contains a TList of sub-lists (TEntryList objects, corresponding to each TTree)
00040   Trees and lists are matched by the TTree name and its file name (full path). 
00041   All sub-lists are returned by the GetLists() function and individual lists are
00042   returned by GetEntryList() function. Such lists are no different from the lists for
00043   TTrees, described above.
00044 End_Html
00045 Begin_Macro(source)
00046 entrylist_figure2.C
00047 End_Macro
00048 
00049 Begin_Html
00050 </ol>
00051              <h4>Operations on entry lists</h4>
00052 
00053 <ul>
00054 <li> <b>Add</b>() - if the lists are for the same tree, adds all the entries of the second list
00055           to the first list. If the lists are for different trees, creates a TEntryList
00056           with 2 sublists for each TTree. If the lists are for TChains, merges the ones
00057           for the same trees and adds new sublists for the TTrees that were not included
00058           in the first TEntryList
00059 <li> <b>Subtract</b>() - if the lists are for the same TTree, removes the entries of the second
00060                list from the first list. If the lists are for TChains, loops over all
00061                sub-lists
00062 <li> <b>GetEntry(n)</b> - returns the n-th entry number 
00063 <li> <b>Next</b>()      - returns next entry number. Note, that this function is 
00064                 much faster than GetEntry, and it's called when GetEntry() is called
00065                 for 2 or more indices in a row.
00066 </ul>
00067 
00068                      <h4>TTree::Draw() and TChain::Draw()</h4>
00069 
00070   Use option <b>entrylist</b> to write the results of TTree::Draw and TChain::Draw into 
00071   an entry list. Example:
00072 <pre>
00073      tree->Draw(">>elist", "x<0 && y>0", "entrylist");
00074      TEntryList *elist = (TEntryList*)gDirectory->Get("elist");
00075 </pre>
00076 
00077                                 <h4> Example of Loop en TEntryList with a TChain</h4>
00078 <pre>
00079 void loopChain() {
00080    TFile *fe = TFile::Open("myelist.root");
00081    TEntryList *myelist=(TEntryList*)fe->Get("myelist");
00082    TChain *ch = new TChain("ntuple");
00083    ch->Add("hsimple.root");
00084    ch->Add("hsimple2.root");
00085    Long64_t listEntries=myelist->GetN();
00086    Long64_t chainEntries = ch->GetEntries();
00087    Int_t treenum=0;
00088    ch->SetEntryList(myelist);
00089    for (Long64_t el =0;el<listEntries;el++) {
00090       Long64_t treeEntry = myelist->GetEntryAndTree(el,treenum);
00091       Long64_t chainEntry = treeEntry+ch->GetTreeOffset()[treenum];
00092       printf("el=%lld, treeEntry=%lld, chainEntry=%lld, treenum=%d\n",el,treeEntry,chainEntry,treenum);
00093    }
00094 }
00095 </pre>
00096 
00097                                 <h4> TSelectors</h4>
00098 
00099   To fill an TEntryList from a TSelector correctly, one must add the TEntryList object
00100   to the output list of the selector (TSelector::fOutput). This is the only way to 
00101   make the sub-lists of the TEntryList switch when the current tree of the TChain is
00102   changed. 
00103 
00104    <h4> Using a TEntryList as input (TTree::SetEntryList() and TChain::SetEntryList())</h4>
00105 
00106   while the TTree::SetEntryList() function is only setting the TTree::fEntryList
00107   data member, the same function in TChain also finds correspondance between
00108   the TTrees of this TChain and the sub-lists of this TEntryList.
00109 
00110                        <h4>TEntryList and the current directory</h4>
00111 
00112   TEntryList objects are automatically added to the current directory (like TTrees).
00113   However, in case of a TEntryList for a chain, only the top-level entry list is added,
00114   not the sub-lists for specific trees. Placing entry lists in the current directory
00115   allows calling them as a part of a TTreeFormula expression, so if the user wants 
00116   to extract a sublist from a TChain entry list via the GetEntryList() or some other
00117   function, he has to add it to the current directory to be able to use it in 
00118   TTreeFormula expressions.
00119 
00120                       <h4>TEntryList and TEventList</h4>
00121 
00122   TTree::SetEventList() and TChain::SetEventList() transform a TEventList into a TEntryList
00123   See comments to those functions for more details
00124 End_Html */
00125 
00126 
00127 #include "TEntryList.h"
00128 #include "TEntryListBlock.h"
00129 #include "TTree.h"
00130 #include "TFile.h"
00131 #include "TSystem.h"
00132 
00133 ClassImp(TEntryList)
00134 
00135 //______________________________________________________________________________
00136 TEntryList::TEntryList() : fEntriesToProcess(0)
00137 {
00138    //default c-tor
00139 
00140    fLists = 0;
00141    fCurrent = 0;
00142    fBlocks = 0;
00143    fN = 0;
00144    fNBlocks = 0;
00145    fTreeName = "";
00146    fFileName = "";
00147    fStringHash = 0;
00148    fTreeNumber = -1;
00149    fDirectory = 0;
00150    fReapply = kFALSE;
00151    fLastIndexQueried = -1;
00152    fLastIndexReturned = 0;
00153    fShift = kFALSE;
00154 }
00155 
00156 //______________________________________________________________________________
00157 TEntryList::TEntryList(const char *name, const char *title) : 
00158    TNamed(name, title),
00159    fEntriesToProcess(0)
00160 {
00161    //c-tor with name and title
00162 
00163    fLists = 0;
00164    fCurrent = 0;
00165    fBlocks = 0;
00166    fN = 0;
00167    fNBlocks = 0;
00168    fTreeName = "";
00169    fFileName = "";
00170    fStringHash = 0;
00171    fTreeNumber = -1;
00172    fReapply = kFALSE;
00173 
00174    fDirectory  = gDirectory;
00175    if (fDirectory) fDirectory->Append(this);
00176 
00177    fLastIndexQueried = -1;
00178    fLastIndexReturned = 0;
00179    fShift = kFALSE;
00180 }
00181 
00182 //______________________________________________________________________________
00183 TEntryList::TEntryList(const char *name, const char *title, const TTree *tree):TNamed(name, title)
00184 {
00185    //constructor with name and title, which also sets the tree
00186 
00187    fLists = 0;
00188    fCurrent = 0;
00189    fBlocks = 0;
00190    fN = 0;
00191    fNBlocks = 0;
00192    fTreeNumber = -1;
00193    SetTree(tree);
00194    fReapply = kFALSE;
00195 
00196    fDirectory  = gDirectory;
00197    if (fDirectory) fDirectory->Append(this);
00198 
00199    fLastIndexQueried = -1;
00200    fLastIndexReturned = 0;
00201    fShift = kFALSE;
00202 }
00203 
00204 //______________________________________________________________________________
00205 TEntryList::TEntryList(const char *name, const char *title, const char *treename, const char *filename) : TNamed(name, title),fEntriesToProcess(0)
00206 {
00207    //c-tor with name and title, which also sets the treename and the filename
00208 
00209    fLists = 0;
00210    fCurrent = 0;
00211    fBlocks = 0;
00212    fNBlocks = 0;
00213    fN = 0;
00214    SetTree(treename, filename);
00215    fTreeNumber = -1;
00216    fReapply = kFALSE;
00217 
00218    fDirectory  = gDirectory;
00219    if (fDirectory) fDirectory->Append(this);
00220 
00221    fLastIndexQueried = -1;
00222    fLastIndexReturned = 0;
00223    fShift = kFALSE;
00224 }
00225 
00226 //______________________________________________________________________________
00227 TEntryList::TEntryList(const TTree *tree) : fEntriesToProcess(0)
00228 {
00229    //c-tor, which sets the tree
00230 
00231    fLists = 0;
00232    fCurrent = 0;
00233    fBlocks = 0;
00234    fNBlocks = 0;
00235    fN = 0;
00236 
00237    SetTree(tree);
00238    fTreeNumber = -1;
00239 
00240    fReapply = kFALSE;
00241    fDirectory  = gDirectory;
00242    if (fDirectory) fDirectory->Append(this);
00243 
00244    fLastIndexQueried = -1;
00245    fLastIndexReturned = 0;
00246    fShift = kFALSE;
00247 }
00248 
00249 //______________________________________________________________________________
00250 TEntryList::TEntryList(const TEntryList &elist) : TNamed(elist)
00251 {
00252    //copy c-tor
00253 
00254    fNBlocks = elist.fNBlocks;
00255    fTreeName = elist.fTreeName;
00256    fFileName = elist.fFileName;
00257    fStringHash = elist.fStringHash;
00258    fTreeNumber = elist.fTreeNumber;
00259    fLastIndexQueried = -1;
00260    fLastIndexReturned = 0;
00261    fN = elist.fN;
00262    fShift = elist.fShift;
00263    fLists = 0;
00264    fBlocks = 0;
00265    fReapply = elist.fReapply;
00266    fCurrent = 0;
00267    fEntriesToProcess = elist.fEntriesToProcess;
00268    if (elist.fLists){
00269       fLists = new TList();
00270       TEntryList *el1 = 0;
00271       TEntryList *el2 = 0;
00272       TIter next(elist.fLists);
00273       while((el1 = (TEntryList*)next())){
00274          el2 = new TEntryList(*el1);
00275          if (el1==elist.fCurrent)
00276             fCurrent = el2;
00277          fLists->Add(el2);
00278       }
00279    } else {
00280       if (elist.fBlocks){
00281          TEntryListBlock *block1 = 0;
00282          TEntryListBlock *block2 = 0;
00283          //or just copy it as a TObjArray??
00284          fBlocks = new TObjArray();
00285          for (Int_t i=0; i<fNBlocks; i++){
00286             block1 = (TEntryListBlock*)elist.fBlocks->UncheckedAt(i);
00287             block2 = new TEntryListBlock(*block1);
00288             fBlocks->Add(block2);
00289          }
00290       }
00291       fCurrent = this;
00292    }
00293    fDirectory  = 0;
00294 
00295 }
00296 
00297 
00298 //______________________________________________________________________________
00299 TEntryList::~TEntryList()
00300 {
00301    // Destructor.
00302 
00303    if (fBlocks){
00304       fBlocks->Delete();
00305       delete fBlocks;
00306    }
00307    fBlocks = 0;
00308    if (fLists){
00309       fLists->Delete();
00310       delete fLists;
00311    }
00312    
00313    fLists = 0;
00314 
00315    if (fDirectory) fDirectory->Remove(this);
00316    fDirectory  = 0;
00317 
00318 }
00319 
00320 //______________________________________________________________________________
00321 void TEntryList::Add(const TEntryList *elist)
00322 {
00323    //Add 2 entry lists
00324 
00325    if (fN==0){
00326       if (!fLists && fTreeName=="" && fFileName==""){
00327          //this list is empty. copy the other list completely
00328          fNBlocks = elist->fNBlocks;
00329          fTreeName = elist->fTreeName;
00330          fFileName = elist->fFileName;
00331          fStringHash = elist->fStringHash;
00332          fTreeNumber = elist->fTreeNumber;
00333          fLastIndexQueried = -1;
00334          fLastIndexReturned = 0;
00335          fN = elist->fN;
00336          if (elist->fLists){
00337             fLists = new TList();
00338             TEntryList *el1 = 0;
00339             TEntryList *el2 = 0;
00340             TIter next(elist->fLists);
00341             while((el1 = (TEntryList*)next())){
00342                el2 = new TEntryList(*el1);
00343                if (el1==elist->fCurrent)
00344                   fCurrent = el2;
00345                fLists->Add(el2);
00346             }
00347          } else {
00348             if (elist->fBlocks){
00349                TEntryListBlock *block1 = 0;
00350                TEntryListBlock *block2 = 0;
00351                fBlocks = new TObjArray();
00352                for (Int_t i=0; i<fNBlocks; i++){
00353                   block1 = (TEntryListBlock*)elist->fBlocks->UncheckedAt(i);
00354                   block2 = new TEntryListBlock(*block1);
00355                   fBlocks->Add(block2);
00356                }
00357             }
00358             fCurrent = 0;
00359          }
00360          return;
00361       }
00362    }
00363 
00364    if (!fLists){
00365       if (!elist->fLists){
00366          if (!strcmp(elist->fTreeName.Data(),fTreeName.Data()) && !strcmp(elist->fFileName.Data(),fFileName.Data())){
00367             //entry lists are for the same tree
00368             if (!elist->fBlocks)
00369                //the other list is empty list
00370                return;
00371             if (!fBlocks){
00372                //this entry list is empty
00373                TEntryListBlock *block1 = 0;
00374                TEntryListBlock *block2 = 0;
00375                fNBlocks = elist->fNBlocks;
00376                fN = elist->fN;
00377                fBlocks = new TObjArray();
00378                for (Int_t i=0; i<fNBlocks; i++){
00379                   block1 = (TEntryListBlock*)elist->fBlocks->UncheckedAt(i);
00380                   block2 = new TEntryListBlock(*block1);
00381                fBlocks->Add(block2);
00382                }
00383                return;
00384             }
00385             //both not empty, merge block by block
00386             TEntryListBlock *block1=0;
00387             TEntryListBlock *block2=0;
00388             Int_t i;
00389             Int_t nmin = TMath::Min(fNBlocks, elist->fNBlocks);
00390             Long64_t nnew, nold;
00391             for (i=0; i<nmin; i++){
00392                block1 = (TEntryListBlock*)fBlocks->UncheckedAt(i);
00393                block2 = (TEntryListBlock*)elist->fBlocks->UncheckedAt(i);
00394                nold = block1->GetNPassed();
00395                nnew = block1->Merge(block2);
00396                fN = fN - nold + nnew;
00397             }
00398             if (fNBlocks<elist->fNBlocks){
00399                Int_t nmax = elist->fNBlocks; 
00400                for (i=nmin; i<nmax; i++){
00401                   block2 = (TEntryListBlock*)elist->fBlocks->UncheckedAt(i);
00402                   block1 = new TEntryListBlock(*block2);
00403                   fBlocks->Add(block1);
00404                   fN+=block1->GetNPassed();
00405                   fNBlocks++;
00406                }
00407             }
00408             fLastIndexQueried = -1;
00409             fLastIndexReturned = 0;
00410          } else {
00411             //entry lists are for different trees. create a chain entry list with
00412             //2 sub lists for the first and second entry lists
00413             fLastIndexQueried = -1;
00414             fLastIndexReturned = 0;
00415             fLists = new TList();
00416             TEntryList *el = new TEntryList();
00417             el->fTreeName = fTreeName;
00418             el->fFileName = fFileName;
00419             el->fBlocks = fBlocks;
00420             fBlocks = 0;
00421             el->fNBlocks = fNBlocks;
00422             el->fN = fN;
00423             el->fLastIndexQueried = -1;
00424             el->fLastIndexReturned = 0;
00425             fLists->Add(el);
00426             el = new TEntryList(*elist);
00427             el->fLastIndexQueried = -1;
00428             el->fLastIndexReturned = 0;
00429             fLists->Add(el);
00430             fN+=el->GetN();
00431             fCurrent = 0;
00432          }
00433       } else {
00434          //second list already has sublists. add one by one
00435          TEntryList *el = 0;
00436          TIter next(elist->fLists);
00437          while ((el = (TEntryList*)next())){
00438             Add(el);
00439          }
00440          fCurrent = 0;
00441       }
00442    } else {
00443       //there are already some sublists in this list, just add another one
00444       if (!elist->fLists){
00445          //the other list doesn't have sublists
00446          TIter next(fLists);
00447          TEntryList *el = 0; 
00448          Bool_t found = kFALSE;
00449          while ((el = (TEntryList*)next())){
00450             if (!strcmp(el->fTreeName.Data(), elist->fTreeName.Data()) && 
00451                 !strcmp(el->fFileName.Data(), elist->fFileName.Data())){
00452             // if (el->fStringHash == elist->fStringHash){
00453                //found a list for the same tree
00454                Long64_t oldn = el->GetN();
00455                el->Add(elist);
00456                found = kTRUE;
00457                fN = fN - oldn + el->GetN();
00458                break;
00459             }
00460          }
00461          if (!found){       
00462             el = new TEntryList(*elist);
00463             el->fLastIndexQueried = -1;
00464             el->fLastIndexReturned = 0;
00465             fLists->Add(el);
00466             fN+=el->GetN();
00467          }
00468       } else {
00469          //add all sublists from the other list
00470          TEntryList *el = 0;
00471          TIter next(elist->fLists);
00472          while ((el = (TEntryList*)next())){
00473             Add(el);
00474          }
00475          fCurrent = 0;
00476       }
00477       if (fCurrent){
00478          if (fCurrent->fBlocks){
00479             Int_t currentblock = (fCurrent->fLastIndexReturned)/kBlockSize;
00480             TEntryListBlock *block = (TEntryListBlock*)fCurrent->fBlocks->UncheckedAt(currentblock);
00481             block->ResetIndices();
00482             fCurrent->fLastIndexReturned = 0;
00483             fCurrent->fLastIndexQueried = -1;
00484          }
00485       }
00486       fCurrent = 0;
00487    }
00488 
00489 }
00490 
00491 
00492 //______________________________________________________________________________
00493 Int_t TEntryList::Contains(Long64_t entry, TTree *tree)
00494 {
00495 //When tree = 0, returns from the current list
00496 //When tree != 0, finds the list, corresponding to this tree
00497 //When tree is a chain, the entry is assumed to be global index and the local
00498 //entry is recomputed from the treeoffset information of the chain
00499 
00500    if (!tree){
00501       if (fBlocks) {
00502          //this entry list doesn't contain any sub-lists
00503          TEntryListBlock *block = 0;
00504          Int_t nblock = entry/kBlockSize;
00505          if (nblock >= fNBlocks) return 0;
00506          block = (TEntryListBlock*)fBlocks->UncheckedAt(nblock);
00507          return block->Contains(entry-nblock*kBlockSize);
00508       }
00509       if (fLists) {
00510          if (!fCurrent) fCurrent = (TEntryList*)fLists->First();
00511          return fCurrent->Contains(entry);
00512       }
00513       return 0;
00514    } else {
00515       Long64_t localEntry = tree->LoadTree(entry);
00516       SetTree(tree->GetTree());
00517       if (fCurrent)
00518          return fCurrent->Contains(localEntry);
00519    }
00520    return 0;
00521 
00522 }
00523 
00524 //______________________________________________________________________________
00525 void TEntryList::DirectoryAutoAdd(TDirectory* dir)
00526 {
00527    // Called by TKey and others to automatically add us to a directory when we are read from a file.
00528    
00529    SetDirectory(dir);
00530 }
00531 
00532 //________________________________________________________________________
00533 Bool_t TEntryList::Enter(Long64_t entry, TTree *tree)
00534 {
00535    //Add entry #entry to the list
00536    //When tree = 0, adds to the current list
00537    //When tree != 0, finds the list, corresponding to this tree
00538    //When tree is a chain, the entry is assumed to be global index and the local
00539    //entry is recomputed from the treeoffset information of the chain
00540    
00541    if (!tree){
00542       if (!fLists) {
00543          if (!fBlocks) fBlocks = new TObjArray();
00544          TEntryListBlock *block = 0;
00545          Long64_t nblock = entry/kBlockSize;
00546          if (nblock >= fNBlocks) {
00547             if (fNBlocks>0){
00548                block = (TEntryListBlock*)fBlocks->UncheckedAt(fNBlocks-1);
00549                if (!block) return 0;
00550                block->OptimizeStorage();
00551             }
00552             for (Int_t i=fNBlocks; i<=nblock; i++){
00553                block = new TEntryListBlock();
00554                fBlocks->Add(block);
00555             }
00556          fNBlocks = nblock+1;
00557          }
00558          block = (TEntryListBlock*)fBlocks->UncheckedAt(nblock);
00559          if (block->Enter(entry-nblock*kBlockSize)) {
00560             fN++;
00561             return 1;
00562          }
00563       } else {
00564          //the entry in the current entry list
00565          if (!fCurrent) fCurrent = (TEntryList*)fLists->First();
00566          if (fCurrent->Enter(entry)) {
00567             if (fLists)
00568                fN++;
00569             return 1;
00570          }
00571       }
00572    } else {
00573       Long64_t localentry = tree->LoadTree(entry);
00574       SetTree(tree->GetTree());
00575       if (fCurrent){
00576          if (fCurrent->Enter(localentry)) {
00577             if (fLists)
00578                fN++;
00579             return 1;
00580          }
00581       }
00582    }
00583    return 0;
00584 
00585 }
00586 
00587 //______________________________________________________________________________
00588 Bool_t TEntryList::Remove(Long64_t entry, TTree *tree)
00589 {
00590 //Remove entry #entry from the list
00591 //When tree = 0, removes from the current list
00592 //When tree != 0, finds the list, corresponding to this tree
00593 //When tree is a chain, the entry is assumed to be global index and the local
00594 //entry is recomputed from the treeoffset information of the chain
00595 
00596    if (!tree){
00597       if (!fLists) {
00598          if (!fBlocks) return 0;
00599          TEntryListBlock *block = 0;
00600          Long64_t nblock = entry/kBlockSize;
00601          block = (TEntryListBlock*)fBlocks->UncheckedAt(nblock);
00602          if (!block) return 0;
00603          Long64_t blockindex = entry - nblock*kBlockSize;
00604          if (block->Remove(blockindex)){
00605             fN--;
00606             return 1;
00607          }
00608       } else {
00609          if (!fCurrent) fCurrent = (TEntryList*)fLists->First();
00610          if (fCurrent->Remove(entry)){
00611             if (fLists)
00612                fN--;
00613             return 1;
00614          }
00615       }
00616    } else {
00617       Int_t localentry = tree->LoadTree(entry);
00618       SetTree(tree->GetTree());
00619       if (fCurrent){
00620          if (fCurrent->Remove(localentry)) {
00621             if (fLists)
00622                fN--;
00623             return 1;
00624          }
00625       }
00626    }
00627    return 0;
00628 }
00629 
00630 //______________________________________________________________________________
00631 Long64_t TEntryList::GetEntry(Int_t index)
00632 {
00633    //return the number of the entry #index of this TEntryList in the TTree or TChain
00634    //See also Next().
00635 
00636 
00637    if (index>=fN){
00638       return -1;
00639    }
00640    if (index==fLastIndexQueried+1){
00641       //in a loop
00642       return Next();
00643    } else {
00644       if (fBlocks) {
00645          TEntryListBlock *block = 0;
00646          Long64_t total_passed = 0;
00647          Int_t i=0;
00648          while (total_passed<=index && i<fNBlocks){
00649             block=(TEntryListBlock*)fBlocks->UncheckedAt(i);
00650             total_passed+=block->GetNPassed();
00651             i++;
00652          }
00653          i--;
00654          total_passed-=block->GetNPassed();
00655          if (i!=fLastIndexReturned/kBlockSize){
00656             block = (TEntryListBlock*)fBlocks->UncheckedAt(fLastIndexReturned/kBlockSize);
00657             block->ResetIndices();
00658             block = (TEntryListBlock*)fBlocks->UncheckedAt(i);
00659          }
00660 
00661          Long64_t localindex = index - total_passed;
00662          Long64_t blockindex = block->GetEntry(localindex);
00663          if (blockindex < 0) return -1;
00664          Long64_t res = i*kBlockSize + blockindex;
00665          fLastIndexQueried = index;
00666          fLastIndexReturned = res;
00667          return res;
00668       } else {
00669          //find the corresponding list
00670          if (!fCurrent) fCurrent = (TEntryList*)fLists->First();
00671          TIter next(fLists);
00672          TEntryList *templist;
00673          Long64_t ntotal = 0;
00674          if (fCurrent){
00675             //reset all indices of the current list
00676             if (fCurrent->fBlocks){
00677                Int_t currentblock = (fCurrent->fLastIndexReturned)/kBlockSize;
00678                TEntryListBlock *block = (TEntryListBlock*)fCurrent->fBlocks->UncheckedAt(currentblock);
00679                block->ResetIndices();
00680                fCurrent->fLastIndexReturned = 0;
00681                fCurrent->fLastIndexQueried = -1;
00682             }
00683          }
00684          while ((templist = (TEntryList*)next())){
00685             if (!fShift){
00686                ntotal += templist->GetN();
00687             } else {
00688                if (templist->GetTreeNumber() >= 0)
00689                   ntotal += templist->GetN();
00690             }
00691             if (ntotal > index)
00692               break;
00693          }
00694          fCurrent = templist;
00695          if (!fCurrent) return -1;
00696          Long64_t localentry = index - (ntotal - fCurrent->GetN());
00697          fLastIndexQueried = index;
00698          fLastIndexReturned = fCurrent->GetEntry(localentry);
00699          return fLastIndexReturned;
00700       }
00701 
00702    }
00703    return -1;
00704 }
00705 
00706 //______________________________________________________________________________
00707 Long64_t TEntryList::GetEntryAndTree(Int_t index, Int_t &treenum)
00708 {
00709 //return the index of "index"-th non-zero entry in the TTree or TChain
00710 //and the # of the corresponding tree in the chain
00711 
00712 //If shift is true, then when the requested entry is found in an entry list,
00713 //for which there is no corresponding tree in the chain, this list is not
00714 //taken into account, and entry from the next list with a tree is returned.
00715 //Example:
00716 //First sublist - 20 entries, second sublist - 5 entries, third sublist - 10 entries
00717 //Second sublist doesn't correspond to any trees of the chain
00718 //Then, when GetEntryAndTree(21, treenum, kTRUE) is called, first entry of the
00719 //third sublist will be returned
00720 
00721    Long64_t result = GetEntry(index);
00722    if (fLists)
00723       treenum = fCurrent->fTreeNumber;
00724    else
00725       treenum = fTreeNumber;
00726    if (treenum<0) return -1;
00727 
00728    return result;
00729 }
00730 
00731 //______________________________________________________________________________
00732 TEntryList *TEntryList::GetEntryList(const char *treename, const char *filename, Option_t *opt)
00733 {
00734    //return the entry list, correspoding to treename and filename
00735    //By default, the filename is first tried as is, and then, if the corresponding list 
00736    //is not found, the filename is expanded to the absolute path, and compared again. 
00737    //To avoid it, use option "ne"
00738 
00739    if (gDebug > 1)
00740       Info("GetEntryList","tree: %s, file: %s",
00741                           (treename ? treename : "-"), (filename ? filename : "-"));
00742 
00743    if (!treename || !filename) return 0;
00744    TString option = opt;
00745    option.ToUpper();
00746    Bool_t nexp = option.Contains("NE");
00747 
00748    TString fn;
00749    TUrl u(filename, kTRUE);
00750    //fn = (!strcmp(u.GetProtocol(),"file")) ? u.GetFile() : filename;
00751    Bool_t local=kFALSE;
00752    if (!nexp){
00753       local = !strcmp(u.GetProtocol(), "file");
00754       if (local) fn = u.GetFile();
00755       else fn = u.GetUrl();
00756    } else {
00757       fn = filename;
00758    }
00759 
00760    if (!fLists){
00761       //there are no sublists
00762       if (!strcmp(treename, fTreeName.Data()) && !(strcmp(fn.Data(), fFileName.Data()))){
00763          return this;
00764       } else {
00765          //if the file is local, try the full name, unless "ne" option was specified
00766          if (!nexp && local){
00767             gSystem->ExpandPathName(fn);
00768             if (!gSystem->IsAbsoluteFileName(fn))
00769                gSystem->PrependPathName(gSystem->pwd(), fn);
00770             fn = gSystem->UnixPathName(fn);
00771             if (!strcmp(treename, fTreeName.Data()) && !(strcmp(fn.Data(), fFileName.Data())))
00772                return this;
00773          }
00774          return 0;
00775       }
00776    }
00777 
00778    TString stotal = treename;
00779    stotal.Append(fn);
00780    ULong_t newhash = stotal.Hash();
00781 
00782    TIter next(fLists);
00783    TEntryList *templist;
00784    while ((templist = (TEntryList*)next())){
00785       if (templist->fStringHash==0){
00786          stotal = templist->fTreeName + templist->fFileName;
00787          templist->fStringHash = stotal.Hash();
00788       }
00789       if (newhash == templist->fStringHash){
00790          if (!strcmp(templist->GetTreeName(), treename) && !strcmp(templist->GetFileName(), fn.Data())){
00791             return templist;
00792          }
00793       }
00794    }
00795 
00796    //didn't find anything for this filename, try the full name too
00797    if (!nexp && local){
00798       TString longname = fn;
00799       gSystem->ExpandPathName(longname);
00800       if (!gSystem->IsAbsoluteFileName(longname))
00801          gSystem->PrependPathName(gSystem->pwd(), longname);
00802       longname = gSystem->UnixPathName(longname);
00803       stotal = treename;
00804       stotal.Append(longname);
00805       newhash = stotal.Hash();
00806       next.Reset();
00807       while ((templist = (TEntryList*)next())){
00808          if (templist->fStringHash==0){
00809             stotal = templist->fTreeName + templist->fFileName;
00810             templist->fStringHash = stotal.Hash();
00811          }
00812          if (newhash == templist->fStringHash){
00813             if (!strcmp(templist->GetTreeName(), treename) && !strcmp(templist->GetFileName(), longname)){
00814                return templist;
00815             }
00816          }
00817       }
00818    }
00819    return 0;
00820 }
00821       
00822 //______________________________________________________________________________
00823 Int_t TEntryList::Merge(TCollection *list)
00824 {
00825    //Merge this list with the lists from the collection
00826 
00827    if (!list) return -1;
00828    TIter next(list);
00829    TEntryList *elist = 0;
00830    while ((elist = (TEntryList*)next())) {
00831       if (!elist->InheritsFrom(TEntryList::Class())) {
00832          Error("Add","Attempt to add object of class: %s to a %s",elist->ClassName(),this->ClassName());
00833          return -1;
00834       }
00835       Add(elist);
00836    }
00837    return 0;   
00838 }
00839 
00840 //______________________________________________________________________________
00841 Long64_t TEntryList::Next()
00842 {
00843    //return the next non-zero entry index (next after fLastIndexQueried)
00844    //this function is faster than GetEntry()
00845 
00846    Long64_t result;
00847    if (fN == fLastIndexQueried+1 || fN==0){
00848       return -1;
00849    }
00850    if (fBlocks){
00851       Int_t iblock = fLastIndexReturned/kBlockSize;
00852       TEntryListBlock *current_block = (TEntryListBlock*)fBlocks->UncheckedAt(iblock);
00853       result = current_block->Next();
00854       if (result>=0) {
00855          fLastIndexQueried++;
00856          fLastIndexReturned = result+kBlockSize*iblock;
00857          return fLastIndexReturned;
00858       }
00859       else {
00860          while (result<0 && iblock<fNBlocks-1) {
00861             current_block->ResetIndices();
00862             iblock++;
00863             current_block = (TEntryListBlock*)fBlocks->UncheckedAt(iblock);
00864             current_block->ResetIndices();
00865             result = current_block->Next();
00866          }
00867          if (result<0) {
00868             fLastIndexQueried = -1;
00869             fLastIndexReturned = 0;
00870             return -1;
00871          }
00872          fLastIndexQueried++;
00873          fLastIndexReturned = result+kBlockSize*iblock;
00874 
00875          return fLastIndexReturned;
00876       }
00877    } else {
00878       if (!fCurrent) {
00879          fCurrent = (TEntryList*)fLists->First();
00880          if (!fCurrent) return 0;
00881          if (fShift) {
00882             while (fCurrent->GetTreeNumber()<0) {
00883                fCurrent = (TEntryList*)fLists->After(fCurrent);
00884                if (!fCurrent) return 0;
00885             }
00886          }
00887       }
00888       result = fCurrent->Next();
00889       if (result>=0) {
00890          fLastIndexQueried++;
00891          fLastIndexReturned = result;
00892          return result;
00893       } else {
00894          if (fCurrent){
00895             //reset all indices of the current list
00896             if (fCurrent->fBlocks){
00897                Int_t currentblock = (fCurrent->fLastIndexReturned)/kBlockSize;
00898                TEntryListBlock *block = (TEntryListBlock*)fCurrent->fBlocks->UncheckedAt(currentblock);
00899                block->ResetIndices();
00900                fCurrent->fLastIndexReturned = 0;
00901                fCurrent->fLastIndexQueried = -1;
00902             }
00903          }
00904 
00905          //find the list with the next non-zero entry
00906          while (result<0 && fCurrent!=((TEntryList*)fLists->Last())){
00907             if (!fCurrent) return 0;
00908             fCurrent->fLastIndexQueried = -1;
00909             fCurrent->fLastIndexReturned = 0;
00910             fCurrent = (TEntryList*)fLists->After(fCurrent);
00911             // fCurrent is guarantee to be non-zero because it is not the 'last' 
00912             // element of the list.
00913             if (!fCurrent) return 0;
00914             if (!fShift)
00915                result = fCurrent->Next();
00916             else {
00917                if (fCurrent->GetTreeNumber() >= 0)
00918                   result = fCurrent->Next();
00919             }
00920          }
00921          fLastIndexQueried++;
00922          fLastIndexReturned = result;
00923          return result;
00924       }
00925    }
00926 }
00927 
00928 
00929 //______________________________________________________________________________
00930 void TEntryList::OptimizeStorage()
00931 {
00932    //Checks if the array representation is more economical and if so, switches to it
00933 
00934    if (fBlocks){
00935       TEntryListBlock *block = 0;
00936       for (Int_t i=0; i<fNBlocks; i++){
00937          block = (TEntryListBlock*)fBlocks->UncheckedAt(i);
00938          block->OptimizeStorage();
00939       }
00940    }
00941 }
00942 
00943 
00944 //______________________________________________________________________________
00945 void TEntryList::Print(const Option_t* option) const
00946 {
00947    //Print this list
00948    //option = "" - default - print the name of the tree and file
00949    //option = "all" - print all the entry numbers
00950 
00951    TString opt = option;
00952    opt.ToUpper();
00953    if (fBlocks) {
00954       printf("%s %s\n", fTreeName.Data(), fFileName.Data());
00955       if (opt.Contains("A")){
00956          TEntryListBlock* block = 0;
00957          for (Int_t i=0; i<fNBlocks; i++){
00958             block = (TEntryListBlock*)fBlocks->UncheckedAt(i);
00959             Int_t shift = i*kBlockSize;
00960             block->PrintWithShift(shift);
00961          }
00962       }
00963    }
00964    else {
00965       TEntryList *elist = 0;
00966       if (fN>0){
00967          TIter next(fLists);
00968          while((elist = (TEntryList*)next())){
00969             elist->Print(option);
00970          }
00971       } else {
00972          if (!fLists) printf("%s %s\n", fTreeName.Data(), fFileName.Data());
00973          else {
00974             TIter next(fLists);
00975             while ((elist = (TEntryList*)next())){
00976                printf("%s %s\n", elist->GetTreeName(), elist->GetFileName());
00977             }
00978          }
00979       }
00980    }
00981 }
00982 
00983 //______________________________________________________________________________
00984 void TEntryList::Reset()
00985 {
00986    //Reset this list
00987 
00988    //Maybe not delete, but just reset the number of blocks to 0????
00989 
00990    if (fBlocks){
00991       fBlocks->Delete();
00992       delete fBlocks;
00993       fBlocks = 0;
00994    }
00995    if (fLists){
00996       if (!((TEntryList*)fLists->First())->GetDirectory()){
00997          fLists->Delete();
00998       }
00999       delete fLists;
01000       fLists = 0;
01001    }
01002    fCurrent = 0;
01003    fBlocks = 0;
01004    fNBlocks = 0;
01005    fN = 0;
01006    fTreeName = "";
01007    fFileName = "";
01008    fStringHash = 0;
01009    fTreeNumber = -1;
01010    fLastIndexQueried = -1;
01011    fLastIndexReturned = 0;
01012    fReapply = kFALSE;
01013 }
01014 
01015 //______________________________________________________________________________
01016 void TEntryList::SetDirectory(TDirectory *dir)
01017 {
01018    //Add reference to directory dir. dir can be 0.
01019 
01020    if (fDirectory == dir) return;
01021    if (fDirectory) fDirectory->Remove(this);
01022    fDirectory = dir;
01023    if (fDirectory) fDirectory->Append(this);
01024 }
01025 
01026 //______________________________________________________________________________
01027 void TEntryList::SetTree(const char *treename, const char *filename)
01028 {
01029    //If a list for a tree with such name and filename exists, sets it as the current sublist
01030    //If not, creates this list and sets it as the current sublist
01031    //
01032    // ! the filename is taken as provided, no extensions to full path or url !
01033 
01034    TEntryList *elist = 0;
01035 
01036    TString stotal = treename;
01037    stotal.Append(filename);
01038    //printf("setting tree %s\n", stotal.Data());
01039    ULong_t newhash = stotal.Hash();
01040    if (fLists) {
01041       //find the corresponding entry list and make it current
01042       if (!fCurrent) fCurrent = (TEntryList*)fLists->First();
01043       if (fCurrent->fStringHash == 0){
01044          stotal = fCurrent->fTreeName + fCurrent->fFileName;
01045          fCurrent->fStringHash = stotal.Hash();
01046       }
01047       if (newhash == fCurrent->fStringHash){
01048          //this list is current
01049          if (!strcmp(fCurrent->fTreeName, treename) && !strcmp(fCurrent->fFileName, filename)){
01050             return;
01051          }
01052       } 
01053       TIter next(fLists);
01054       while ((elist = (TEntryList*)next())){
01055          if (newhash == elist->fStringHash){
01056             if (!strcmp(elist->GetTreeName(), treename) && !strcmp(elist->GetFileName(), filename)){
01057                //the current entry list was changed. reset the fLastIndexQueried,
01058                //so that Next() doesn't start with the wrong current list
01059                //Also, reset those indices in the previously current list
01060                if (fCurrent->fBlocks){
01061                   Int_t currentblock = (fCurrent->fLastIndexReturned)/kBlockSize;
01062                   TEntryListBlock *block = (TEntryListBlock*)fCurrent->fBlocks->UncheckedAt(currentblock);
01063                   block->ResetIndices();
01064                   fCurrent->fLastIndexReturned = 0;
01065                   fCurrent->fLastIndexQueried = -1;
01066                }
01067                fCurrent = elist;
01068                fLastIndexQueried = -3;
01069                return;
01070             }
01071          }
01072       }
01073       //didn't find an entry list for this tree, create a new one
01074       elist = new TEntryList("", "", treename, filename);
01075       if (elist->GetDirectory()) {
01076          //sub lists are not added to the current directory
01077          elist->GetDirectory()->Remove(elist);
01078          elist->SetDirectory(0);
01079       }
01080       fLists->Add(elist);
01081       fCurrent = elist;
01082       return;
01083    } else {
01084       if (fN==0 && fTreeName=="" && fFileName==""){
01085          //this is the first tree set to this list
01086          fTreeName = treename;
01087          fFileName = filename;
01088          stotal = fTreeName + fFileName;
01089          //fStringHash = stotal.Hash();
01090          fStringHash = newhash;
01091          fCurrent = this;
01092       } else {
01093          if (fStringHash == 0){
01094             stotal = fTreeName + fFileName;
01095             fStringHash = stotal.Hash();
01096          }
01097          if (newhash != fStringHash){
01098             //we have a chain and already have an entry list for the first tree
01099             //move the first entry list to the fLists
01100             fLists = new TList();
01101             elist = new TEntryList();
01102             elist->fTreeName = fTreeName;
01103             elist->fFileName = fFileName;
01104             elist->fStringHash = fStringHash;
01105             elist->fN = fN;
01106             elist->fTreeNumber = fTreeNumber;
01107             elist->fBlocks = fBlocks;
01108             fBlocks = 0;
01109             elist->fNBlocks = fNBlocks;
01110             fLists->Add(elist);
01111             elist = new TEntryList("", "", treename, filename);
01112             if (elist->GetDirectory()) {
01113                //sub lists are not added to the current directory
01114                elist->GetDirectory()->Remove(elist);
01115                elist->SetDirectory(0);
01116             }
01117             fLists->Add(elist);
01118             fCurrent = elist;
01119             //the current entry list was changed. reset the fLastIndexQueried,
01120             //so that Next() doesn't start with the wrong current list
01121             fLastIndexQueried = -3;
01122             
01123          }
01124          else {
01125             //same tree as in the current entry list, don't do anything
01126             return;
01127          }
01128       }
01129    }
01130 }
01131 
01132 //______________________________________________________________________________
01133 void TEntryList::SetTree(const TTree *tree)
01134 {
01135    //If a list for a tree with such name and filename exists, sets it as the current sublist
01136    //If not, creates this list and sets it as the current sublist
01137    //The name of the file, where the tree is, is taken as 
01138    //tree->GetTree()->GetCurrentFile()->GetName(), and then expanded either to the absolute path,
01139    //or to full url. If, for some reason, you want to provide 
01140    //the filename in a different format, use SetTree(const char *treename, const char *filename),
01141    //where the filename is taken "as is".
01142 
01143    if (!tree) return;
01144    TString treename = tree->GetTree()->GetName();
01145    TString filename;
01146    if (tree->GetTree()->GetCurrentFile()){
01147       filename = tree->GetTree()->GetCurrentFile()->GetName();
01148       TUrl url(filename.Data(), kTRUE);
01149       if (!strcmp(url.GetProtocol(), "file")){
01150          gSystem->ExpandPathName(filename);
01151          if (!gSystem->IsAbsoluteFileName(filename))
01152             gSystem->PrependPathName(gSystem->pwd(), filename);
01153          filename = gSystem->UnixPathName(filename);
01154       } else {
01155          filename = url.GetUrl();
01156       }
01157    } else {
01158       //memory-resident
01159       filename = "";
01160    }
01161    SetTree(treename, filename);
01162 
01163 }
01164 
01165 //______________________________________________________________________________
01166 void TEntryList::Subtract(const TEntryList *elist)
01167 {
01168    //remove all the entries of this entry list, that are contained in elist
01169 
01170    TEntryList *templist = 0;
01171    if (!fLists){
01172       if (!fBlocks) return;
01173       //check if lists are for the same tree
01174       if (!elist->fLists){
01175          //second list is also only for 1 tree
01176          if (!strcmp(elist->fTreeName.Data(),fTreeName.Data()) && 
01177              !strcmp(elist->fFileName.Data(),fFileName.Data())){
01178             //same tree
01179             Long64_t n2 = elist->GetN();
01180             Long64_t entry;
01181             for (Int_t i=0; i<n2; i++){
01182                entry = (const_cast<TEntryList*>(elist))->GetEntry(i);
01183                Remove(entry);
01184             }
01185          } else {
01186             //different trees
01187             return;
01188          }
01189       } else {
01190          //second list has sublists, try to find one for the same tree as this list
01191          TIter next1(elist->GetLists());
01192          templist = 0;
01193          Bool_t found = kFALSE;
01194          while ((templist = (TEntryList*)next1())){
01195             if (!strcmp(templist->fTreeName.Data(),fTreeName.Data()) && 
01196                 !strcmp(templist->fFileName.Data(),fFileName.Data())){
01197                found = kTRUE;
01198                break;
01199             }
01200          }
01201          if (found) {
01202             Subtract(templist);
01203          }
01204       } 
01205    } else {
01206       //this list has sublists
01207       TIter next2(fLists);
01208       templist = 0;
01209       Long64_t oldn=0;
01210       while ((templist = (TEntryList*)next2())){
01211          oldn = templist->GetN();
01212          templist->Subtract(elist);
01213          fN = fN - oldn + templist->GetN();
01214       }
01215    }
01216    return;
01217 
01218 
01219 }
01220 
01221 //______________________________________________________________________________
01222 TEntryList operator||(TEntryList &elist1, TEntryList &elist2)
01223 {
01224    TEntryList eresult = elist1;
01225    //eresult = elist1;
01226    // printf("internal in operator1\n");
01227    eresult.Print("all");
01228    eresult.Add(&elist2);
01229    // printf("internal in operator2\n");
01230    eresult.Print("all");
01231 
01232    return eresult;
01233 }
01234 
01235 

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