Write TTree out to file seems to corrupt it


Please read tips for efficient and successful posting and posting code

ROOT Version: 5.34/36
Platform: cygwin
Compiler: 10.2.0


Hi, this is slightly embarrassing because I seem to hit something really basic that I should know, but clearly I do not. This is my example:

void treeProblem() {

  // define my tree with 2 ints
  TTree *evnt = new TTree("eventData","event data");
  int DAQdms, SELdms;
  evnt->Branch("DAQdms",&DAQdms,"DAQdms/I");
  evnt->Branch("SELdms",&SELdms,"SELdms/I");

  DAQdms = 0;
  SELdms = 1;
  evnt->Fill(); // there is one entry in evnt

  TFile rootFile("pass1.root","recreate");
  evnt->Write();    // write this out on pass1.root
  rootFile.Close();

  DAQdms = 2;
  SELdms = 3;
  evnt->Fill(); // evnt has 2 entries now

  TFile rootFile("pass2.root","recreate");
  evnt->Write();    // write this out on pass2.root
  rootFile.Close();

}

The macro runs no problem and no errors. The data in pass1.root, when read out later, are correct. The data in pass2.root are corrupt.

If I comment all lines after the 1st evnt->Write(), and fire up a TBrowser, double clicking the leaves already shows junk.

The sample might appear stupid, but what I am trying to do is run on events for a long time, saving the Ttree in a different file after every (say) 10000 events, and have the complete stat in the last file.

I could (I think) accumulate 10000 events, save them, delete the TTree, start fresh a new one and so on, using TChain to read back all the files, but this appears silly.

What am I doing wrong? Can I keep my TTree accumulating correctly after each Write()?
Thank you!

Hello,

The problem might be related to the registering of the tree in the files, since you are trying to use the same tree to write to two different files.

@pcanal will know better what is happening here and how this could be done.

Also the first Close should have deleted the tree if the first file owns the tree, so the tree shouldn’t be used afterwards. Perhaps you can do this with two trees, one for each file, or just write one file per execution of the application and parameterize the name of the file and what should be written in it.

Thank you for looking into this. The first rootFile.Close() does not seem to harm the tree, commenting that line does not alter the result.
In the meantime, I have given up with the OneTree idea, now every 10000 events I just close the prev file, trash the prev tree, plant a new one with a similar name, grow its leaves and start again.
It looks anyway cleaner since I can very easily TChain later all files when reading. And last file is not growing forever.
Than you anyhow! Sandro

You could try using TTree::ChangeFile or the pattern:

TFile rootFile("pass1.root","recreate");
TTree *evnt = new TTree("eventData","event data");
...
loop
    evnt->Fill();
...
rootFile.Write();
evnt->SetDirectory(nullptr);
evnt->Reset();
rootFile.Close();
....
TFile rootFile2("pass2.root","recreate");
evnt->SetDirectory(&rootFile2);
...
loop
    evnt->Fill();
...
rootFile2.Write();
evnt->SetDirectory(nullptr);
evnt->Reset();
rootFile2.Close();