00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "TChain.h"
00030
00031 #include "TBranch.h"
00032 #include "TBrowser.h"
00033 #include "TChainElement.h"
00034 #include "TClass.h"
00035 #include "TCut.h"
00036 #include "TError.h"
00037 #include "TMath.h"
00038 #include "TFile.h"
00039 #include "TFileInfo.h"
00040 #include "TFriendElement.h"
00041 #include "TLeaf.h"
00042 #include "TList.h"
00043 #include "TObjString.h"
00044 #include "TPluginManager.h"
00045 #include "TROOT.h"
00046 #include "TRegexp.h"
00047 #include "TSelector.h"
00048 #include "TSystem.h"
00049 #include "TTree.h"
00050 #include "TTreeCloner.h"
00051 #include "TTreeCache.h"
00052 #include "TUrl.h"
00053 #include "TVirtualIndex.h"
00054 #include "TEventList.h"
00055 #include "TEntryList.h"
00056 #include "TEntryListFromFile.h"
00057 #include "TFileStager.h"
00058
00059 const Long64_t theBigNumber = Long64_t(1234567890)<<28;
00060
00061 ClassImp(TChain)
00062
00063
00064 TChain::TChain()
00065 : TTree()
00066 , fTreeOffsetLen(100)
00067 , fNtrees(0)
00068 , fTreeNumber(-1)
00069 , fTreeOffset(0)
00070 , fCanDeleteRefs(kFALSE)
00071 , fTree(0)
00072 , fFile(0)
00073 , fFiles(0)
00074 , fStatus(0)
00075 , fProofChain(0)
00076 {
00077
00078
00079 fTreeOffset = new Long64_t[fTreeOffsetLen];
00080 fFiles = new TObjArray(fTreeOffsetLen);
00081 fStatus = new TList();
00082 fTreeOffset[0] = 0;
00083 gDirectory->Remove(this);
00084 gROOT->GetListOfSpecials()->Add(this);
00085 fFile = 0;
00086 fDirectory = 0;
00087
00088
00089 ResetBit(kProofUptodate);
00090 ResetBit(kProofLite);
00091
00092
00093 gROOT->GetListOfDataSets()->Add(this);
00094
00095
00096 gROOT->GetListOfCleanups()->Add(this);
00097 }
00098
00099
00100 TChain::TChain(const char* name, const char* title)
00101 :TTree(name, title)
00102 , fTreeOffsetLen(100)
00103 , fNtrees(0)
00104 , fTreeNumber(-1)
00105 , fTreeOffset(0)
00106 , fCanDeleteRefs(kFALSE)
00107 , fTree(0)
00108 , fFile(0)
00109 , fFiles(0)
00110 , fStatus(0)
00111 , fProofChain(0)
00112 {
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 fTreeOffset = new Long64_t[fTreeOffsetLen];
00151 fFiles = new TObjArray(fTreeOffsetLen);
00152 fStatus = new TList();
00153 fTreeOffset[0] = 0;
00154 gDirectory->Remove(this);
00155 gROOT->GetListOfSpecials()->Add(this);
00156 fFile = 0;
00157 fDirectory = 0;
00158
00159
00160 ResetBit(kProofUptodate);
00161 ResetBit(kProofLite);
00162
00163
00164 gROOT->GetListOfDataSets()->Add(this);
00165
00166
00167 gROOT->GetListOfCleanups()->Add(this);
00168 }
00169
00170
00171 TChain::~TChain()
00172 {
00173
00174 gROOT->GetListOfCleanups()->Remove(this);
00175
00176 SafeDelete(fProofChain);
00177 fStatus->Delete();
00178 delete fStatus;
00179 fStatus = 0;
00180 fFiles->Delete();
00181 delete fFiles;
00182 fFiles = 0;
00183 delete fFile;
00184 fFile = 0;
00185
00186 fTree = 0;
00187 delete[] fTreeOffset;
00188 fTreeOffset = 0;
00189
00190 gROOT->GetListOfSpecials()->Remove(this);
00191
00192
00193 gROOT->GetListOfDataSets()->Remove(this);
00194
00195
00196 fDirectory = 0;
00197 }
00198
00199
00200 Int_t TChain::Add(TChain* chain)
00201 {
00202
00203
00204
00205 if (!chain) return 0;
00206
00207
00208 if ((fNtrees + chain->GetNtrees()) >= fTreeOffsetLen) {
00209 fTreeOffsetLen += 2 * chain->GetNtrees();
00210 Long64_t* trees = new Long64_t[fTreeOffsetLen];
00211 for (Int_t i = 0; i <= fNtrees; i++) {
00212 trees[i] = fTreeOffset[i];
00213 }
00214 delete[] fTreeOffset;
00215 fTreeOffset = trees;
00216 }
00217 chain->GetEntries();
00218 TIter next(chain->GetListOfFiles());
00219 Int_t nf = 0;
00220 TChainElement* element = 0;
00221 while ((element = (TChainElement*) next())) {
00222 Long64_t nentries = element->GetEntries();
00223 if (fTreeOffset[fNtrees] == theBigNumber) {
00224 fTreeOffset[fNtrees+1] = theBigNumber;
00225 } else {
00226 fTreeOffset[fNtrees+1] = fTreeOffset[fNtrees] + nentries;
00227 }
00228 fNtrees++;
00229 fEntries += nentries;
00230 TChainElement* newelement = new TChainElement(element->GetName(), element->GetTitle());
00231 newelement->SetPacketSize(element->GetPacketSize());
00232 newelement->SetNumberEntries(nentries);
00233 fFiles->Add(newelement);
00234 nf++;
00235 }
00236 if (fProofChain)
00237
00238 ResetBit(kProofUptodate);
00239
00240 return nf;
00241 }
00242
00243
00244 Int_t TChain::Add(const char* name, Long64_t nentries )
00245 {
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 if (!TString(name).MaybeWildcard()) {
00297 return AddFile(name, nentries);
00298 }
00299
00300
00301 Int_t nf = 0;
00302 TString basename(name);
00303
00304 Int_t dotslashpos = -1;
00305 {
00306 Int_t next_dot = basename.Index(".root");
00307 while(next_dot>=0) {
00308 dotslashpos = next_dot;
00309 next_dot = basename.Index(".root",dotslashpos+1);
00310 }
00311 if (basename[dotslashpos+5]!='/') {
00312
00313
00314 dotslashpos = -1;
00315 }
00316 }
00317
00318 TString behind_dot_root;
00319 if (dotslashpos>=0) {
00320
00321 behind_dot_root = basename(dotslashpos+6,basename.Length()-dotslashpos+6);
00322
00323 basename.Remove(dotslashpos+5);
00324 }
00325
00326 Int_t slashpos = basename.Last('/');
00327 TString directory;
00328 if (slashpos>=0) {
00329 directory = basename(0,slashpos);
00330 basename.Remove(0,slashpos+1);
00331 } else {
00332 directory = gSystem->UnixPathName(gSystem->WorkingDirectory());
00333 }
00334
00335 const char *file;
00336 const char *epath = gSystem->ExpandPathName(directory.Data());
00337 void *dir = gSystem->OpenDirectory(epath);
00338 delete [] epath;
00339 if (dir) {
00340
00341 TList l;
00342 TRegexp re(basename,kTRUE);
00343 while ((file = gSystem->GetDirEntry(dir))) {
00344 if (!strcmp(file,".") || !strcmp(file,"..")) continue;
00345 TString s = file;
00346 if ( (basename!=file) && s.Index(re) == kNPOS) continue;
00347 l.Add(new TObjString(file));
00348 }
00349 gSystem->FreeDirectory(dir);
00350
00351 l.Sort();
00352 TIter next(&l);
00353 TObjString *obj;
00354 while ((obj = (TObjString*)next())) {
00355 file = obj->GetName();
00356 if (behind_dot_root.Length() != 0)
00357 nf += AddFile(Form("%s/%s/%s",directory.Data(),file,behind_dot_root.Data()),nentries);
00358 else
00359 nf += AddFile(Form("%s/%s",directory.Data(),file),nentries);
00360 }
00361 l.Delete();
00362 }
00363 if (fProofChain)
00364
00365 ResetBit(kProofUptodate);
00366
00367 return nf;
00368 }
00369
00370
00371 Int_t TChain::AddFile(const char* name, Long64_t nentries , const char* tname )
00372 {
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 const char *treename = GetName();
00418 if (tname && strlen(tname) > 0) treename = tname;
00419 char *dot = 0;
00420 {
00421 char *nextdot = (char*)strstr(name,".root");
00422 while (nextdot) {
00423 dot = nextdot;
00424 nextdot = (char*)strstr(dot+1,".root");
00425 }
00426 }
00427
00428
00429
00430
00431
00432
00433
00434 if (fNtrees+1 >= fTreeOffsetLen) {
00435 fTreeOffsetLen *= 2;
00436 Long64_t *trees = new Long64_t[fTreeOffsetLen];
00437 for (Int_t i=0;i<=fNtrees;i++) trees[i] = fTreeOffset[i];
00438 delete [] fTreeOffset;
00439 fTreeOffset = trees;
00440 }
00441
00442
00443 Int_t nch = strlen(name) + strlen(treename);
00444 char *filename = new char[nch+1];
00445 strlcpy(filename,name,nch+1);
00446 if (dot) {
00447 char *pos = filename + (dot-name) + 5;
00448 while (*pos) {
00449 if (*pos == '/') {
00450 treename = pos+1;
00451 *pos = 0;
00452 break;
00453 }
00454 pos++;
00455 }
00456 }
00457
00458
00459 Int_t pksize = 0;
00460 if (nentries <= 0) {
00461 TFile* file;
00462 {
00463 TDirectory::TContext ctxt(0);
00464 file = TFile::Open(filename);
00465 }
00466 if (!file || file->IsZombie()) {
00467 delete file;
00468 file = 0;
00469 delete[] filename;
00470 filename = 0;
00471 return 0;
00472 }
00473
00474
00475
00476 TObject* obj = file->Get(treename);
00477 if (!obj || !obj->InheritsFrom(TTree::Class())) {
00478 Error("AddFile", "cannot find tree with name %s in file %s", treename, filename);
00479 delete file;
00480 file = 0;
00481 delete[] filename;
00482 filename = 0;
00483 return 0;
00484 }
00485 TTree* tree = (TTree*) obj;
00486 nentries = tree->GetEntries();
00487 pksize = tree->GetPacketSize();
00488
00489 delete file;
00490 file = 0;
00491 }
00492
00493 if (nentries > 0) {
00494 if (nentries != kBigNumber) {
00495 fTreeOffset[fNtrees+1] = fTreeOffset[fNtrees] + nentries;
00496 fEntries += nentries;
00497 } else {
00498 fTreeOffset[fNtrees+1] = theBigNumber;
00499 fEntries = nentries;
00500 }
00501 fNtrees++;
00502
00503 TChainElement* element = new TChainElement(treename, filename);
00504 element->SetPacketSize(pksize);
00505 element->SetNumberEntries(nentries);
00506 fFiles->Add(element);
00507 } else {
00508 Warning("AddFile", "Adding tree with no entries from file: %s", filename);
00509 }
00510
00511 delete [] filename;
00512 if (fProofChain)
00513
00514 ResetBit(kProofUptodate);
00515
00516 return 1;
00517 }
00518
00519
00520 Int_t TChain::AddFileInfoList(TCollection* filelist, Long64_t nfiles )
00521 {
00522
00523
00524
00525 if (!filelist)
00526 return 0;
00527 TIter next(filelist);
00528
00529 TObject *o = 0;
00530 Long64_t cnt=0;
00531 while ((o = next())) {
00532
00533 TString cn = o->ClassName();
00534 const char *url = 0;
00535 if (cn == "TFileInfo") {
00536 TFileInfo *fi = (TFileInfo *)o;
00537 url = (fi->GetCurrentUrl()) ? fi->GetCurrentUrl()->GetUrl() : 0;
00538 if (!url) {
00539 Warning("AddFileInfoList", "found TFileInfo with empty Url - ignoring");
00540 continue;
00541 }
00542 } else if (cn == "TUrl") {
00543 url = ((TUrl*)o)->GetUrl();
00544 } else if (cn == "TObjString") {
00545 url = ((TObjString*)o)->GetName();
00546 }
00547 if (!url) {
00548 Warning("AddFileInfoList", "object is of type %s : expecting TFileInfo, TUrl"
00549 " or TObjString - ignoring", o->ClassName());
00550 continue;
00551 }
00552
00553 cnt++;
00554 AddFile(url);
00555 if (cnt >= nfiles)
00556 break;
00557 }
00558 if (fProofChain) {
00559
00560 ResetBit(kProofUptodate);
00561 }
00562
00563 return 1;
00564 }
00565
00566
00567 TFriendElement* TChain::AddFriend(const char* chain, const char* dummy )
00568 {
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 if (!fFriends) {
00616 fFriends = new TList();
00617 }
00618 TFriendElement* fe = new TFriendElement(this, chain, dummy);
00619
00620 R__ASSERT(fe);
00621
00622 fFriends->Add(fe);
00623
00624 if (fProofChain)
00625
00626 ResetBit(kProofUptodate);
00627
00628
00629
00630 fTreeNumber = -1;
00631
00632 TTree* tree = fe->GetTree();
00633 if (!tree) {
00634 Warning("AddFriend", "Unknown TChain %s", chain);
00635 }
00636 return fe;
00637 }
00638
00639
00640 TFriendElement* TChain::AddFriend(const char* chain, TFile* dummy)
00641 {
00642
00643
00644 if (!fFriends) fFriends = new TList();
00645 TFriendElement *fe = new TFriendElement(this,chain,dummy);
00646
00647 R__ASSERT(fe);
00648
00649 fFriends->Add(fe);
00650
00651 if (fProofChain)
00652
00653 ResetBit(kProofUptodate);
00654
00655
00656
00657 fTreeNumber = -1;
00658
00659 TTree *t = fe->GetTree();
00660 if (!t) {
00661 Warning("AddFriend","Unknown TChain %s",chain);
00662 }
00663 return fe;
00664 }
00665
00666
00667 TFriendElement* TChain::AddFriend(TTree* chain, const char* alias, Bool_t )
00668 {
00669
00670
00671 if (!fFriends) fFriends = new TList();
00672 TFriendElement *fe = new TFriendElement(this,chain,alias);
00673 R__ASSERT(fe);
00674
00675 fFriends->Add(fe);
00676
00677 if (fProofChain)
00678
00679 ResetBit(kProofUptodate);
00680
00681
00682
00683 fTreeNumber = -1;
00684
00685 TTree *t = fe->GetTree();
00686 if (!t) {
00687 Warning("AddFriend","Unknown TChain %s",chain->GetName());
00688 }
00689 return fe;
00690 }
00691
00692
00693 void TChain::Browse(TBrowser* b)
00694 {
00695
00696
00697 TTree::Browse(b);
00698 }
00699
00700
00701 void TChain::CanDeleteRefs(Bool_t flag )
00702 {
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715 fCanDeleteRefs = flag;
00716 }
00717
00718
00719 void TChain::CreatePackets()
00720 {
00721
00722
00723 TIter next(fFiles);
00724 TChainElement* element = 0;
00725 while ((element = (TChainElement*) next())) {
00726 element->CreatePackets();
00727 }
00728 }
00729
00730
00731 void TChain::DirectoryAutoAdd(TDirectory * )
00732 {
00733
00734
00735
00736 }
00737
00738
00739 Long64_t TChain::Draw(const char* varexp, const TCut& selection,
00740 Option_t* option, Long64_t nentries, Long64_t firstentry)
00741 {
00742
00743
00744
00745
00746
00747
00748
00749 if (fProofChain) {
00750
00751 if (!TestBit(kProofUptodate))
00752 SetProof(kTRUE, kTRUE);
00753 fProofChain->SetEventList(fEventList);
00754 fProofChain->SetEntryList(fEntryList);
00755 return fProofChain->Draw(varexp, selection, option, nentries, firstentry);
00756 }
00757
00758 return TChain::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
00759 }
00760
00761
00762 Long64_t TChain::Draw(const char* varexp, const char* selection,
00763 Option_t* option,Long64_t nentries, Long64_t firstentry)
00764 {
00765
00766
00767
00768
00769 if (fProofChain) {
00770
00771 if (!TestBit(kProofUptodate))
00772 SetProof(kTRUE, kTRUE);
00773 fProofChain->SetEventList(fEventList);
00774 fProofChain->SetEntryList(fEntryList);
00775 return fProofChain->Draw(varexp, selection, option, nentries, firstentry);
00776 }
00777 GetPlayer();
00778 if (LoadTree(firstentry) < 0) return 0;
00779 return TTree::Draw(varexp,selection,option,nentries,firstentry);
00780 }
00781
00782
00783 TBranch* TChain::FindBranch(const char* branchname)
00784 {
00785
00786
00787 if (fProofChain && !(fProofChain->TestBit(kProofLite))) {
00788
00789 if (!TestBit(kProofUptodate))
00790 SetProof(kTRUE, kTRUE);
00791 return fProofChain->FindBranch(branchname);
00792 }
00793 if (fTree) {
00794 return fTree->FindBranch(branchname);
00795 }
00796 LoadTree(0);
00797 if (fTree) {
00798 return fTree->FindBranch(branchname);
00799 }
00800 return 0;
00801 }
00802
00803
00804 TLeaf* TChain::FindLeaf(const char* searchname)
00805 {
00806
00807
00808 if (fProofChain && !(fProofChain->TestBit(kProofLite))) {
00809
00810 if (!TestBit(kProofUptodate))
00811 SetProof(kTRUE, kTRUE);
00812 return fProofChain->FindLeaf(searchname);
00813 }
00814 if (fTree) {
00815 return fTree->FindLeaf(searchname);
00816 }
00817 LoadTree(0);
00818 if (fTree) {
00819 return fTree->FindLeaf(searchname);
00820 }
00821 return 0;
00822 }
00823
00824
00825 const char* TChain::GetAlias(const char* aliasName) const
00826 {
00827
00828
00829 const char* alias = TTree::GetAlias(aliasName);
00830 if (alias) {
00831 return alias;
00832 }
00833 if (fTree) {
00834 return fTree->GetAlias(aliasName);
00835 }
00836 const_cast<TChain*>(this)->LoadTree(0);
00837 if (fTree) {
00838 return fTree->GetAlias(aliasName);
00839 }
00840 return 0;
00841 }
00842
00843
00844 TBranch* TChain::GetBranch(const char* name)
00845 {
00846
00847
00848 if (fProofChain && !(fProofChain->TestBit(kProofLite))) {
00849
00850 if (!TestBit(kProofUptodate))
00851 SetProof(kTRUE, kTRUE);
00852 return fProofChain->GetBranch(name);
00853 }
00854 if (fTree) {
00855 return fTree->GetBranch(name);
00856 }
00857 LoadTree(0);
00858 if (fTree) {
00859 return fTree->GetBranch(name);
00860 }
00861 return 0;
00862 }
00863
00864
00865 Bool_t TChain::GetBranchStatus(const char* branchname) const
00866 {
00867
00868 if (fProofChain && !(fProofChain->TestBit(kProofLite))) {
00869
00870 if (!TestBit(kProofUptodate))
00871 Warning("GetBranchStatus", "PROOF proxy not up-to-date:"
00872 " run TChain::SetProof(kTRUE, kTRUE) first");
00873 return fProofChain->GetBranchStatus(branchname);
00874 }
00875 return TTree::GetBranchStatus(branchname);
00876 }
00877
00878
00879 Long64_t TChain::GetChainEntryNumber(Long64_t entry) const
00880 {
00881
00882
00883
00884
00885 return entry + fTreeOffset[fTreeNumber];
00886 }
00887
00888
00889 Long64_t TChain::GetEntries() const
00890 {
00891
00892
00893
00894
00895 if (fProofChain && !(fProofChain->TestBit(kProofLite))) {
00896
00897 if (!TestBit(kProofUptodate))
00898 Warning("GetEntries", "PROOF proxy not up-to-date:"
00899 " run TChain::SetProof(kTRUE, kTRUE) first");
00900 return fProofChain->GetEntries();
00901 }
00902 if (fEntries >= theBigNumber || fEntries==kBigNumber) {
00903 const_cast<TChain*>(this)->LoadTree(theBigNumber-1);
00904 }
00905 return fEntries;
00906 }
00907
00908
00909 Int_t TChain::GetEntry(Long64_t entry, Int_t getall)
00910 {
00911
00912
00913
00914
00915
00916
00917
00918
00919 Long64_t treeReadEntry = LoadTree(entry);
00920 if (treeReadEntry < 0) {
00921 return 0;
00922 }
00923 if (!fTree) {
00924 return 0;
00925 }
00926 return fTree->GetEntry(treeReadEntry, getall);
00927 }
00928
00929
00930 Long64_t TChain::GetEntryNumber(Long64_t entry) const
00931 {
00932
00933
00934
00935
00936
00937
00938
00939 if (fEntryList){
00940 Int_t treenum = 0;
00941 Long64_t localentry = fEntryList->GetEntryAndTree(entry, treenum);
00942
00943
00944 if (localentry<0) return -1;
00945 if (treenum != fTreeNumber){
00946 if (fTreeOffset[treenum]==theBigNumber){
00947 for (Int_t i=0; i<=treenum; i++){
00948 if (fTreeOffset[i]==theBigNumber)
00949 (const_cast<TChain*>(this))->LoadTree(fTreeOffset[i-1]);
00950 }
00951 }
00952
00953 }
00954 Long64_t globalentry = fTreeOffset[treenum] + localentry;
00955 return globalentry;
00956 }
00957 return entry;
00958 }
00959
00960
00961 Int_t TChain::GetEntryWithIndex(Int_t major, Int_t minor)
00962 {
00963
00964
00965
00966
00967
00968
00969
00970
00971 Long64_t serial = GetEntryNumberWithIndex(major, minor);
00972 if (serial < 0) return -1;
00973 return GetEntry(serial);
00974 }
00975
00976
00977 TFile* TChain::GetFile() const
00978 {
00979
00980
00981
00982 if (fFile) {
00983 return fFile;
00984 }
00985
00986 const_cast<TChain*>(this)->LoadTree(0);
00987 return fFile;
00988 }
00989
00990
00991 TLeaf* TChain::GetLeaf(const char* name)
00992 {
00993
00994
00995 if (fProofChain && !(fProofChain->TestBit(kProofLite))) {
00996
00997 if (!TestBit(kProofUptodate))
00998 SetProof(kTRUE, kTRUE);
00999 return fProofChain->GetLeaf(name);
01000 }
01001 if (fTree) {
01002 return fTree->GetLeaf(name);
01003 }
01004 LoadTree(0);
01005 if (fTree) {
01006 return fTree->GetLeaf(name);
01007 }
01008 return 0;
01009 }
01010
01011
01012 TObjArray* TChain::GetListOfBranches()
01013 {
01014
01015
01016
01017
01018
01019
01020
01021 if (fProofChain && !(fProofChain->TestBit(kProofLite))) {
01022
01023 if (!TestBit(kProofUptodate))
01024 SetProof(kTRUE, kTRUE);
01025 return fProofChain->GetListOfBranches();
01026 }
01027 if (fTree) {
01028 return fTree->GetListOfBranches();
01029 }
01030 LoadTree(0);
01031 if (fTree) {
01032 return fTree->GetListOfBranches();
01033 }
01034 return 0;
01035 }
01036
01037
01038 TObjArray* TChain::GetListOfLeaves()
01039 {
01040
01041
01042
01043
01044
01045 if (fProofChain && !(fProofChain->TestBit(kProofLite))) {
01046
01047 if (!TestBit(kProofUptodate))
01048 SetProof(kTRUE, kTRUE);
01049 return fProofChain->GetListOfLeaves();
01050 }
01051 if (fTree) {
01052 return fTree->GetListOfLeaves();
01053 }
01054 LoadTree(0);
01055 if (fTree) {
01056 return fTree->GetListOfLeaves();
01057 }
01058 return 0;
01059 }
01060
01061
01062 Double_t TChain::GetMaximum(const char* columname)
01063 {
01064
01065
01066 Double_t theMax = -FLT_MAX;
01067 for (Int_t file = 0; file < fNtrees; file++) {
01068 Long64_t first = fTreeOffset[file];
01069 LoadTree(first);
01070 Double_t curmax = fTree->GetMaximum(columname);
01071 if (curmax > theMax) {
01072 theMax = curmax;
01073 }
01074 }
01075 return theMax;
01076 }
01077
01078
01079 Double_t TChain::GetMinimum(const char* columname)
01080 {
01081
01082
01083 Double_t theMin = FLT_MAX;
01084 for (Int_t file = 0; file < fNtrees; file++) {
01085 Long64_t first = fTreeOffset[file];
01086 LoadTree(first);
01087 Double_t curmin = fTree->GetMinimum(columname);
01088 if (curmin < theMin) {
01089 theMin = curmin;
01090 }
01091 }
01092 return theMin;
01093 }
01094
01095
01096 Int_t TChain::GetNbranches()
01097 {
01098
01099
01100
01101
01102
01103 if (fTree) {
01104 return fTree->GetNbranches();
01105 }
01106 LoadTree(0);
01107 if (fTree) {
01108 return fTree->GetNbranches();
01109 }
01110 return 0;
01111 }
01112
01113
01114 Long64_t TChain::GetReadEntry() const
01115 {
01116
01117
01118 if (fProofChain && !(fProofChain->TestBit(kProofLite))) {
01119
01120 if (!TestBit(kProofUptodate))
01121 Warning("GetBranchStatus", "PROOF proxy not up-to-date:"
01122 " run TChain::SetProof(kTRUE, kTRUE) first");
01123 return fProofChain->GetReadEntry();
01124 }
01125 return TTree::GetReadEntry();
01126 }
01127
01128
01129 Double_t TChain::GetWeight() const
01130 {
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140 if (TestBit(kGlobalWeight)) {
01141 return fWeight;
01142 } else {
01143 if (fTree) {
01144 return fTree->GetWeight();
01145 }
01146 const_cast<TChain*>(this)->LoadTree(0);
01147 if (fTree) {
01148 return fTree->GetWeight();
01149 }
01150 return 0;
01151 }
01152 }
01153
01154
01155 Int_t TChain::LoadBaskets(Long64_t )
01156 {
01157
01158
01159
01160
01161
01162 Error("LoadBaskets", "Function not yet implemented for TChain.");
01163 return 0;
01164 }
01165
01166
01167 Long64_t TChain::LoadTree(Long64_t entry)
01168 {
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181 if (kLoadTree & fFriendLockStatus) {
01182 return 0;
01183 }
01184
01185 if (!fNtrees) {
01186
01187 return 1;
01188 }
01189
01190 if ((entry < 0) || ((entry > 0) && (entry >= fEntries && entry!=(theBigNumber-1) ))) {
01191
01192 if (fTree) fTree->LoadTree(-1);
01193 fReadEntry = -1;
01194 return -2;
01195 }
01196
01197
01198 Int_t treenum = fTreeNumber;
01199 if ((fTreeNumber == -1) || (entry < fTreeOffset[fTreeNumber]) || (entry >= fTreeOffset[fTreeNumber+1]) || (entry==theBigNumber-1)) {
01200
01201
01202
01203
01204
01205 for (treenum = 0; treenum < fNtrees; treenum++) {
01206 if (entry < fTreeOffset[treenum+1]) {
01207 break;
01208 }
01209 }
01210 }
01211
01212
01213 Long64_t treeReadEntry = entry - fTreeOffset[treenum];
01214 fReadEntry = entry;
01215
01216
01217 if (fTree && treenum == fTreeNumber) {
01218
01219
01220
01221 fTree->LoadTree(treeReadEntry);
01222 if (fFriends) {
01223
01224
01225
01226
01227 TIter next(fFriends);
01228 TFriendLock lock(this, kLoadTree);
01229 TFriendElement* fe = 0;
01230 TFriendElement* fetree = 0;
01231 Bool_t needUpdate = kFALSE;
01232 while ((fe = (TFriendElement*) next())) {
01233 TObjLink* lnk = 0;
01234 if (fTree->GetListOfFriends()) {
01235 lnk = fTree->GetListOfFriends()->FirstLink();
01236 }
01237 fetree = 0;
01238 while (lnk) {
01239 TObject* obj = lnk->GetObject();
01240 if (obj->TestBit(TFriendElement::kFromChain) && obj->GetName() && !strcmp(fe->GetName(), obj->GetName())) {
01241 fetree = (TFriendElement*) obj;
01242 break;
01243 }
01244 lnk = lnk->Next();
01245 }
01246 TTree* at = fe->GetTree();
01247 if (at->InheritsFrom(TChain::Class())) {
01248 Int_t oldNumber = ((TChain*) at)->GetTreeNumber();
01249 TTree* old = at->GetTree();
01250 TTree* oldintree = fetree ? fetree->GetTree() : 0;
01251 at->LoadTreeFriend(entry, this);
01252 Int_t newNumber = ((TChain*) at)->GetTreeNumber();
01253 if ((oldNumber != newNumber) || (old != at->GetTree()) || (oldintree && (oldintree != at->GetTree()))) {
01254
01255
01256
01257 needUpdate = kTRUE;
01258 fTree->RemoveFriend(oldintree);
01259 fTree->AddFriend(at->GetTree(), fe->GetName())->SetBit(TFriendElement::kFromChain);
01260 }
01261 } else {
01262
01263
01264
01265
01266 at->LoadTreeFriend(entry, this);
01267 }
01268 }
01269 if (needUpdate) {
01270
01271
01272
01273
01274 TChainElement *frelement;
01275 TIter fnext(fStatus);
01276 while ((frelement = (TChainElement*) fnext())) {
01277 Int_t status = frelement->GetStatus();
01278 fTree->SetBranchStatus(frelement->GetName(), status);
01279 }
01280
01281
01282 fnext.Reset();
01283 while ((frelement = (TChainElement*) fnext())) {
01284 void* addr = frelement->GetBaddress();
01285 if (addr) {
01286 TBranch* br = fTree->GetBranch(frelement->GetName());
01287 TBranch** pp = frelement->GetBranchPtr();
01288 if (pp) {
01289
01290 *pp = br;
01291 }
01292 if (br) {
01293
01294
01295 br->SetAddress(addr);
01296 if (TestBit(kAutoDelete)) {
01297 br->SetAutoDelete(kTRUE);
01298 }
01299 }
01300 }
01301 }
01302 if (fPlayer) {
01303 fPlayer->UpdateFormulaLeaves();
01304 }
01305
01306 if (fNotify) {
01307 fNotify->Notify();
01308 }
01309 }
01310 }
01311 return treeReadEntry;
01312 }
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322 if (fTree && fTree->GetListOfClones()) {
01323 for (TObjLink* lnk = fTree->GetListOfClones()->FirstLink(); lnk; lnk = lnk->Next()) {
01324 TTree* clone = (TTree*) lnk->GetObject();
01325 AddClone(clone);
01326 }
01327 }
01328
01329
01330 TTreeCache* tpf = 0;
01331
01332
01333
01334 if (fFile) {
01335 if (!fDirectory->GetList()->FindObject(this)) {
01336 tpf = (TTreeCache*) fFile->GetCacheRead();
01337 if (tpf) tpf->ResetCache();
01338 fFile->SetCacheRead(0);
01339 if (fCanDeleteRefs) {
01340 fFile->Close("R");
01341 }
01342 delete fFile;
01343 fFile = 0;
01344
01345 fTree = 0;
01346 }
01347 }
01348
01349 TChainElement* element = (TChainElement*) fFiles->At(treenum);
01350 if (!element) {
01351 if (treeReadEntry) {
01352 return -4;
01353 }
01354
01355 element = (TChainElement*) fFiles->At(0);
01356 if (!element) {
01357 return -4;
01358 }
01359 }
01360
01361
01362
01363 {
01364 TDirectory::TContext ctxt(0);
01365 fFile = TFile::Open(element->GetTitle());
01366 if (fFile) fFile->SetBit(kMustCleanup);
01367 }
01368
01369
01370 Int_t returnCode = 0;
01371 if (!fFile || fFile->IsZombie()) {
01372 if (fFile) {
01373 delete fFile;
01374 fFile = 0;
01375 }
01376
01377 fTree = 0;
01378 returnCode = -3;
01379 } else {
01380
01381 fTree = (TTree*) fFile->Get(element->GetName());
01382 if (!fTree) {
01383
01384 Error("LoadTree", "Cannot find tree with name %s in file %s", element->GetName(), element->GetTitle());
01385 delete fFile;
01386 fFile = 0;
01387
01388
01389 returnCode = -4;
01390 }
01391 }
01392
01393 fTreeNumber = treenum;
01394
01395
01396 fDirectory = fFile;
01397
01398
01399 if (tpf) {
01400 if (fFile) {
01401 tpf->ResetCache();
01402 fFile->SetCacheRead(tpf);
01403 tpf->SetFile(fFile);
01404
01405 tpf->UpdateBranches(fTree);
01406 } else {
01407
01408
01409
01410 delete tpf;
01411 tpf = 0;
01412 this->SetCacheSize(fCacheSize);
01413 }
01414 } else {
01415 this->SetCacheSize(fCacheSize);
01416 }
01417
01418
01419 Long64_t nentries = 0;
01420 if (fTree) {
01421 nentries = fTree->GetEntries();
01422 }
01423
01424 if (fTreeOffset[fTreeNumber+1] != (fTreeOffset[fTreeNumber] + nentries)) {
01425 fTreeOffset[fTreeNumber+1] = fTreeOffset[fTreeNumber] + nentries;
01426 fEntries = fTreeOffset[fNtrees];
01427 element->SetNumberEntries(nentries);
01428
01429 if (entry >= fTreeOffset[fTreeNumber+1]) {
01430 if ((fTreeNumber < (fNtrees - 1)) && (entry < fTreeOffset[fTreeNumber+2])) {
01431 return LoadTree(entry);
01432 } else {
01433 treeReadEntry = fReadEntry = -2;
01434 }
01435 }
01436 }
01437
01438 if (!fTree) {
01439
01440
01441
01442
01443 fTreeNumber = -1;
01444 return returnCode;
01445 }
01446
01447
01448
01449
01450 if (fClones) {
01451 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
01452 TTree* clone = (TTree*) lnk->GetObject();
01453 ((TChain*) fTree)->TTree::AddClone(clone);
01454 }
01455 }
01456
01457
01458
01459
01460
01461
01462
01463 fTree->LoadTree(treeReadEntry);
01464
01465
01466 if (fFriends) {
01467
01468
01469 TIter next(fFriends);
01470 TFriendLock lock(this, kLoadTree);
01471 TFriendElement* fe = 0;
01472 while ((fe = (TFriendElement*) next())) {
01473 TTree* t = fe->GetTree();
01474 if (!t) continue;
01475 if (t->GetTreeIndex()) {
01476 t->GetTreeIndex()->UpdateFormulaLeaves(0);
01477 }
01478 if (t->GetTree() && t->GetTree()->GetTreeIndex()) {
01479 t->GetTree()->GetTreeIndex()->UpdateFormulaLeaves(GetTree());
01480 }
01481 t->LoadTreeFriend(entry, this);
01482 TTree* friend_t = t->GetTree();
01483 if (friend_t) {
01484 fTree->AddFriend(friend_t, fe->GetName())->SetBit(TFriendElement::kFromChain);
01485 }
01486 }
01487 }
01488
01489 fTree->SetMakeClass(fMakeClass);
01490 fTree->SetMaxVirtualSize(fMaxVirtualSize);
01491
01492 SetChainOffset(fTreeOffset[fTreeNumber]);
01493
01494
01495 TIter next(fStatus);
01496 while ((element = (TChainElement*) next())) {
01497 Int_t status = element->GetStatus();
01498 fTree->SetBranchStatus(element->GetName(), status);
01499 }
01500
01501
01502 next.Reset();
01503 while ((element = (TChainElement*) next())) {
01504 void* addr = element->GetBaddress();
01505 if (addr) {
01506 TBranch* br = fTree->GetBranch(element->GetName());
01507 TBranch** pp = element->GetBranchPtr();
01508 if (pp) {
01509
01510 *pp = br;
01511 }
01512 if (br) {
01513
01514
01515 br->SetAddress(addr);
01516 if (TestBit(kAutoDelete)) {
01517 br->SetAutoDelete(kTRUE);
01518 }
01519 }
01520 }
01521 }
01522
01523
01524 if (fClones) {
01525 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
01526 TTree* clone = (TTree*) lnk->GetObject();
01527 CopyAddresses(clone);
01528 }
01529 }
01530
01531
01532 if (fPlayer) {
01533 fPlayer->UpdateFormulaLeaves();
01534 }
01535
01536
01537 if (fNotify) {
01538 fNotify->Notify();
01539 }
01540
01541
01542 return treeReadEntry;
01543 }
01544
01545
01546 void TChain::Lookup(Bool_t force)
01547 {
01548
01549
01550
01551
01552 TIter next(fFiles);
01553 TChainElement* element = 0;
01554 Int_t nelements = fFiles->GetEntries();
01555 printf("\n");
01556 printf("TChain::Lookup - Looking up %d files .... \n", nelements);
01557 Int_t nlook = 0;
01558 TFileStager *stg = 0;
01559 while ((element = (TChainElement*) next())) {
01560
01561 if (element->HasBeenLookedUp() && !force) continue;
01562
01563 nlook++;
01564
01565 TUrl elemurl(element->GetTitle(), kTRUE);
01566
01567 TString anchor = elemurl.GetAnchor();
01568 TString options = elemurl.GetOptions();
01569
01570 elemurl.SetOptions("");
01571 elemurl.SetAnchor("");
01572
01573 TString eurl(elemurl.GetUrl());
01574 if (!stg || !stg->Matches(eurl)) {
01575 SafeDelete(stg);
01576 {
01577 TDirectory::TContext ctxt(0);
01578 stg = TFileStager::Open(eurl);
01579 }
01580 if (!stg) {
01581 Error("Lookup", "TFileStager instance cannot be instantiated");
01582 break;
01583 }
01584 }
01585 Int_t n1 = (nelements > 100) ? (Int_t) nelements / 100 : 1;
01586 if (stg->Locate(eurl.Data(), eurl) == 0) {
01587 if (nlook > 0 && !(nlook % n1)) {
01588 printf("Lookup | %3d %% finished\r", 100 * nlook / nelements);
01589 fflush(stdout);
01590 }
01591
01592 elemurl.SetUrl(eurl);
01593
01594 elemurl.SetOptions(options);
01595 elemurl.SetAnchor(anchor);
01596
01597 element->SetTitle(elemurl.GetUrl());
01598
01599 element->SetLookedUp();
01600 } else {
01601
01602 fFiles->Remove(element);
01603 if (gSystem->AccessPathName(eurl))
01604 Error("Lookup", "file %s does not exist\n", eurl.Data());
01605 else
01606 Error("Lookup", "file %s cannot be read\n", eurl.Data());
01607 }
01608 }
01609 if (nelements > 0)
01610 printf("Lookup | %3d %% finished\n", 100 * nlook / nelements);
01611 else
01612 printf("\n");
01613 fflush(stdout);
01614 SafeDelete(stg);
01615 }
01616
01617
01618 void TChain::Loop(Option_t* option, Long64_t nentries, Long64_t firstentry)
01619 {
01620
01621
01622 Error("Loop", "Function not yet implemented");
01623
01624 if (option || nentries || firstentry) { }
01625
01626 #if 0
01627 if (LoadTree(firstentry) < 0) return;
01628
01629 if (firstentry < 0) firstentry = 0;
01630 Long64_t lastentry = firstentry + nentries -1;
01631 if (lastentry > fEntries-1) {
01632 lastentry = fEntries -1;
01633 }
01634
01635 GetPlayer();
01636 GetSelector();
01637 fSelector->Start(option);
01638
01639 Long64_t entry = firstentry;
01640 Int_t tree,e0,en;
01641 for (tree=0;tree<fNtrees;tree++) {
01642 e0 = fTreeOffset[tree];
01643 en = fTreeOffset[tree+1] - 1;
01644 if (en > lastentry) en = lastentry;
01645 if (entry > en) continue;
01646
01647 LoadTree(entry);
01648 fSelector->BeginFile();
01649
01650 while (entry <= en) {
01651 fSelector->Execute(fTree, entry - e0);
01652 entry++;
01653 }
01654 fSelector->EndFile();
01655 }
01656
01657 fSelector->Finish(option);
01658 #endif
01659 }
01660
01661
01662 void TChain::ls(Option_t* option) const
01663 {
01664
01665 TIter next(fFiles);
01666 TChainElement* file = 0;
01667 while ((file = (TChainElement*)next())) {
01668 file->ls(option);
01669 }
01670 }
01671
01672
01673 Long64_t TChain::Merge(const char* name, Option_t* option)
01674 {
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695 TFile *file = TFile::Open(name, "recreate", "chain files", 1);
01696 return Merge(file, 0, option);
01697 }
01698
01699
01700 Long64_t TChain::Merge(TCollection* , Option_t* )
01701 {
01702
01703
01704 Error("Merge", "not implemented");
01705 return -1;
01706 }
01707
01708
01709 Long64_t TChain::Merge(TFile* file, Int_t basketsize, Option_t* option)
01710 {
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811 if (!file) {
01812
01813 return 0;
01814 }
01815
01816
01817 Bool_t fastClone = kFALSE;
01818 TString opt = option;
01819 opt.ToLower();
01820 if (opt.Contains("fast")) {
01821 fastClone = kTRUE;
01822 }
01823
01824
01825
01826
01827 TObjArray* lbranches = GetListOfBranches();
01828 if (!lbranches) {
01829
01830 return 0;
01831 }
01832
01833
01834
01835 if (!fTree) {
01836
01837
01838 return 0;
01839 }
01840
01841
01842
01843 TTree* newTree = CloneTree(0);
01844 if (!newTree) {
01845
01846 return 0;
01847 }
01848
01849
01850
01851
01852
01853
01854 newTree->SetName(gSystem->BaseName(GetName()));
01855
01856
01857 newTree->SetAutoSave(2000000000);
01858
01859
01860
01861
01862 newTree->SetCircular(0);
01863
01864
01865 if (opt.Contains("c")) {
01866 TBranch* branch = 0;
01867 TIter nextb(newTree->GetListOfBranches());
01868 while ((branch = (TBranch*) nextb())) {
01869 branch->SetCompressionLevel(file->GetCompressionLevel());
01870 }
01871 }
01872
01873
01874 if (basketsize > 1000) {
01875 TBranch* branch = 0;
01876 TIter nextb(newTree->GetListOfBranches());
01877 while ((branch = (TBranch*) nextb())) {
01878 branch->SetBasketSize(basketsize);
01879 }
01880 }
01881
01882
01883 if (fastClone) {
01884 if ( newTree->CopyEntries( this, -1, option ) < 0 ) {
01885
01886 Error("Merge", "TTree has not been cloned\n");
01887 }
01888 } else {
01889 newTree->CopyEntries( this, -1, option );
01890 }
01891
01892
01893 newTree->Write();
01894
01895
01896 Int_t nfiles = newTree->GetFileNumber() + 1;
01897
01898
01899 if (!opt.Contains("keep")) {
01900
01901 delete newTree->GetCurrentFile();
01902 }
01903 return nfiles;
01904 }
01905
01906
01907 void TChain::Print(Option_t *option) const
01908 {
01909
01910
01911
01912 TIter next(fFiles);
01913 TChainElement *element;
01914 while ((element = (TChainElement*)next())) {
01915 TFile *file = TFile::Open(element->GetTitle());
01916 if (file && !file->IsZombie()) {
01917 TTree *tree = (TTree*)file->Get(element->GetName());
01918 if (tree) tree->Print(option);
01919 }
01920 delete file;
01921 }
01922 }
01923
01924
01925 Long64_t TChain::Process(const char *filename, Option_t *option, Long64_t nentries, Long64_t firstentry)
01926 {
01927
01928
01929
01930
01931
01932 if (fProofChain) {
01933
01934 if (!TestBit(kProofUptodate))
01935 SetProof(kTRUE, kTRUE);
01936 fProofChain->SetEventList(fEventList);
01937 fProofChain->SetEntryList(fEntryList);
01938 return fProofChain->Process(filename, option, nentries, firstentry);
01939 }
01940
01941 if (LoadTree(firstentry) < 0) {
01942 return 0;
01943 }
01944 return TTree::Process(filename, option, nentries, firstentry);
01945 }
01946
01947
01948 Long64_t TChain::Process(TSelector* selector, Option_t* option, Long64_t nentries, Long64_t firstentry)
01949 {
01950
01951
01952
01953
01954 if (fProofChain) {
01955
01956 if (!TestBit(kProofUptodate))
01957 SetProof(kTRUE, kTRUE);
01958 fProofChain->SetEventList(fEventList);
01959 fProofChain->SetEntryList(fEntryList);
01960 return fProofChain->Process(selector, option, nentries, firstentry);
01961 }
01962
01963 return TTree::Process(selector, option, nentries, firstentry);
01964 }
01965
01966
01967 void TChain::RecursiveRemove(TObject *obj)
01968 {
01969
01970
01971
01972 if (fFile == obj) {
01973 fFile = 0;
01974 fDirectory = 0;
01975 fTree = 0;
01976 }
01977 if (fDirectory == obj) {
01978 fDirectory = 0;
01979 fTree = 0;
01980 }
01981 if (fTree == obj) {
01982 fTree = 0;
01983 }
01984 }
01985
01986
01987 void TChain::Reset(Option_t*)
01988 {
01989
01990
01991 delete fFile;
01992 fFile = 0;
01993 fNtrees = 0;
01994 fTreeNumber = -1;
01995 fTree = 0;
01996 fFile = 0;
01997 fFiles->Delete();
01998 fStatus->Delete();
01999 fTreeOffset[0] = 0;
02000 TChainElement* element = new TChainElement("*", "");
02001 fStatus->Add(element);
02002 fDirectory = 0;
02003
02004 TTree::Reset();
02005 }
02006
02007
02008 Long64_t TChain::Scan(const char* varexp, const char* selection, Option_t* option, Long64_t nentries, Long64_t firstentry)
02009 {
02010
02011
02012
02013
02014
02015
02016 if (LoadTree(firstentry) < 0) {
02017 return 0;
02018 }
02019 return TTree::Scan(varexp, selection, option, nentries, firstentry);
02020 }
02021
02022
02023 void TChain::SetAutoDelete(Bool_t autodelete)
02024 {
02025
02026
02027
02028
02029
02030
02031 if (autodelete) {
02032 SetBit(kAutoDelete, 1);
02033 } else {
02034 SetBit(kAutoDelete, 0);
02035 }
02036 }
02037
02038
02039 void TChain::ResetBranchAddress(TBranch *branch)
02040 {
02041
02042
02043 TChainElement* element = (TChainElement*) fStatus->FindObject(branch->GetName());
02044 if (element) {
02045 element->SetBaddress(0);
02046 }
02047 if (fTree) {
02048 fTree->ResetBranchAddress(branch);
02049 }
02050 }
02051
02052
02053 void TChain::ResetBranchAddresses()
02054 {
02055
02056
02057 TIter next(fStatus);
02058 TChainElement* element = 0;
02059 while ((element = (TChainElement*) next())) {
02060 element->SetBaddress(0);
02061 }
02062 if (fTree) {
02063 fTree->ResetBranchAddresses();
02064 }
02065 }
02066
02067
02068 Int_t TChain::SetBranchAddress(const char *bname, void* add, TBranch** ptr)
02069 {
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084 Int_t res = kNoCheck;
02085
02086
02087
02088 TChainElement* element = (TChainElement*) fStatus->FindObject(bname);
02089 if (!element) {
02090 element = new TChainElement(bname, "");
02091 fStatus->Add(element);
02092 }
02093 element->SetBaddress(add);
02094 element->SetBranchPtr(ptr);
02095
02096
02097 if (fTreeNumber >= 0) {
02098 TBranch* branch = fTree->GetBranch(bname);
02099 if (ptr) {
02100 *ptr = branch;
02101 }
02102 if (branch) {
02103 res = CheckBranchAddressType(branch, TClass::GetClass(element->GetBaddressClassName()), (EDataType) element->GetBaddressType(), element->GetBaddressIsPtr());
02104 if (fClones) {
02105 void* oldAdd = branch->GetAddress();
02106 for (TObjLink* lnk = fClones->FirstLink(); lnk; lnk = lnk->Next()) {
02107 TTree* clone = (TTree*) lnk->GetObject();
02108 TBranch* cloneBr = clone->GetBranch(bname);
02109 if (cloneBr && (cloneBr->GetAddress() == oldAdd)) {
02110
02111 cloneBr->SetAddress(add);
02112 }
02113 }
02114 }
02115 branch->SetAddress(add);
02116 }
02117 } else {
02118 if (ptr) {
02119 *ptr = 0;
02120 }
02121 }
02122 return res;
02123 }
02124
02125
02126 Int_t TChain::SetBranchAddress(const char* bname, void* add, TClass* realClass, EDataType datatype, Bool_t isptr)
02127 {
02128
02129
02130
02131
02132
02133
02134 return SetBranchAddress(bname, add, 0, realClass, datatype, isptr);
02135 }
02136
02137
02138 Int_t TChain::SetBranchAddress(const char* bname, void* add, TBranch** ptr, TClass* realClass, EDataType datatype, Bool_t isptr)
02139 {
02140
02141
02142
02143
02144
02145
02146
02147 TChainElement* element = (TChainElement*) fStatus->FindObject(bname);
02148 if (!element) {
02149 element = new TChainElement(bname, "");
02150 fStatus->Add(element);
02151 }
02152 if (realClass) {
02153 element->SetBaddressClassName(realClass->GetName());
02154 }
02155 element->SetBaddressType((UInt_t) datatype);
02156 element->SetBaddressIsPtr(isptr);
02157 element->SetBranchPtr(ptr);
02158 return SetBranchAddress(bname, add, ptr);
02159 }
02160
02161
02162 void TChain::SetBranchStatus(const char* bname, Bool_t status, UInt_t* found)
02163 {
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179 TChainElement* element = (TChainElement*) fStatus->FindObject(bname);
02180 if (element) {
02181 fStatus->Remove(element);
02182 } else {
02183 element = new TChainElement(bname, "");
02184 }
02185 fStatus->Add(element);
02186 element->SetStatus(status);
02187
02188 if (fTreeNumber >= 0) {
02189 fTree->SetBranchStatus(bname, status, found);
02190 } else if (found) {
02191 *found = 1;
02192 }
02193 }
02194
02195
02196 void TChain::SetDirectory(TDirectory* dir)
02197 {
02198
02199
02200
02201
02202 if (fDirectory == dir) return;
02203 if (fDirectory) fDirectory->Remove(this);
02204 fDirectory = dir;
02205 if (fDirectory) {
02206 fDirectory->Append(this);
02207 fFile = fDirectory->GetFile();
02208 } else {
02209 fFile = 0;
02210 }
02211 }
02212
02213
02214 void TChain::SetEntryList(TEntryList *elist, Option_t *opt)
02215 {
02216
02217
02218
02219
02220
02221
02222
02223
02224 if (fEntryList){
02225
02226
02227
02228 if (fEntryList->TestBit(kCanDelete)) {
02229 TEntryList *tmp = fEntryList;
02230 fEntryList = 0;
02231 delete tmp;
02232 } else {
02233 fEntryList = 0;
02234 }
02235 }
02236 if (!elist){
02237 fEntryList = 0;
02238 fEventList = 0;
02239 return;
02240 }
02241 if (!elist->TestBit(kCanDelete)){
02242
02243 fEventList = 0;
02244 }
02245 if (elist->GetN() == 0){
02246 fEntryList = elist;
02247 return;
02248 }
02249 if (fProofChain){
02250
02251
02252 fEventList = 0;
02253 fEntryList = elist;
02254 return;
02255 }
02256
02257 Int_t ne = fFiles->GetEntries();
02258 Int_t listfound=0;
02259 TString treename, filename;
02260
02261 TEntryList *templist = 0;
02262 for (Int_t ie = 0; ie<ne; ie++){
02263 treename = gSystem->BaseName( ((TChainElement*)fFiles->UncheckedAt(ie))->GetName() );
02264 filename = ((TChainElement*)fFiles->UncheckedAt(ie))->GetTitle();
02265 templist = elist->GetEntryList(treename.Data(), filename.Data(), opt);
02266 if (templist) {
02267 listfound++;
02268 templist->SetTreeNumber(ie);
02269 }
02270 }
02271
02272 if (listfound == 0){
02273 Error("SetEntryList", "No list found for the trees in this chain");
02274 fEntryList = 0;
02275 return;
02276 }
02277 fEntryList = elist;
02278 TList *elists = elist->GetLists();
02279 Bool_t shift = kFALSE;
02280 TIter next(elists);
02281
02282
02283
02284 while((templist = (TEntryList*)next())){
02285 if (templist->GetTreeNumber() < 0){
02286 shift = kTRUE;
02287 break;
02288 }
02289 }
02290 fEntryList->SetShift(shift);
02291
02292 }
02293
02294
02295 void TChain::SetEntryListFile(const char *filename, Option_t * )
02296 {
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317 if (fEntryList){
02318
02319
02320
02321 if (fEntryList->TestBit(kCanDelete)) {
02322 TEntryList *tmp = fEntryList;
02323 fEntryList = 0;
02324 delete tmp;
02325 } else {
02326 fEntryList = 0;
02327 }
02328 }
02329
02330 fEventList = 0;
02331
02332 TString basename(filename);
02333
02334 Int_t dotslashpos = basename.Index(".root/");
02335 TString behind_dot_root = "";
02336 if (dotslashpos>=0) {
02337
02338 behind_dot_root = basename(dotslashpos+6,basename.Length()-dotslashpos+6);
02339
02340 basename.Remove(dotslashpos+5);
02341 }
02342 fEntryList = new TEntryListFromFile(basename.Data(), behind_dot_root.Data(), fNtrees);
02343 fEntryList->SetBit(kCanDelete, kTRUE);
02344 fEntryList->SetDirectory(0);
02345 ((TEntryListFromFile*)fEntryList)->SetFileNames(fFiles);
02346 }
02347
02348
02349
02350 void TChain::SetEventList(TEventList *evlist)
02351 {
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363 fEventList = evlist;
02364 if (fEntryList) {
02365 if (fEntryList->TestBit(kCanDelete)) {
02366 TEntryList *tmp = fEntryList;
02367 fEntryList = 0;
02368 delete tmp;
02369 } else {
02370 fEntryList = 0;
02371 }
02372 }
02373
02374 if (!evlist) {
02375 fEntryList = 0;
02376 fEventList = 0;
02377 return;
02378 }
02379
02380 if(fProofChain) {
02381
02382 if (fEntryList){
02383
02384
02385
02386 if (fEntryList->TestBit(kCanDelete)){
02387 TEntryList *tmp = fEntryList;
02388 fEntryList = 0;
02389 delete tmp;
02390 } else {
02391 fEntryList = 0;
02392 }
02393 }
02394 return;
02395 }
02396
02397 char enlistname[100];
02398 snprintf(enlistname,100, "%s_%s", evlist->GetName(), "entrylist");
02399 TEntryList *enlist = new TEntryList(enlistname, evlist->GetTitle());
02400 enlist->SetDirectory(0);
02401
02402 Int_t nsel = evlist->GetN();
02403 Long64_t globalentry, localentry;
02404 const char *treename;
02405 const char *filename;
02406 if (fTreeOffset[fNtrees-1]==theBigNumber){
02407
02408
02409
02410 printf("loading trees\n");
02411 (const_cast<TChain*>(this))->LoadTree(evlist->GetEntry(evlist->GetN()-1));
02412 }
02413 for (Int_t i=0; i<nsel; i++){
02414 globalentry = evlist->GetEntry(i);
02415
02416 Int_t treenum = 0;
02417 while (globalentry>=fTreeOffset[treenum])
02418 treenum++;
02419 treenum--;
02420 localentry = globalentry - fTreeOffset[treenum];
02421
02422 treename = ((TNamed*)fFiles->At(treenum))->GetName();
02423 filename = ((TNamed*)fFiles->At(treenum))->GetTitle();
02424
02425 enlist->SetTree(treename, filename);
02426 enlist->Enter(localentry);
02427 }
02428 enlist->SetBit(kCanDelete, kTRUE);
02429 enlist->SetReapplyCut(evlist->GetReapplyCut());
02430 SetEntryList(enlist);
02431 }
02432
02433
02434 void TChain::SetPacketSize(Int_t size)
02435 {
02436
02437
02438 fPacketSize = size;
02439 TIter next(fFiles);
02440 TChainElement *element;
02441 while ((element = (TChainElement*)next())) {
02442 element->SetPacketSize(size);
02443 }
02444 }
02445
02446
02447 void TChain::SetProof(Bool_t on, Bool_t refresh, Bool_t gettreeheader)
02448 {
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459 if (!on) {
02460
02461 SafeDelete(fProofChain);
02462
02463 ResetBit(kProofUptodate);
02464 } else {
02465 if (fProofChain && !refresh &&
02466 (!gettreeheader || (gettreeheader && fProofChain->GetTree()))) {
02467 return;
02468 }
02469 SafeDelete(fProofChain);
02470 ResetBit(kProofUptodate);
02471
02472
02473 TPluginHandler *h;
02474 if ((h = gROOT->GetPluginManager()->FindHandler("TChain", "proof"))) {
02475 if (h->LoadPlugin() == -1)
02476 return;
02477 if (!(fProofChain = reinterpret_cast<TChain *>(h->ExecPlugin(2, this, gettreeheader))))
02478 Error("SetProof", "creation of TProofChain failed");
02479
02480 SetBit(kProofUptodate);
02481 }
02482 }
02483 }
02484
02485
02486 void TChain::SetWeight(Double_t w, Option_t* option)
02487 {
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503 fWeight = w;
02504 TString opt = option;
02505 opt.ToLower();
02506 ResetBit(kGlobalWeight);
02507 if (opt.Contains("global")) {
02508 SetBit(kGlobalWeight);
02509 }
02510 }
02511
02512
02513 void TChain::Streamer(TBuffer& b)
02514 {
02515
02516
02517 if (b.IsReading()) {
02518 UInt_t R__s, R__c;
02519 Version_t R__v = b.ReadVersion(&R__s, &R__c);
02520 if (R__v > 2) {
02521 b.ReadClassBuffer(TChain::Class(), this, R__v, R__s, R__c);
02522 return;
02523 }
02524
02525 TTree::Streamer(b);
02526 b >> fTreeOffsetLen;
02527 b >> fNtrees;
02528 fFiles->Streamer(b);
02529 if (R__v > 1) {
02530 fStatus->Streamer(b);
02531 fTreeOffset = new Long64_t[fTreeOffsetLen];
02532 b.ReadFastArray(fTreeOffset,fTreeOffsetLen);
02533 }
02534 b.CheckByteCount(R__s, R__c, TChain::IsA());
02535
02536
02537 } else {
02538 b.WriteClassBuffer(TChain::Class(),this);
02539 }
02540 }
02541
02542
02543 void TChain::UseCache(Int_t , Int_t )
02544 {
02545
02546
02547 }