If TH1::FillN() is not working with numpy arrays, this may be the cause of your error. If a 1-D slice of a numpy array is taken, the dimension from which the slice is taken from matters. Even if the slice is reduced to a 1-D numpy array and has the shape (N,), whether or not this is from rank ‘m’ will make the difference between FillN succeeding or crashing. I have demonstrated this bug in the following MWE.
import numpy as np import ROOT A = np.random.normal(loc=0.0, scale=1.0, size=(1000,)) weights = np.ones(1000) th1d_A = ROOT.TH1D('test_th1_A', 'Test', 100, -1.0, 1.0) print(type(A)) print(A.shape) th1d_A.FillN(A.shape, A, weights) B = np.random.normal(loc=0.0, scale=1.0, size=(1000,2)) B_slice_copy = np.ndarray.copy(B[:,0]) th1d_B = ROOT.TH1D('test_th1_B', 'Test', 100, -1.0, 1.0) th1d_B.FillN(B_slice_copy.shape, B_slice_copy, weights) B_slice_transp = B_slice_transp = np.random.normal(loc=0.0, scale=1.0, size=(2,1000))[1,:] th1d_C = ROOT.TH1D('test_th1_C', 'Test', 100, -1.0, 1.0) th1d_C.FillN(B_slice_transp.shape, B_slice_transp, weights) B_slice = B[:,1] print(B.shape) print(type(B_slice)) print(B_slice.shape) th1d_D = ROOT.TH1D('test_th1_D', 'Test', 100, -1.0, 1.0) th1d_D.FillN(B_slice.shape, B_slice, weights)
What is happening here? Example A works fine as per the pyroot tutorial.
Example B will work because a new slot of memory is allocated, and the python pointer is pointing at this new memory. Example C works because it is sliced from dimension 0, i.e. [m,:]. Example D fails however because it uses a slice from dimension 2. This is extremely hard to catch because as I’ve shown, the two array slices will show up with the exact same shape and type as far as the python interpreter is concerned. The output is the following:
<class 'numpy.ndarray'> (1000,) (1000, 2) <class 'numpy.ndarray'> (1000,) Traceback (most recent call last): File "~/Projects/Experimental/test_filln_root.py", line 30, in <module> th1d_D.FillN(B_slice.shape, B_slice, weights) TypeError: none of the 2 overloaded methods succeeded. Full details: void TH1::FillN(int ntimes, const double* x, const double* w, int stride = 1) => TypeError: could not convert argument 2 (could not convert argument to buffer or nullptr) void TH1::FillN(int, const double*, const double*, const double*, int) => TypeError: takes at least 5 arguments (3 given)
ROOT Version: ROOT Version: 6.22/08
Platform: Built for linuxx8664gcc on Apr 14 2021, 11:53:00
For reference, this is the latest root build on conda-forge: :: Anaconda.org
Compiler: Not Provided