Problem with CloneTree & multiple files

I’m using 4.02.00 in RHEL3 linux.

I am using CloneTree to rewrite one column of a tuple, so I turn off that branch, clone the tree, then add a branch of that name to the cloned tree and then fill it. I am TChaining files for the input.

It works fine with a single file in the TChain, but for multiple files, it is as if the CloneTree did not ignore the turned-off branch - the new column is identical to the original version! Here is a snippet of the code:

int doit(TChain* chain, char* fileStem) {

float origLivetime(0.);
float correctedLivetime(0.);
float run;

TFile* outfil = new TFile(fileStem,“RECREATE”);

chain->SetBranchStatus(“EvtLiveTime”,0); // turn off the livetime branch
TTree* clone = chain->CloneTree(0); // copy the other branches

clone->Branch(“EvtLiveTime”,&correctedLivetime,“EvtLiveTime/F”);

chain->SetBranchStatus(“EvtLiveTime”,1); // turn the livetime back on
chain->SetBranchAddress(“EvtLiveTime”,&origLivetime); // do this one by hand
chain->SetBranchAddress(“EvtRun”,&run); // do this one by hand

float timeOffset = 0.;

for ( ULong64_t iEvt(0); iEvt < chain->GetEntries(); iEvt++) {
// for ( ULong64_t iEvt(0); iEvt < 20; iEvt++) {
chain->LoadTree(iEvt);
chain->GetEntry(iEvt);

correctedLivetime = origLivetime + mapLive[(long long)run];

lastSeenLivetime = origLivetime;

clone->Fill();

}

// there is only a single output file anyhow, but in case

outfil = clone->GetCurrentFile();

// Write selected data to output disk file
outfil->Write(0, TObject::kWriteDelete);
return clone->GetEntries();
}

I searched the forum, but could not find any reference to a problem with CloneTree and multiple files…

Richard

I have a workaround. I suspect it a matter of what happens to the branch addresses when TChain changes files.

I got it to work by explicitly looping over the files in the TChain and then doing a CopyBranchAddress to my cloned tree. I suspect there is a vastly more elegant way to do this!

TTree* clone=0;
clone = chain->CloneTree(0); // copy the other branches

clone->Branch(“EvtLiveTime”,&correctedLivetime,“EvtLiveTime/F”);

for ( ULong64_t iFile(0); iFile < listFiles->GetEntries(); iFile++) {

const char* fName = ((TChainElement*)listFiles->At(iFile))->GetTitle();

TFile* currentFile = new TFile(fName);
currentFile->cd();
TTree* currentTree = (TTree*)gDirectory->Get(“MeritTuple”);

currentTree->SetBranchStatus(“EvtLiveTime”,0); // turn off the livetime bra
nch
clone->CopyAddresses(currentTree);
currentTree->SetBranchStatus(“EvtLiveTime”,1); // turn the livetime back on

clone->CopyAddresses(currentTree);
currentTree->SetBranchStatus(“EvtLiveTime”,1); // turn the livetime back on

currentTree->SetBranchAddress(“EvtLiveTime”,&origLivetime); // do this one b
y hand

float lastSeenLivetime = 0;

for ( ULong64_t iEvt(0); iEvt < currentTree->GetEntries(); iEvt++) {
// for ( ULong64_t iEvt(0); iEvt < 20; iEvt++) {
currentTree->LoadTree(iEvt);
currentTree->GetEntry(iEvt);

 TLeaf* rLeaf = currentTree->GetLeaf("EvtRun");
 run = static_cast<float>(rLeaf->GetValue());

 correctedLivetime = origLivetime + mapLive[(long long)run];
  }

 lastSeenLivetime = origLivetime;


 clone->Fill();
 //      delete currentFile;

}
}

// Write selected data to output disk file
outfil->Write(0, TObject::kWriteDelete);

return clone->GetEntries();
}

Hi Richard,

The problem is the TChain has no way to distinguish your special case (partial clone + add a new branch whose name already exist) and the full cloning. Hence it assumes that the 2 branches are connected and (properly?) propagate the addresses.

However what you want to do can be very simply achieved by modifying in place the value:

[code]int doit(TChain* chain, char* fileStem) {

float origLivetime(0.);
float livetime(0.);
float run;

TFile* outfil = new TFile(fileStem,“RECREATE”);

TTree* clone = chain->CloneTree(0); // copy the other branches

chain->SetBranchAddress(“EvtLiveTime”,&livetime); // do this one by hand
chain->SetBranchAddress(“EvtRun”,&run); // do this one by hand

float timeOffset = 0.;

for ( ULong64_t iEvt(0); iEvt < chain->GetEntries(); iEvt++) {
chain->LoadTree(iEvt);
chain->GetEntry(iEvt);

 origLivetime = lifetime;
 livetime = origLivetime + mapLive[(long long)run];

 lastSeenLivetime = origLivetime;

 clone->Fill();

}

// there is only a single output file anyhow, but in case
outfil = clone->GetCurrentFile();

// Write selected data to output disk file
outfil->Write(0, TObject::kWriteDelete);
return clone->GetEntries();
}[/code]

Cheers,
Philippe.

PS. Otherwise your work-around (which can be greatly simplified by just calling GetListOfClones()->Remove(clone) ) would also work.

Hi Philippe,

Thanks! That is diabolically simple, and obvious now that you show it to me. Rene always tells me I find the most convoluted ways of doing things. :smiley:

Enjoy Mumbai!

Richard