Problem writing to a file


I have a problem when trying to write a tree to a file (opened in “recreate” mode), while having other files opened in “read” mode. Root seems to try and write into one of the read-only files, since I get the message

Some more details:
I have created classes (PData and PAnalysis), which open files and read trees when instanciated.
For PAnalysis (an object of this class is created at the very beginning of the program):

PAnalysis::PAnalysis(...){ myOutputFile = (TFile*) new TFile(..., "RECREATE"); myTree = (TTree*) new TTree("name","name"); myTree->Branch("blah",&variable); ... }

Then, a few PData objects are created, where:

PData::PData(...){ myFile = (TFile*) new TFile((xxx), "READ"); myTree = (TTree*) myFile->Get("Event"); ... }

The program then calls member functions of the PAnalysis object, which read the trees “owned” by the PData objects and fill the tree owned by the PAnalysis object. Then, I want to call this member function:

PAnalysis::WriteOutput(){ myTree->Write(); }
… But I get the error quoted above.

Actually, I get the same error when simply trying to write, say, a canvas owned by a PAnalysis object. In this particular case, it did work when I created the canvas, opened the writable file, wrote the canvas, and closed the file in the same member function. But of course this doesn’t work for the tree anymore, since it is always created at instanciation.

I’ve searched this forum and the internet for people having similar problems, but I couldn’t find a satisfactory answer and I don’t understand what I’m doing wrong in the order I open, read and write my files and trees…



Use :

PAnalysis::WriteOutput(){ myOutputFile->Write(); }

The documentation for TTree::Write reads:

Int_t TTree::Write(const char *name, Int_t option, Int_t bufsize) { // Write this object to the current directory. For more see TObject::Write // If option & kFlushBasket, call FlushBasket before writing the tree.
where the ‘current’ directory may or may not be associated with the TTree (and is not in your case).


Thank you for your answer!

In regard of what you’re suggesting, in the end the best way to proceed (since calling myOutputFile->Write(); only writes myTree and not the other objects, such as histograms) would simply be to call myOutputFile->cd(); before myTree->Write(); etc.

This way it seems to work, but I don’t understand why myTree is not associated with myOutputfile… And if it’s not, why calling myOutputFile->Write(); succeeds in writing myTree, but without writing the other objects (canvases, histograms) I create after opening myOutputFile…



[quote]but I don’t understand why myTree is not associated with myOutputfile… [quote]I am not sure what you mean. For example:myTree->GetDirectory()->cd(); myTree->Write();should have the exact same effect as your latest solution. It is the semantic of TTree::Write (and TObject::Write) to ignore any previous configuration of the TTree (object) and write in the current directory at the time of execution of Write.

[quote]but without writing the other objects (canvases, histograms) I create after opening myOutputFile…[/quote][/quote][/quote]Most likely, the current directory is not the intended one when creating the histogram. Since you are using both histogram and canvas, you simplest solution is to explicitly call myOutputFile->Append on each of them (for histogram you can also call histo->SetDirectory(myOutputFile)).


Thank you, this does work as well!

But there’s still something weird: when I append the tree to the output file (at the same place in the program where I wanted to write it), and then write the file, the tree appears… twice in the file!


This is expected. TTree (and histogram) add themselves to the directory that current at the time of their creation. (So the TTree is already in the list)