Write TH1 in root file

Hello, I’ve to save a TH1 in a ROOT file and print it in a pdf file.

It works for the pdf file, but not for root file. I.e. It creates the file but it doesn’t write the TH1.
Moreove, I read
Error in <TFile::WriteTObject>: Directory MC_300.0kev_br3.root is not writable

but that file is only read-mode.

Here the in files and the macro


Hi @faca87,

did you forget to attach the ROOT macro so that we can take a look?


Hi @jalopezg ,
The macro is in the we transfer link together with the root files

Hi @dastudillo ,
I’m not sure to understand what you mean…
I added


but I get same problems than previously.

Dear @faca87 ,

First, a disclaimer

Your code is full of new without a single delete. This is extremely bad practice, please refrain from it, use std::unique_ptr sparingly and just declare most if not all of your objects on the stack.

Secondly, do not use raw c-style casts like (TH1D*)myobj. If you really need to cast an object to another type, prefer static_cast or dynamic_cast depending on your needs.

Back to your issue

In your code, I see the following

	TH1D *dati1 = (TH1D*) dati->Clone();

I would like to bring to your attention the call to Write. Where would you expect that call to write your histogram? I see many TFiles being opened in your application, for example:

	TFile *ROOTOut = new TFile(FileOut.c_str(),"RECREATE");
	TFile *ROOTData = TFile::Open(FileData.c_str(),"READ");

And then this other for loop which opens more files

	TFile *ROOTMC[Nbr];
	for (int j=0; j<Nbr; j++) {
		ROOTMC[j] = TFile::Open(FileMC[j].c_str(),"READ");
		mc[j] = (TH1D*)ROOTMC[j]->Get(Hist_MC.c_str());

So, in which file specifically would you expect the Write operation to write the file?

If the answer is ROOTOut, then your expectation is wrong. By default, some ROOT objects that have the Write method will be written in the latest opened file (also aliased by the variable gDirectory). It’s important that you know/remember what this variable is pointing to at any given point of your application.

Or, as a better solution, you can be more explicit about what object you want to write to what file, i.e.

ROOTOut->WriteObject(myhisto, "name_of_the_histo");


1 Like

Hi @vpadulan thank you for your help and also your suggestions.

This option

works but if I write the histo i.e. for example

ROOTOut->WriteObject(dati1, "dati1");

ROOT writes only the dati1 histo but, on the contrary, I’ve other histo (mc_tot) to write in the same canvas, the legend, etc.

I tried to add options:

ROOTOut->WriteObject(mc_tot, "mc_tot", "hist same");
ROOTOut->WriteObject(dati1, "dati1", "e0 same");
ROOTOut->WriteObject(legend1, "legend1", "same");
ROOTOut->WriteObject(legend2, "legend2", "same");

but it didn’t work.

I then tried to write the full canvas, i.e.

ROOTOut->WriteObject(c, "c");

and I got the total canvas (i.e. the two histos and the two legends), but I couldn’t find a way to set the axis.

ROOTOut->WriteObject(dati1, "dati1");

This does what you expect, it writes the dati1 TH1 object to the file with key "dati1". Consequently, you could call this line for every object you need to store:

ROOTOut->WriteObject(dati1, "dati1");
ROOTOut->WriteObject(mc_tot, "mc_tot");
ROOTOut->WriteObject(legend1, "legend1",);
ROOTOut->WriteObject(legend2, "legend2");

I don’t understand why you would expect such a call to work WriteObject(legend2, "legend2", "same");. Is there any place in the documentation that tells you that WriteObject can accept the options that Draw accepts? A search in the docs would have told you otherwise.

Sure, I guess you can store the whole canvas in the file. Then retrieve at some following time. I don’t know what advantage this gives you practically.

I would just save all the histograms you need to the file, then plot them as needed in a separate plotting script. This is a cleaner approach and I believe more portable in general.


Hi @vpadulan , sorry I’ve just noticed your reply!
Thanks !

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.