Closed 1000NightsAKnight closed 1 year ago
The main issue is that we need a symbolic expression of your function, with (ideally) defined derivatives. We use sympy for all symbolic operations, so look there to find a symbolic equivalent function, or open an issue/feature request there. Otherwise you could try going for a https://symfit.readthedocs.io/en/stable/module_docs.html#symfit.core.models.CallableNumericalModel, but I don't know the required syntax from the top of my head.
Thanks for the reply @pckroon. As you advised, I did look at sympy to find a symbolic equivalent function. It tells me that Ei(z), as used in my my code is that function. However, I still get the following error: 'NameError: name 'Ei' is not defined'.
You do need to import the Ei
from sympy (not symfit) before using it of course.
I tried to follow your advice, @pckroon, by adding to my header the line: import sympy as sp
I then modified the original functions mod1
and mod2
to:
def mod1(data, a_decay, b_decay, constant, on1_a_amplitude, on1_b_amplitude, ARE_A, ARE_B): # not all parameters are used here
first_term_a = sp.Ei(-data/a_decay)
second_term_a = (sp.Ei(-data*(1+ARE_A*a_decay)/a_decay))
first_term_b = (sp.Ei(-data/b_decay))
second_term_b = (sp.Ei(-data*(1+ARE_B*b_decay)/b_decay))
return constant+on1_a_amplitude*(first_term_a-second_term_a+sf.log(1+ARE_A*a_decay)) + on1_b_amplitude*(first_term_b-second_term_b+sf.log(1+ARE_B*b_decay))
def mod2(data, a_decay, b_decay, constant, on2_a_amplitude, on2_b_amplitude, ARE_A, ARE_B): # not all parameters are used here
first_term_a = (sp.Ei((t2-t1-data)/a_decay)) - (sp.Ei((t2-data)/a_decay))
second_term_a = (sp.Ei((t2-data)*(1+ARE_A*a_decay)/a_decay)) - (sp.Ei((t2-t1-data)*(1+ARE_A*a_decay)/a_decay))
third_term_a = (sp.Ei((t2-data)/a_decay)) -(sp.Ei((t2-data)*(1+ARE_A*a_decay)/a_decay)) + sf.log(ARE_A*a_decay)
first_term_b = (sp.Ei((t2-t1-data)/b_decay)) - (sp.Ei((t2-data)/b_decay))
second_term_b = (sp.Ei((t2-data)*(1+ARE_B*b_decay)/b_decay)) - (sp.Ei((t2-t1-data)*(1+ARE_B*b_decay)/a_decay))
third_term_b = (sp.Ei((t2-data)/b_decay)) - (sp.Ei((t2-data)*(1+ARE_B*b_decay)/b_decay)) + sf.log(ARE_B*b_decay)
return constant+on2_a_amplitude*(sf.exp((t1-t2)/a_decay)*(first_term_a+second_term_a)+third_term_a)+on2_b_amplitude*(sf.exp((t1-t2)/b_decay)*(first_term_b+second_term_b)+third_term_b)
I still get the same 'NameError: name 'Ei' is not defined' error.
I did a bit more digging. The issue is that Ei
cannot be lambdified by sympy lambdify
(which we use internally). Consider the following snippet:
from sympy import Symbol, Ei, lambdify
x = Symbol('x')
expr = Ei(x)
f = lambdify([x], expr, dummify=False)
f(3)
This gives the NameError
.
We could monkeypatch this in symfit.core.printing
, but I'm really not enthusiastic about that. I'd much rather see this fixed in sympy.
Hello @pckroon. Thanks for continuing to dig. I believe I have encountered the same complaint against sympy here. Is there a work around or do I have to open a sympy issue/feature request?
Yes, that's the same (or at least very similar) issue. Please do open an issue at sympy regarding Ei, since there seems to be a clear scipy implementation.
@pckroon I did open the issue at sympy and got the response that the Ei
can be lambdified. Can you suggest what else the problem might be?
@pckroon My attempt to open an issue at sympy regarding Ei
doesn't seem to have gone anywhere. Do we have further recourse?
You got a reply on your sympy issue that you never responded to. Summary is that this is fixed in sympy==1.12
@pckroon I did indeed get a reply. But I am not sure what kind of response I could have given since my problem is with symfit
. In other words: the problem of lambdifying Ei
is fixed in sympy==1.12
. Is it therefore fixed in symfit
?
Yes.
@pckroon Thanks! I will try it shortly.
I asked this question first on stackoverflow, though this might be the more appropriate place. My objective function contains exponential integrals, Ei, but this results in a name error. i.e. 'Name Error: name 'Ei' is not defined,' which I have not been able to solve.
Regards, Ricardo