Problems with copying a subset of a chain

Thanks for the help, I managed to modify my program so that it now uses chains. However, I still encounter a proplem when trying to copy the subset of a (chain) tree into a new file.

Though the program runs without a problem and writes the subset of the tree to the output file “simdata” the content of “RunID” and “EventID” are corrupted (yield segmentation violation when trying to draw in root).

I suspect the reason to be that I use two chains on the same tree though I thought that using the clone command when doing the dummy-SetTree() would separat them in memory.

Below is an an excerpt of my program:

class TreeEvtSelection
{
public:
  TreeEvtSelection() 
    : fChain(0),
      fNewTree(0),
      fTreeNumber(0),
      fRunID(0),
      fEvtID(0),
      fEntry(0)
  {};

  ~TreeEvtSelection() {};

  void SetTree(TChain* chain) {
    fChain = chain;
    fNewTree = fChain->CloneTree(0);
    fChain->SetBranchAddress("RunID",&fRunID);  
    fChain->SetBranchAddress("EventID",&fEvtID);  
  };

  void SelectEvt(int treeNumber, int evtID, int newRunID, int newEvtID) {
    for ( int entryID=fEntry; entryID<fChain->GetEntries(); entryID++ ){
      fChain->GetEntry(entryID);
      fTreeNumber = fChain->GetTreeNumber();
      if ( fTreeNumber == treeNumber && fEvtID == evtID ) {
	fEvtID = newEvtID;
	fNewTree->Fill();
	fEntry = entryID+1;
	break;
      } else if ( (fTreeNumber == treeNumber && fEvtID > evtID) || 
		  fTreeNumber > treeNumber ) {
	fEntry = entryID;
	break;
      }
    }
  };

main program:
 TFile* simDataFile = new TFile("simDataFile.root","RECREATE");

*** this is  a loop over the different input file names
	treeChain2->Add(fileName.c_str());
 	treeChain->Add(fileName.c_str());
***

 simDataFile->cd();
 TreeEvtSelection* dummy = new TreeEvtSelection;
 dummy->SetTree((TChain*) treeChain2->Clone());
 
*** I forgot these lines the first time
int evtID;
int maxEntries = treeChain->GetEntries();
treeChain->SetBranchAddress("EventID",&evtID);
***
for ( int entry=0; entry<maxEntries; entry++ ) {
      treeChain->GetEntry(entry);
      int treeNumber = treeChain->GetTreeNumber();
      if (selection) {
          dummy->SelectEvt(treeNumber,evtID,newRunID,newEvtID);
      }
}
 dummy->Save();
***

Regards, Alexander

It looks like instead of:dummy->SetTree((TChain*) treeChain2->Clone()); you need dummy->SetTree(treeChain2);
Cheers,
Philippe

Hi Philippe,

thanks for the hint. Unfortunately, it doesn’t work.

Also, I just noticed that I forgot a crucial part in the main program (the 2 lines before the FOR loop below). Actually, I think it is these lines that cause the trouble as they define a second time a pointer to “EventID”, though I thought using the Clone method (treeChain2->Clone()) would solve this.

main program:
 TFile* simDataFile = new TFile("simDataFile.root","RECREATE");

*** this is  a loop over the different input file names
   treeChain2->Add(fileName.c_str());
    treeChain->Add(fileName.c_str());
***

 simDataFile->cd();
 TreeEvtSelection* dummy = new TreeEvtSelection;
 dummy->SetTree((TChain*) treeChain2->Clone());

 int maxEntries = treeChain->GetEntries();
 treeChain->SetBranchAddress("EventID",&evtID);
 for ( int entry=0; entry<maxEntries; entry++ ) {
      treeChain->GetEntry(entry);
      int treeNumber = treeChain->GetTreeNumber();
      if (selection) {
          dummy->SelectEvt(treeNumber,evtID,newRunID,newEvtID);
      }
}
 dummy->Save();
*** 

Regards, Alexander

Hi,

I am a bit confused on what you are trying to do …

What’s the difference between treeChain and treeChain2?

Why do you completely clone (including data) one of the chain and then turn around and clone it again. [ treeChain2->Clone() completely clone the chain ]. In addition the cast code treeChain2->Clone() [/code] is illegal since the object returned by Clone is really a TTree.

Cheers,
Philippe.

Hi Philippe,

actually, I was not sure whether

treeChain2->Add(fileName.c_str());
treeChain->Add(fileName.c_str()); 

would produce two completely independent chains in memory which I think I need in order to use the two SetBranchAddresses independently from each other.

From what you write I understand that this is indeed the case and the second clone command is unnecessary and even illegal. However, also using “dummy->SetTree(treeChain2)” doesn’t solve the problem.

Cheers, Alexander

[quote]the content of “RunID” and “EventID” are corrupted (yield segmentation violation when trying to draw in root). [/quote]Humm this is very bad :slight_smile: … and there is no clear reason in your code why this would be … My best guess is that the TTree (or TChain) you use to Draw is incorrect (has already been deleted or whatever else).

Anyway, your best bet is to send a complete, running example via an attached tar file so that we can reproduce the problem.

Cheers,
Philippe

Actually, the drawing is done afterwards from the written file using TBrowser.

I also just looked at the value of fEvtID right before “fNewTree->Fill()” in “SelectEvt”; it has the correct values. What exactly happens when doing “fNewTree->Fill()”?

I will try to set up a running example but it may take a while as the program uses some non-standard libraries.

Cheers, Alexander

[quote]Actually, the drawing is done afterwards from the written file using TBrowser.[/quote]Even weirder … can you give me access to the root file.

It ‘stream’ the info from the variable into the in-memory file buffer, when those in-memory buffer (TBuffer) are full, they are written to disk …

Cheers,
Philippe

So can the info accidentally be changed after it had been streamed?

The root file is attached
simDataFile.root (8.27 KB)