#include "TROOT.h"
#include "TClass.h"
#include "TChain.h"
#include "TTree.h"
#include "TCut.h"
#include "TError.h"
#include "TFile.h"
#include "TSelector.h"
#include "TBranch.h"
#include "TLeaf.h"
#include "TBrowser.h"
#include "TChainElement.h"
#include "TFriendElement.h"
#include "TSystem.h"
#include "TRegexp.h"
#include "TObjString.h"
#include "TChainProof.h"
#include "TVirtualProof.h"
#include "TDSet.h"
#include "TError.h"
#include "TVirtualIndex.h"
#include "TFileInfo.h"
#include "TUrl.h"
#include "TTreeCloner.h"
#include "TTreeCache.h"
#include <queue>
#include <map>
ClassImp(TChain)
TChain::TChain(): TTree()
{
fTreeOffsetLen = 100;
fNtrees = 0;
fTreeNumber = -1;
fTreeOffset = new Long64_t[fTreeOffsetLen];
fTree = 0;
fFile = 0;
fFiles = new TObjArray(fTreeOffsetLen );
fStatus = new TList();
fCanDeleteRefs = kFALSE;
fChainProof = 0;
gROOT->GetListOfDataSets()->Add(this);
}
TChain::TChain(const char *name, const char *title)
:TTree(name,title)
{
fTreeOffsetLen = 100;
fNtrees = 0;
fTreeNumber = -1;
fTreeOffset = new Long64_t[fTreeOffsetLen];
fTree = 0;
fFile = 0;
fFiles = new TObjArray(fTreeOffsetLen );
fStatus = new TList();
fTreeOffset[0] = 0;
fCanDeleteRefs = kFALSE;
gDirectory->GetList()->Remove(this);
gROOT->GetListOfSpecials()->Add(this);
fDirectory = 0;
fChainProof = 0;
gROOT->GetListOfDataSets()->Add(this);
}
TChain::TChain(const TChain& tc) :
TTree(tc),
fTreeOffsetLen(tc.fTreeOffsetLen),
fNtrees(tc.fNtrees),
fTreeNumber(tc.fTreeNumber),
fTreeOffset(tc.fTreeOffset),
fCanDeleteRefs(tc.fCanDeleteRefs),
fTree(tc.fTree),
fFile(tc.fFile),
fFiles(tc.fFiles),
fStatus(tc.fStatus),
fChainProof(tc.fChainProof)
{
}
TChain& TChain::operator=(const TChain& tc)
{
if(this!=&tc) {
TTree::operator=(tc);
fTreeOffsetLen=tc.fTreeOffsetLen;
fNtrees=tc.fNtrees;
fTreeNumber=tc.fTreeNumber;
fTreeOffset=tc.fTreeOffset;
fCanDeleteRefs=tc.fCanDeleteRefs;
fTree=tc.fTree;
fFile=tc.fFile;
fFiles=tc.fFiles;
fStatus=tc.fStatus;
fChainProof=tc.fChainProof;
}
return *this;
}
TChain::~TChain()
{
ReleaseChainProof();
fDirectory = 0;
delete fFile; fFile = 0; fTree = 0;
gROOT->GetListOfSpecials()->Remove(this);
delete [] fTreeOffset;
fFiles->Delete();
delete fFiles;
fStatus->Delete();
delete fStatus;
gROOT->GetListOfDataSets()->Remove(this);
}
Int_t TChain::Add(TChain *chain)
{
if (fNtrees+chain->GetNtrees() >= fTreeOffsetLen) {
fTreeOffsetLen += 2*chain->GetNtrees();
Long64_t *trees = new Long64_t[fTreeOffsetLen];
for (Int_t i=0;i<=fNtrees;i++) trees[i] = fTreeOffset[i];
delete [] fTreeOffset;
fTreeOffset = trees;
}
TIter next(chain->GetListOfFiles());
TChainElement *element, *newelement;
Int_t nf = 0;
while ((element = (TChainElement*)next())) {
Long64_t nentries = element->GetEntries();
if (fTreeOffset[fNtrees]==kBigNumber) {
fTreeOffset[fNtrees+1] = kBigNumber;
} else {
fTreeOffset[fNtrees+1] = fTreeOffset[fNtrees] + nentries;
}
fNtrees++;
fEntries += nentries;
newelement = new TChainElement(element->GetName(),element->GetTitle());
newelement->SetPacketSize(element->GetPacketSize());
newelement->SetNumberEntries(nentries);
fFiles->Add(newelement);
nf++;
}
if (fChainProof)
SetProof(fChainProof->GetProof(), kTRUE);
return nf;
}
Int_t TChain::Add(const char *name, Long64_t nentries)
{
if (!TString(name).MaybeWildcard()) {
return AddFile(name,nentries);
}
Int_t nf = 0;
TString basename(name);
Int_t dotslashpos = basename.Index(".root/");
TString behind_dot_root;
if (dotslashpos>=0) {
behind_dot_root = basename(dotslashpos+6,basename.Length()-dotslashpos+6);
basename.Remove(dotslashpos+5);
}
Int_t slashpos = basename.Last('/');
TString directory;
if (slashpos>=0) {
directory = basename(0,slashpos);
basename.Remove(0,slashpos+1);
} else {
directory = gSystem->WorkingDirectory();
}
const char *file;
void *dir = gSystem->OpenDirectory(gSystem->ExpandPathName(directory.Data()));
if (dir) {
TList l;
TRegexp re(basename,kTRUE);
while ((file = gSystem->GetDirEntry(dir))) {
if (!strcmp(file,".") || !strcmp(file,"..")) continue;
TString s = file;
if ( (basename!=file) && s.Index(re) == kNPOS) continue;
l.Add(new TObjString(file));
}
gSystem->FreeDirectory(dir);
l.Sort();
TIter next(&l);
TObjString *obj;
while ((obj = (TObjString*)next())) {
file = obj->GetName();
if (behind_dot_root.Length() != 0)
nf += AddFile(Form("%s/%s/%s",directory.Data(),file,behind_dot_root.Data()),kBigNumber);
else
nf += AddFile(Form("%s/%s",directory.Data(),file),kBigNumber);
}
l.Delete();
}
if (fChainProof)
SetProof(fChainProof->GetProof(), kTRUE);
return nf;
}
Int_t TChain::AddFile(const char *name, Long64_t nentries, const char *tname)
{
TDirectory *cursav = gDirectory;
const char *treename = GetName();
if (tname && strlen(tname) > 0) treename = tname;
char *dot = (char*)strstr(name,".root");
if (fNtrees+1 >= fTreeOffsetLen) {
fTreeOffsetLen *= 2;
Long64_t *trees = new Long64_t[fTreeOffsetLen];
for (Int_t i=0;i<=fNtrees;i++) trees[i] = fTreeOffset[i];
delete [] fTreeOffset;
fTreeOffset = trees;
}
Int_t nch = strlen(name) + strlen(treename);
char *filename = new char[nch+1];
strcpy(filename,name);
if (dot) {
char *pos = (char*)strstr(filename,".root") + 5;
while (*pos) {
if (*pos == '/') {
treename = pos+1;
*pos = 0;
break;
}
pos++;
}
}
Int_t pksize = 0;
if (nentries <= 0) {
TFile *file = TFile::Open(filename);
if (!file || file->IsZombie()) {
delete file;
delete [] filename;
return 0;
}
TObject *obj = file->Get(treename);
if (!obj || !obj->InheritsFrom("TTree") ) {
Error("AddFile","cannot find tree with name %s in file %s", treename,filename);
delete file;
delete [] filename;
return 0;
}
TTree *tree = (TTree*)obj;
nentries = tree->GetEntries();
pksize = tree->GetPacketSize();
delete file;
}
if (nentries > 0) {
if (nentries < kBigNumber) {
fTreeOffset[fNtrees+1] = fTreeOffset[fNtrees] + nentries;
fEntries += nentries;
} else {
fTreeOffset[fNtrees+1] = kBigNumber;
fEntries = nentries;
}
fNtrees++;
TChainElement *element = new TChainElement(treename,filename);
element->SetPacketSize(pksize);
element->SetNumberEntries(nentries);
fFiles->Add(element);
} else {
Warning("Add","Adding Tree with no entries from file: %s",filename);
}
delete [] filename;
if (cursav) cursav->cd();
if (fChainProof)
SetProof(fChainProof->GetProof(), kTRUE);
return 1;
}
Int_t TChain::AddFileInfoList(TList *fileinfolist, Long64_t nfiles)
{
if (!fileinfolist)
return 0;
TIter next(fileinfolist);
TFileInfo* finfo;
Long64_t cnt=0;
while ((finfo = (TFileInfo*)next())) {
cnt++;
finfo->ResetUrl();
if (finfo->GetCurrentUrl())
AddFile((finfo->GetCurrentUrl())->GetUrl());
if (cnt>=nfiles)
break;
}
if (fChainProof)
SetProof(fChainProof->GetProof(), kTRUE);
return 1;
}
TFriendElement *TChain::AddFriend(const char *chain, const char *dummy)
{
//Begin_Html
/*
<img src="gif/chain_friend.gif">
*/
//End_Html
if (!fFriends) fFriends = new TList();
TFriendElement *fe = new TFriendElement(this,chain,dummy);
R__ASSERT(fe);
fFriends->Add(fe);
fTreeNumber = -1;
TTree *t = fe->GetTree();
if (!t) {
Warning("AddFriend","Unknown TChain %s",chain);
}
return fe;
}
TFriendElement *TChain::AddFriend(const char *chain, TFile *dummy)
{
if (!fFriends) fFriends = new TList();
TFriendElement *fe = new TFriendElement(this,chain,dummy);
R__ASSERT(fe);
fFriends->Add(fe);
fTreeNumber = -1;
TTree *t = fe->GetTree();
if (!t) {
Warning("AddFriend","Unknown TChain %s",chain);
}
return fe;
}
TFriendElement *TChain::AddFriend(TTree *chain, const char* alias,
Bool_t )
{
// Add the whole chain or tree as a friend of this chain
if (!fFriends) fFriends = new TList();
TFriendElement *fe = new TFriendElement(this,chain,alias);
R__ASSERT(fe);
fFriends->Add(fe);
// We need to invalidate the loading of the current tree because its list
// of real friend is now obsolete. It is repairable only from LoadTree
fTreeNumber = -1;
TTree *t = fe->GetTree();
if (!t) {
Warning("AddFriend","Unknown TChain %s",chain->GetName());
}
return fe;
}
void TChain::Browse(TBrowser *b)
{
TTree::Browse(b);
}
void TChain::CanDeleteRefs(Bool_t flag)
{
fCanDeleteRefs = flag;
}
void TChain::CreatePackets()
{
TIter next(fFiles);
TChainElement *element;
while ((element = (TChainElement*)next())) {
element->CreatePackets();
}
}
Long64_t TChain::Draw(const char *varexp, const TCut &selection, Option_t *option, Long64_t nentries, Long64_t firstentry)
{
if (fChainProof) {
fChainProof->SetEventList(fEventList);
return fChainProof->Draw(varexp, selection, option, nentries, firstentry);
}
return TChain::Draw(varexp, selection.GetTitle(), option, nentries, firstentry);
}
Long64_t TChain::Draw(const char *varexp, const char *selection, Option_t *option,Long64_t nentries, Long64_t firstentry)
{
if (fChainProof) {
fChainProof->SetEventList(fEventList);
return fChainProof->Draw(varexp, selection, option, nentries, firstentry);
}
if (LoadTree(firstentry) < 0) return 0;
return TTree::Draw(varexp,selection,option,nentries,firstentry);
}
TBranch *TChain::GetBranch(const char *name)
{
if (fChainProof) return fChainProof->GetBranch(name);
if (fTree) return fTree->GetBranch(name);
LoadTree(0);
if (fTree) return fTree->GetBranch(name);
return 0;
}
Long64_t TChain::GetChainEntryNumber(Long64_t entry) const
{
return entry + fTreeOffset[fTreeNumber];
}
Long64_t TChain::GetEntries() const
{
if (fChainProof) return fChainProof->GetEntries();
if (fEntries >= kBigNumber) {
const_cast<TChain*>(this)->LoadTree(fEntries-1);
}
return fEntries;
}
Int_t TChain::GetEntry(Long64_t entry, Int_t getall)
{
if (LoadTree(entry) < 0) return 0;
if (fTree==0) return 0;
return fTree->GetEntry(fReadEntry,getall);
}
Int_t TChain::GetEntryWithIndex(Int_t major, Int_t minor)
{
Long64_t serial = GetEntryNumberWithIndex(major, minor);
if (serial < 0) return -1;
return GetEntry(serial);
}
TFile *TChain::GetFile() const
{
if (fFile) return fFile;
const_cast<TChain*>(this)->LoadTree(0);
return fFile;
}
TLeaf *TChain::GetLeaf(const char *name)
{
if (fChainProof) return fChainProof->GetLeaf(name);
if (fTree) return fTree->GetLeaf(name);
LoadTree(0);
if (fTree) return fTree->GetLeaf(name);
return 0;
}
TObjArray *TChain::GetListOfBranches()
{
if (fChainProof) return fChainProof->GetListOfBranches();
if (fTree) return fTree->GetListOfBranches();
LoadTree(0);
if (fTree) return fTree->GetListOfBranches();
return 0;
}
TObjArray *TChain::GetListOfLeaves()
{
if (fChainProof) return fChainProof->GetListOfLeaves();
if (fTree) return fTree->GetListOfLeaves();
LoadTree(0);
if (fTree) return fTree->GetListOfLeaves();
return 0;
}
Double_t TChain::GetMaximum(const char *columname)
{
Double_t theMax = -FLT_MAX;
for (Int_t file=0;file<fNtrees;file++) {
Long64_t first = fTreeOffset[file];
LoadTree(first);
Double_t curmax = fTree->GetMaximum(columname);;
if (curmax > theMax) theMax = curmax;
}
return theMax;
}
Double_t TChain::GetMinimum(const char *columname)
{
Double_t theMin = FLT_MAX;
for (Int_t file=0;file<fNtrees;file++) {
Long64_t first = fTreeOffset[file];
LoadTree(first);
Double_t curmin = fTree->GetMinimum(columname);;
if (curmin < theMin) theMin = curmin;
}
return theMin;
}
Int_t TChain::GetNbranches()
{
if (fTree) return fTree->GetNbranches();
LoadTree(0);
if (fTree) return fTree->GetNbranches();
return 0;
}
const char *TChain::GetAlias(const char *aliasName) const
{
const char *alias = TTree::GetAlias(aliasName);
if (alias) return alias;
if (fTree) return fTree->GetAlias(aliasName);
const_cast<TChain*>(this)->LoadTree(0);
if (fTree) return fTree->GetAlias(aliasName);
return 0;
}
Double_t TChain::GetWeight() const
{
if (TestBit(kGlobalWeight)) return fWeight;
else {
if (fTree) return fTree->GetWeight();
const_cast<TChain*>(this)->LoadTree(0);
if (fTree) return fTree->GetWeight();
return 0;
}
}
Int_t TChain::LoadBaskets(Long64_t )
{
Error("LoadBaskets","function not yet implemented for TChains");
return 0;
}
Long64_t TChain::LoadTree(Long64_t entry)
{
if (kLoadTree & fFriendLockStatus) return 0;
if (!fNtrees) return 1;
if (entry < 0 || (entry > 0 && entry >= fEntries)) return -2;
Int_t t;
if (fTreeNumber!=-1 &&
(entry >= fTreeOffset[fTreeNumber] && entry < fTreeOffset[fTreeNumber+1])){
t = fTreeNumber;
}
else {
for (t=0;t<fNtrees;t++) {
if (entry < fTreeOffset[t+1]) break;
}
}
fReadEntry = entry - fTreeOffset[t];
if (t == fTreeNumber) {
fTree->LoadTree(fReadEntry);
if (fFriends) {
TIter next(fFriends);
TFriendLock lock(this,kLoadTree);
TFriendElement *fe;
TFriendElement *fetree;
Bool_t needUpdate = kFALSE;
while ((fe = (TFriendElement*)next())) {
TObjLink *lnk = 0;
if (fTree->GetListOfFriends())
lnk = fTree->GetListOfFriends()->FirstLink();
fetree = 0;
while (lnk) {
TObject *obj = lnk->GetObject();
if (obj->TestBit(TFriendElement::kFromChain)
&& obj->GetName() && !strcmp(fe->GetName(), obj->GetName())) {
fetree = (TFriendElement*)obj;
break;
}
lnk = lnk->Next();
}
TTree *at = fe->GetTree();
if (at->InheritsFrom(TChain::Class())) {
Int_t oldNumber = ((TChain*)at)->GetTreeNumber();
TTree* old = at->GetTree();
TTree* oldintree = fetree ? fetree->GetTree() : 0;
at->LoadTreeFriend(entry, this);
Int_t newNumber = ((TChain*)at)->GetTreeNumber();
if (oldNumber!=newNumber || old!=at->GetTree()
|| (oldintree && oldintree != at->GetTree())) {
needUpdate = kTRUE;
fTree->RemoveFriend(oldintree);
fTree->AddFriend(at->GetTree(),fe->GetName())
->SetBit(TFriendElement::kFromChain);
}
} else {
at->LoadTreeFriend(entry, this);
}
}
if (needUpdate) {
if (fPlayer) fPlayer->UpdateFormulaLeaves();
if (fNotify) fNotify->Notify();
}
}
return fReadEntry;
}
if (fTree && fTree->GetListOfClones()) {
TObjLink *lnk = fTree->GetListOfClones()->FirstLink();
while (lnk) {
TTree *clone = (TTree*)lnk->GetObject();
AddClone(clone);
lnk = lnk->Next();
}
fTree->GetListOfClones()->Clear();
}
TDirectory *cursav = gDirectory;
TTreeCache *tpf = 0;
if (fFile) {
if (!fDirectory->GetList()->FindObject(this)) {
if (cursav && cursav->GetFile()==fFile) {
cursav = gROOT;
}
tpf = (TTreeCache*)fFile->GetCacheRead();
fFile->SetCacheRead(0);
if (fCanDeleteRefs) fFile->Close("R");
delete fFile; fFile = 0; fTree = 0;
}
}
TChainElement *element = (TChainElement*)fFiles->At(t);
if (!element) {
if (fReadEntry) return -4;
element = (TChainElement*)fFiles->At(0);
if (!element) return -4;
}
fFile = TFile::Open(element->GetTitle());
Int_t returnCode=0;
if (!fFile || fFile->IsZombie()) {
delete fFile; fFile = 0;
fTree=0;
returnCode=-3;
} else {
fTree = (TTree*)fFile->Get(element->GetName());
if (fTree==0) {
Error("LoadTree","cannot find tree with name %s in file %s",
element->GetName(),element->GetTitle());
delete fFile; fFile = 0;
returnCode=-4;
}
}
fTreeNumber = t;
fDirectory = fFile;
if (tpf) {
fFile->SetCacheRead(tpf);
tpf->SetFile(fFile);
tpf->UpdateBranches(fTree);
} else {
this->SetCacheSize(fCacheSize);
}
Long64_t nentries = fTree ? fTree->GetEntries() : 0;
if (fTreeOffset[fTreeNumber+1] != fTreeOffset[fTreeNumber] + nentries) {
fTreeOffset[fTreeNumber+1] = fTreeOffset[fTreeNumber] + nentries;
fEntries = fTreeOffset[fNtrees];
element->SetNumberEntries(nentries);
if (entry >= fTreeOffset[fTreeNumber+1]) {
cursav->cd();
if (fTreeNumber < fNtrees-1 && entry < fTreeOffset[fTreeNumber+2]) return LoadTree(entry);
else fReadEntry = -2;
}
}
if (fTree==0) {
fTreeNumber = -1;
return returnCode;
}
fTree->LoadTree(fReadEntry);
if (fFriends) {
TIter next(fFriends);
TFriendLock lock(this,kLoadTree);
TFriendElement *fe;
while ((fe = (TFriendElement*)next())) {
TTree *t = fe->GetTree();
if (t->GetTreeIndex())
t->GetTreeIndex()->UpdateFormulaLeaves();
t->LoadTreeFriend(entry, this);
TTree *friend_t = t->GetTree();
if (friend_t) {
fTree->AddFriend(friend_t,fe->GetName())
->SetBit(TFriendElement::kFromChain);
}
}
}
fTree->SetMakeClass(fMakeClass);
fTree->SetMaxVirtualSize(fMaxVirtualSize);
SetChainOffset(fTreeOffset[t]);
TIter next(fStatus);
Int_t status;
while ((element = (TChainElement*)next())) {
status = element->GetStatus();
fTree->SetBranchStatus(element->GetName(),status);
}
next.Reset();
while ((element = (TChainElement*)next())) {
void *add = element->GetBaddress();
if (add) {
TBranch *br = fTree->GetBranch(element->GetName());
TBranch **ptr = element->GetBranchPtr();
if (ptr) { *ptr = br; }
if (br) {
br->SetAddress(add);
if (TestBit(kAutoDelete)) br->SetAutoDelete(kTRUE);
}
}
}
if (cursav) cursav->cd();
if (fClones) {
TObjLink *lnk = fClones->FirstLink();
while (lnk) {
TTree *clone = (TTree*)lnk->GetObject();
CopyAddresses(clone);
lnk = lnk->Next();
}
}
if (fPlayer) fPlayer->UpdateFormulaLeaves();
if (fNotify) fNotify->Notify();
return fReadEntry;
}
void TChain::Lookup()
{
TIter next(fFiles);
TChainElement *element;
Int_t nelements = fFiles->GetEntries();
printf("\n");
printf("TChain::Lookup - Looking up %d files .... \n",nelements);
Int_t nlook = 0;
while ((element = (TChainElement*)next())) {
nlook++;
TUrl cachefileurl(element->GetTitle());
TString options=cachefileurl.GetOptions();
cachefileurl.SetOptions(options+="&filetype=raw");
TFile *cachefile = TFile::Open(cachefileurl.GetUrl());
if ((!cachefile) || cachefile->IsZombie()) {
fFiles->Remove(element);
Error("Lookup","Couldn't open %s\n",cachefileurl.GetUrl());
} else {
printf("Lookup | %03.02f %% finished\r",100.0*nlook/nelements);
fflush(stdout);
TString urlstring = ((TUrl*)cachefile->GetEndpointUrl())->GetUrl();
urlstring.ReplaceAll("&filetype=raw","");
element->SetTitle( urlstring );
delete cachefile;
}
}
printf("\n");
}
void TChain::Loop(Option_t *option, Long64_t nentries, Long64_t firstentry)
{
Error("Loop","Function not yet implemented");
if (option || nentries || firstentry) { }
#ifdef NEVER
if (LoadTree(firstentry) < 0) return;
if (firstentry < 0) firstentry = 0;
Long64_t lastentry = firstentry + nentries -1;
if (lastentry > fEntries-1) {
lastentry = fEntries -1;
}
GetPlayer();
GetSelector();
fSelector->Start(option);
Long64_t entry = firstentry;
Int_t tree,e0,en;
for (tree=0;tree<fNtrees;tree++) {
e0 = fTreeOffset[tree];
en = fTreeOffset[tree+1] - 1;
if (en > lastentry) en = lastentry;
if (entry > en) continue;
LoadTree(entry);
fSelector->BeginFile();
while (entry <= en) {
fSelector->Execute(fTree, entry - e0);
entry++;
}
fSelector->EndFile();
}
fSelector->Finish(option);
#endif
}
void TChain::ls(Option_t *option) const
{
TIter next(fFiles);
TChainElement *file;
while ((file = (TChainElement*)next())) {
file->ls(option);
}
}
Long64_t TChain::Merge(const char *name, Option_t *option)
{
TFile *file = TFile::Open(name,"recreate","chain files",1);
return Merge(file,0,option);
}
Long64_t TChain::Merge(TCollection * , Option_t * )
{
Error("Merge", "not implemented");
return -1;
}
Long64_t TChain::Merge(TFile *file, Int_t basketsize, Option_t *option)
{
if (!file) return 0;
Bool_t fastClone = kFALSE;
TString opt = option;
opt.ToLower();
if (opt.Contains("fast")) {
fastClone = kTRUE;
}
TObjArray *lbranches = GetListOfBranches();
if (!lbranches) return 0;
if (!fTree) return 0;
TTree *hnew = CloneTree(0);
if (!hnew) return 0;
hnew->SetName(gSystem->BaseName(GetName()));
hnew->SetAutoSave(2000000000);
hnew->SetCircular(0);
TBranch *branch;
TIter nextb(hnew->GetListOfBranches());
if (opt.Contains("c")) {
while ((branch = (TBranch*)nextb())) {
branch->SetCompressionLevel(file->GetCompressionLevel());
}
nextb.Reset();
}
if (basketsize > 1000) {
while ((branch = (TBranch*)nextb())) {
branch->SetBasketSize(basketsize);
}
nextb.Reset();
}
char *firstname = new char[1000];
firstname[0] = 0;
strcpy(firstname,gFile->GetName());
Long64_t nentries = GetEntriesFast();
if (fastClone) {
for (Long64_t i=0; i<nentries; i += this->GetTree()->GetEntries() )
{
if (LoadTree(i) < 0) break;
TTreeCloner t(GetTree(),hnew,option);
if (t.IsValid()) {
hnew->SetEntries( hnew->GetEntries() + GetTree()->GetEntries() );
t.Exec();
} else {
if (GetFile()) {
Warning("Merge","Skipped file %s\n", GetFile()->GetName());
} else {
Warning("Merge","Skipped file number %d\n", fTreeNumber);
}
}
}
} else {
for (Long64_t i=0;i<nentries;i++) {
if (GetEntry(i) <= 0) break;
hnew->Fill();
}
}
hnew->Write();
Int_t nfiles = hnew->GetFileNumber()+1;
delete [] firstname;
if (!opt.Contains("keep")) delete hnew->GetCurrentFile();
return nfiles;
}
void TChain::Print(Option_t *option) const
{
TIter next(fFiles);
TChainElement *element;
while ((element = (TChainElement*)next())) {
TFile *file = TFile::Open(element->GetTitle());
if (file && !file->IsZombie()) {
TTree *tree = (TTree*)file->Get(element->GetName());
if (tree) tree->Print(option);
}
delete file;
}
}
Long64_t TChain::Process(const char *filename,Option_t *option, Long64_t nentries, Long64_t firstentry)
{
if (fChainProof)
return fChainProof->Process(filename, option, nentries, firstentry);
if (LoadTree(firstentry) < 0) return 0;
return TTree::Process(filename,option,nentries,firstentry);
}
Long64_t TChain::Process(TSelector *selector,Option_t *option, Long64_t nentries, Long64_t firstentry)
{
if (fChainProof)
return fChainProof->Process(selector, option, nentries, firstentry);
return TTree::Process(selector,option,nentries,firstentry);
}
void TChain::Reset(Option_t *)
{
delete fFile;
fNtrees = 0;
fTreeNumber = -1;
fTree = 0;
fFile = 0;
fFiles->Delete();
fStatus->Delete();
fTreeOffset[0] = 0;
TChainElement *element = new TChainElement("*","");
fStatus->Add(element);
fDirectory = 0;
TTree::Reset();
}
Long64_t TChain::Scan(const char *varexp, const char *selection,
Option_t *option, Long64_t nentries, Long64_t firstentry)
{
if (LoadTree(firstentry) < 0) return 0;
return TTree::Scan(varexp,selection,option,nentries,firstentry);
}
void TChain::SetAutoDelete(Bool_t autodelete)
{
if (autodelete) SetBit(kAutoDelete,1);
else SetBit(kAutoDelete,0);
}
void TChain::ResetBranchAddresses()
{
TIter next(fStatus);
TChainElement *element = 0;
while ((element = (TChainElement*)next())) {
element->SetBaddress(0);
}
if (fTree) fTree->ResetBranchAddresses();
}
void TChain::SetBranchAddress(const char *bname, void *add, TBranch **ptr)
{
TChainElement *element = (TChainElement*)fStatus->FindObject(bname);
if (!element) {
element = new TChainElement(bname,"");
fStatus->Add(element);
}
element->SetBaddress(add);
element->SetBranchPtr(ptr);
if (fTreeNumber >= 0) {
TBranch *branch = fTree->GetBranch(bname);
if (ptr) { *ptr = branch; }
if (branch) {
CheckBranchAddressType(branch,
gROOT->GetClass(element->GetBaddressClassName()),
(EDataType)element->GetBaddressType(),element->GetBaddressIsPtr());
if (fClones) {
void *oldAdd = branch->GetAddress();
TObjLink *lnk = fClones->FirstLink();
while (lnk) {
TTree *clone = (TTree*)lnk->GetObject();
TBranch *cloneBr = clone->GetBranch(bname);
if (cloneBr && cloneBr->GetAddress() == oldAdd ) {
cloneBr->SetAddress(add);
}
lnk = lnk->Next();
}
}
branch->SetAddress(add);
}
} else {
if (ptr) *ptr = 0;
}
}
void TChain::SetBranchAddress(const char *bname,void *add,
TClass *realClass, EDataType datatype,
Bool_t isptr)
{
return SetBranchAddress(bname,add,0,realClass,datatype,isptr);
}
void TChain::SetBranchAddress(const char *bname,void *add,
TBranch **ptr,
TClass *realClass, EDataType datatype,
Bool_t isptr)
{
TChainElement *element = (TChainElement*)fStatus->FindObject(bname);
if (!element) {
element = new TChainElement(bname,"");
fStatus->Add(element);
}
if (realClass) element->SetBaddressClassName(realClass->GetName());
element->SetBaddressType((UInt_t)datatype);
element->SetBaddressIsPtr(isptr);
element->SetBranchPtr(ptr);
SetBranchAddress(bname,add,ptr);
}
void TChain::SetBranchStatus(const char *bname, Bool_t status, UInt_t *found)
{
TChainElement *element = (TChainElement*)fStatus->FindObject(bname);
if (element)
fStatus->Remove (element);
else
element = new TChainElement(bname,"");
fStatus->Add(element);
element->SetStatus(status);
if (fTreeNumber >= 0) {
fTree->SetBranchStatus(bname,status,found);
} else if (found) {
*found = 1;
}
}
void TChain::SetDirectory(TDirectory *dir)
{
if (fDirectory == dir) return;
if (fDirectory) fDirectory->GetList()->Remove(this);
fDirectory = dir;
if (fDirectory) {
fDirectory->GetList()->Add(this);
fFile = fDirectory->GetFile();
} else {
fFile = 0;
}
}
void TChain::SetPacketSize(Int_t size)
{
fPacketSize = size;
TIter next(fFiles);
TChainElement *element;
while ((element = (TChainElement*)next())) {
element->SetPacketSize(size);
}
}
void TChain::SetWeight(Double_t w, Option_t *option)
{
fWeight = w;
TString opt = option;
opt.ToLower();
ResetBit(kGlobalWeight);
if (opt.Contains("global")) {
SetBit(kGlobalWeight);
}
}
void TChain::Streamer(TBuffer &b)
{
if (b.IsReading()) {
UInt_t R__s, R__c;
Version_t R__v = b.ReadVersion(&R__s, &R__c);
if (R__v > 2) {
TChain::Class()->ReadBuffer(b, this, R__v, R__s, R__c);
return;
}
TTree::Streamer(b);
b >> fTreeOffsetLen;
b >> fNtrees;
fFiles->Streamer(b);
if (R__v > 1) {
fStatus->Streamer(b);
fTreeOffset = new Long64_t[fTreeOffsetLen];
b.ReadFastArray(fTreeOffset,fTreeOffsetLen);
}
b.CheckByteCount(R__s, R__c, TChain::IsA());
} else {
TChain::Class()->WriteBuffer(b,this);
}
}
void TChain::UseCache(Int_t , Int_t )
{
}
void TChain::ReleaseChainProof()
{
if (!fChainProof) return;
fChainProof->GetProof()->RemoveChain(this);
SafeDelete(fChainProof);
}
TDSet* TChain::MakeTDSet() const
{
TDSet * mainDSet = MakeTDSetWithoutFriends();
std::set<const TChain*> processed;
std::queue<const TChain*> chainsQueue;
chainsQueue.push(this);
processed.insert(this);
while (!chainsQueue.empty()) {
const TChain* chain = chainsQueue.front();
chainsQueue.pop();
TIter friendsIter(chain->GetListOfFriends());
while(TFriendElement *friendElement = dynamic_cast<TFriendElement*> (friendsIter()) ) {
if (TChain* friendChain = dynamic_cast<TChain*>(friendElement->GetTree())) {
if (processed.find(friendChain) == processed.end()) {
processed.insert(friendChain);
mainDSet->AddFriend(friendChain->MakeTDSetWithoutFriends(), friendElement->GetName());
chainsQueue.push(friendChain);
}
}
else {
delete mainDSet;
Error("MakeTDSetWithFriends",
"Only TChains supported. Illegal tree %s.\n", friendElement->GetTree()->GetName());
return 0;
}
}
}
return mainDSet;
}
TDSet* TChain::MakeTDSetWithoutFriends() const
{
TIter next(GetListOfFiles());
TChainElement *element;
TDSet *dset = new TDSet("TTree", GetName());
while ((element = (TChainElement*)next())) {
TString file(element->GetTitle());
TString tree(element->GetName());
Int_t slashpos = tree.Index("/");
TString dir = "/";
if (slashpos>=0) {
TString behindSlash = tree(slashpos+1,tree.Length()-slashpos-1);
tree.Remove(slashpos);
dir = tree;
tree = behindSlash;
}
dset->Add(file, tree, dir);
}
dset->SetDirectory(0);
return dset;
}
void TChain::SetProof(TVirtualProof *proof, Bool_t refresh, Bool_t gettreeheader)
{
if (proof == (TVirtualProof*) -1)
proof = gProof;
if (fChainProof && proof == fChainProof->GetProof() && !refresh &&
(!gettreeheader || (gettreeheader && fChainProof->HasTreeHeader())))
return;
ReleaseChainProof();
if (proof) {
TDSet* set = MakeTDSet();
gROOT->GetListOfDataSets()->Remove(set);
R__ASSERT(set);
fChainProof = TChainProof::MakeChainProof(set, proof, gettreeheader);
if (!fChainProof)
Error("SetProof", "can't set PROOF");
else
proof->AddChain(this);
}
}
Long64_t TChain::GetReadEntry() const
{
if (fChainProof) return fChainProof->GetReadEntry();
return TTree::GetReadEntry();
}
TBranch *TChain::FindBranch(const char* branchname)
{
if (fChainProof) return fChainProof->FindBranch(branchname);
if (fTree) return fTree->FindBranch(branchname);
LoadTree(0);
if (fTree) return fTree->FindBranch(branchname);
return 0;
}
TLeaf *TChain::FindLeaf(const char* searchname)
{
if (fChainProof) return fChainProof->FindLeaf(searchname);
if (fTree) return fTree->FindLeaf(searchname);
LoadTree(0);
if (fTree) return fTree->FindLeaf(searchname);
return 0;
}
Bool_t TChain::GetBranchStatus(const char *branchname) const
{
if (fChainProof) return fChainProof->GetBranchStatus(branchname);
return TTree::GetBranchStatus(branchname);
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.