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:
- I create TFile object (now it become current directory)
- 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.