Hello,
I have recently made ‘brew upgrade’ (that was not a proper intension)
Now I can not get a list of TH1F from function in python 3.8 .
How should it be done?
The code takes a list of filenames and TH1F name and should give the list of TH1Fs
The code is below:
def get_hists(file_names, hist_name, mark):
NPoints = len(file_names)
h_array = [TH1F for y in range(0,NPoints)]
f = [TFile for y in range(0,NPoints)]
for i in range(0,NPoints):
f[i] = TFile.Open(file_names[i])
hist_new_name = hist_name+'_{0:d}'.format(i)+mark
h = f[i].Get(hist_name).Clone(hist_new_name)
h_array[i] = h
h_array[i].SetTitle(hist_new_name)
return h_array
This is how it is implemented:
files = ['FIle_0.root',...,'File_20.root']
h_array = [TH1F for i in range(0,NPoints)]
h_array = get_hists(files , 'h_y_endpoint', '_B0_i' )
c = TCanvas()
h_array[0].Draw()
All the list elements have ‘None’ type.
When I draw inside the function in the loop everything is OK.
But as soon as the file is changed, the histogram is ‘None’.
The error is:
File “./plot_Y.py”, line 268, in
h_array[0].Draw()
AttributeError: ‘CPyCppyy_NoneType’ object has no attribute ‘Draw’
From reading the code I don’t see any obvious problem, since you are cloning the histograms, so that when the files are destroyed you should keep the cloned ones (their references are stored in h_array).
What happens if, after the loop (still inside the function), you try to Draw h_array[0]?
Hello,
Inside the function, it works without errors
Here is how print (h_array) works before (0), inside (1) and after (2) the function
`
print(h_array)
Hello,
I think it was 20.04, I will try to switch back to it
By the way,
Are you aware of this thing? https://root.cern.ch/root/html524/src/TMath.h.html#411
It was strongly criticized and recommended never to use ROOT for calculations during the sPHENIX collaboration meeting 2 days ago:
both with 6.22 and 6.20 and the result is the same: the final histogram becomes None because, when its TFile is being destructed, it destroys its associated histograms too. I think this is what happens in your code too.
In any case, there is a solution to free the histogram from being tied to the TFile. You need to write:
def get_hists(file_names, hist_name, mark):
NPoints = len(file_names)
h_array = [TH1F for y in range(0,NPoints)]
f = [TFile for y in range(0,NPoints)]
for i in range(0,NPoints):
f[i] = TFile.Open(file_names[i])
hist_new_name = hist_name+'_{0:d}'.format(i)+mark
h = f[i].Get(hist_name).Clone(hist_new_name)
h.SetDirectory(0) # notice this line !!!!
h_array[i] = h
h_array[i].SetTitle(hist_new_name)
return h_array
As for the TMath question, perhaps @moneta can comment on it.
Hello @etejedor,
This solution is working
Thank you, the issue was probably due to the fact that previously I have not been using separate files, but was reading from one.
Thank you for noticing that TMath::Acos(2) returns 0. A protection to avoid values outside the [-1,1] range was added many years ago. I don’t know the reason. I think it is more correct to return a NaN as in std::acos.