Home | News | Documentation | Download

Creating a Histogram Using ROOT from Python

Hello, I am trying to create a histogram using Root from Python. I created the histogram in python by writing:

“h1 = ROOT.TH1F(“h1”,” Some Title",500,0,5)

h1.Fill(theta)"

I then created a TFile objects so that ROOT can access the file in which I created my histogram files.
I wrote

“ThetaFile = ROOT.TFile(“Math.root”,“NEW”)”

Then in the ROOT prompt, I wrote

root [0] TFile *hfile = new TFile(“Math.root”);

root[1] TH1F histog = (TH1F) hfile->Get(“h1”);

root[2] histog->Draw()

And I don’t get a histogram. Instead I get this warning:

Error in : Trying to dereference null pointer or trying to call routine taking non-null arguments.
Execution of your code was aborted.
ROOT_prompt_3:1:1: warning: null passed to a callee that requires a non-null argument [-Wnonnull]
histo->Draw()
^~~~~

When I read about creating histograms, it writes that a histogram plot window should appear, but I am not seeing that. What am I doing wrong? Do I need to install something to see the histogram?

Try

TH1F *histog = (TH1F*) hfile->Get(“h1”);

Get returns a pointer to the histogram, not an instance of one.

I just tried that. What happens is that I get an empty histogram with only one entry? I am filling my histogram with a previously calculated variable called theta in my code. I started out with a text file that contained several hundred lines of data. I read the data and did some calculations on it to get a theta for each data line. It is with this theta that I want to fill the histogram with. But why is it empty?

Here is what I have written in my python code:

histo = ROOT.TH1F("histo","Histogram Title",100,-4,4)
    histo.SetDirectory(0)
    
    f = ROOT.TFile("angle.root","RECREATE")
   
    
    histo.Fill(theta) #where theta is a variable calculated in a for loop (written above in my code) so that there is a theta calculated for each data line 
     
   	histo.Write()
    f.Close()
    del f
    histo.Draw()

I have this still inside my for loop where I calculated theta.

More info on what may be going on. When I write root histo->Fill(theta), I get this error:
histo->Fill(theta)
input_line_44:2:44: error: use of undeclared identifier ‘theta’
((((class TH1F **)0x7f9ab3f50360))->Fill(theta))
^
Error in : Error evaluating expression (((
(class TH1F **)0x7f9ab3f50360))->Fill(theta)).
Execution of your code was aborted.

So, for some reason even though it is reading the file, it can’t identify theta??

histo.Fill needs to be called every time you calculate a new theta. It goes in the same loop. Your loop is not shown here, not sure how it’s being done exactly.

Look at the number of entries in the histogram shown in the stats box. The number of entries should equal the number of times histo.Fill is called.

Check the values you generate for theta. In your code above it theta is < -4 or > 4 then histo counts it as an entry, but it will not be displayed in the histogram because those are underflow and overflow entries. Look at the number of underflows and overflows in the histogram as reported in the stats box. You may even have unit issues such that you calculate radians but mean to fill with degrees. That’ll cause unintended over/underflows. So even if you calculate 5000 theta values and use histo.Fill, the number of events you see in the plot may be only one, while the rest go into under/overflow. Check to make sure this isn’t happening.

Before every call to histo.Fill print out the value of theta to see if they make sense.

I have this still inside my for loop where I calculated theta.

If that code is contained in your python loop, then the reason why you end up with only a single event in the histogram is because every time you run through your loop, you are opening a file, deleting any contents in that file, then creating a new histogram, putting one entry in the histogram, then closing the file.

The lines

histo = ROOT.TH1F("histo","Histogram Title",100,-4,4)
    histo.SetDirectory(0)
    
    f = ROOT.TFile("angle.root","RECREATE")

need to be placed before your loop

histo.Fill(theta)

must be in your loop

histo.Write()
    f.Close()
    del f
    histo.Draw()

goes after your loop.

histo.Fill is in my loop. I have print(theta) inside my loop and it prints all the theta values. histoFill is right underneath and yet histoFill just gives me one entry. Theta is just what I am calling a variable but there is no units associated with it (degrees or radians are irrelevant).

Ok, it seems like we replied at the same time. I am going to try your suggestion now.

Ok, trying the suggestion I get more than one entry (~15000 entries) but it is still empty. Is it how I am defining my underflow and overflow?

Probably. That’s why I suggested you print out the values you are using in the Fill command. Make sure they are within the limits you defined for the histogram. Simple programming mistakes can occur, so you might not be filling the histogram with the values you think you should be using. Just change your code a little bit to make your loop end after about 100 events while you print, and see what values you are printing and what is put in the histogram (are they underflows or overflows? the stats box can tell you this if you have it set to do that. Or you can also read the values in your ROOT session doing histo->GetBinContent(0) (underflow) histo->GetBinContent(N+1) where you replace N with the number of bins you declared for the histogram.

I got it. Thanks for clarifying what happens and how to fix it.