Which file TTree object writes to

I find big problem in how TTree works with files. I can’t connect TTree object with TFile i want to write to. If i want to read from file, it is not a problem, i just create TFile and read TTree object from it.
If i want to write to TFile:

  1. I create TFile object (now it become current directory)
  2. After that i create TTree object. TTree connected with my TFile object, and i can check it by calling TTree::GetCurrentFile() (adress of my TFile and result of GetCurrentFile will be the same).

But if i create another file before writing my TTree, TTree will write data to the last file. At the same time TTree::GetCurrentFile() will return link to first file.
Here is code that i took from tutorial (“tree1.C”) and modify a bit:

#include "TROOT.h"
#include "TFile.h"
#include "TTree.h"
#include "TBrowser.h"
#include "TH2.h"
#include "TRandom.h"

void tree1()
{
   //create a Tree file tree1.root
   TFile *f = 0;
   //create the file, the Tree and a few branches
   TFile f1("tree1.root","recreate"); 
   TTree t1("t1","a simple Tree with simple variables");
   cout<<">> f1: "<< &f1 << endl;  

   f = t1.GetCurrentFile();
   cout<<">> 1: "<< f << endl;  

   TFile f2("tree1_test1.root", "recreate");
   cout<<">> f2: "<< &f2 << endl; 
   //t1.ChangeFile(&f2);

   f = t1.GetCurrentFile();
   cout<<">> 2: "<< f << endl;

   Float_t px, py, pz;
   Double_t random;
   Int_t ev;
   t1.Branch("px",&px,"px/F");
   t1.Branch("py",&py,"py/F");
   t1.Branch("pz",&pz,"pz/F");
   t1.Branch("random",&random,"random/D");
   t1.Branch("ev",&ev,"ev/I");
   TFile f3("tree1_test2.root", "recreate");
   cout<<">> f3: "<< &f3 << endl; 

   f = t1.GetCurrentFile();
   cout<<">> 3: "<< f << endl;
   
   //fill the tree
   for (Int_t i=0;i<10000;i++) {
     gRandom->Rannor(px,py);
     pz = px*px + py*py;
     random = gRandom->Rndm();
     ev = i;
     t1.Fill();
  }

  TFile f4("tree1_test3.root", "recreate");
  cout<<">> f4: "<< &f4 << endl; 

  f = t1.GetCurrentFile();
  cout<<">> 4: "<< f << endl;

  //save the Tree header. The file will be automatically closed
  //when going out of the function scope
  t1.Write();
  f = t1.GetCurrentFile();
  cout<<">> 5: "<< f << endl;

}

Output is:

.x tree/tree1.C 
>> f1: 0xbfd9b880
>> 1: 0xbfd9b880
>> f2: 0xbfd9b438
>> 2: 0xbfd9b880
>> f3: 0xbfd9b1e0
>> 3: 0xbfd9b880
>> f4: 0xbfd9afa0
>> 4: 0xbfd9b880
>> 5: 0xbfd9b880

As i found from TBrowser, this code writes all data to “f4” (** tree1_test3.root**). Here is the output from bash du -sh tree1*:

220K	tree1.root
4,0K	tree1_test1.root
4,0K	tree1_test2.root
8,0K	tree1_test3.root

I don’t know what was written to tree1.root but if i delete it and then reload ROOT, TBrowser shows, that file tree1_test3.root contains TTree object with data i expected.

In this code i find another problem, line: t1.ChangeFile(&f2);
throws segmentation violation or abort root:

root [3] .x tree/tree1.C 
>> f1: 0xbfd9b890
>> 1: 0xbfd9b890
>> f2: 0xbfd9b448
Warning in <TTree::ChangeFile>: file tree1_test1_1.root already exist, trying with 2 underscores
Fill: Switching to new file: tree1_test1__1.root
munmap_chunk(): invalid pointer
miksarus@miksarus-VirtualBox:~/Documents$ 

If method called “ChangeFile” I expected, it will change TFile, my tree writes to, but it do something i can’t understand what…

Why it all important fo me: i want to use TTree inside my own classes, and i can’t guarantee that while using one TTree i will not want to open another file. And i can’t predict result of multithreading work of such classes as i don’t understand logic of working with TTree and TFile.

Please help me to understand how to safely connect my TTree with known TFile. I afraid that my TTree will want to write part of data from buffer during work with data.

If you want to write it to f1, try:

  f1->cd();

before writing the tree.

1 Like

thank you, it works :blush:
But as for me, it is very “curve logic”.

Not just for you.

We are re-working many of the key ROOT features to behave more along the lines of what people would expect these days; examples are ROOT::RDataFrame and ROOT’s coming histogram classes ROOT::Experimental::RHist, as well as a new GUI / graphics system (webGUI) and even a TTree successor (currently called ROOT::Experimental::RForest). All of that sails under the flag “ROOT7”. I.e. we agree and we’re working on the remedy!