Hello. This is my first forum post, so please forgive any transgressions.
I noticed some PyROOT behaviour recently and I donāt know if itās a bug or if this is the way itās supposed to be, so Iāll just describe what Iām doing and hope you can help me with thisā¦
Iāve been working on a sort of Python interface to TMinuit for performing simple one-dimensional function fits to data points. To take full advantage of Pythonās flexibility I have defined a fit function in Python which always takes the independent variable (x) as its first argument and the parameters as keyword arguments:
def expo(x, amplitude=.8, xcoefficient=.5):
return amplitude * exp(xcoefficient * x)
Iāve implemented a function (calculate_chi2) to calculate the chi^2 for a given parameter set and defined a FCN for TMinuit using the usual syntax (function_to_minimize), which I passed to TMinuit using SetFCN.
# calculate the chi^2 for the current parameters
def calculate_chi2(parameters):
result = 0.0
for i in range(number_of_points):
x = xdata[i]
# This doesn't work, presumably because the unpacking operator `*'
# doesn't behave well when used with buffers... (?):
fit_function_value_at_x = expo(x, *parameters)
y = ydata[i]
result += ((y-fit_function_value_at_x)*(y-fit_function_value_at_x))
return result
# this is passed to TMinuit.SetFCN
def function_to_minimize(number_of_parameters, derivatives, f, parameters, internal_flag):
f[0] = calculate_chi2(parameters)
# refer TMinuit to the aforementioned FCN
gMinuit = TMinuit(number_of_parameters)
gMinuit.SetFCN(function_to_minimize)
The result was that everything failed with a MemoryError. Debugging on the Python side says the culprit is the line "fit_function_value_at_x = expo(x, parameters)" in calculate_chi2. Also, I expected the parameter vector to be passed as a Python list, or in any case as an iterable, so the unpacking operator () will work on it.
I donāt really understand the mechanics of C++ communicating with Python, but is there any way the pythonization of TMinuit could be improved upon/expanded, so the unpacking operator could be used in the above code without causing a MemoryError?
Iāve found a temporary workaround by putting the parameters in a Python iterable (e.g. a list) and unpacking that when passing to the fit function. What I thought this would do is actually bring C++ data to the Python side, so that Python (and the * operator) can work with it, but Iām afraid this translation doesnāt scale well with large inputs (making fits with a lot of plot points slower than necessary).
# temporary workaround -> put the parameters in a list, which
# can be unpacked by `*'... (slow?)
parameter_list = []
for j in range(number_of_parameters):
parameter_list.append(parameters[j])
fit_function_value_at_x = expo(x, *parameter_list)
Any thoughts?