Return type of model.eval(...)

42 views
Skip to first unread message

Christoph Rosemann

unread,
Feb 12, 2019, 8:41:41 AM2/12/19
to lmfit-py
Hi,

I'm still finding some leftover issues from switching from a very ancient version of lmfit (shipped with Debian 8) to more recently outdated one (shipped with Debian 9). But the issue still exists with the most recent one (current pip install: v0.9.12).

Testcode:
from lmfit.models import LinearModel as lm
linmodel
= lm()
from lmfit.models import ConstantModel as cm
constmodel
= cm()

import numpy as np
xdata
= np.linspace(0,10,11)

linpoints
= linmodel.eval(x=xdata, intercept=1., slope=2.)
constpoints
= constmodel.eval(x=xdata, c=2.)

print("linear: " + str(type(linpoints)))
print("constant: " + str(type(constpoints)))

It was -- and is supposed to be -- to return <class 'numpy.ndarray'> in any case (e.g. https://lmfit.github.io/lmfit-py/model.html#model-class-methods).

But it turns out that in the case of a ConstantModel it's a different type; which creates some problems, at least for me.

Cheers,
Christoph

Matt Newville

unread,
Feb 12, 2019, 9:11:01 AM2/12/19
to lmfit-py
Hi Christoph,


Yeah, that is a problem.  I think that `Model.eval()` would have to be changed to 
    `return np.asarray(func(**self.make_funcargs(params, kwargs))`

This would complicate (somewhat) the case where `Model.eval()` is given a float as `x` (as in "evaluate this model at a particular value for the independent variable").   Currently, that returns a float, and with this change it would return an ndarray of length 1.
But that is what the documentation says, so at least that is defensible!

Anyone have a strong opinion on this?  I don't if anyone is relying on the type returned from evaluating of a model at a single value for the independent variable(s).

--Matt

Christoph Rosemann

unread,
Feb 12, 2019, 10:01:31 AM2/12/19
to lmfit-py

Hi Matt,

On Tuesday, February 12, 2019 at 3:11:01 PM UTC+1, Matt Newville wrote:

Yeah, that is a problem.  I think that `Model.eval()` would have to be changed to 
    `return np.asarray(func(**self.make_funcargs(params, kwargs))`

This would complicate (somewhat) the case where `Model.eval()` is given a float as `x` (as in "evaluate this model at a particular value for the independent variable").   Currently, that returns a float, and with this change it would return an ndarray of length 1.
But that is what the documentation says, so at least that is defensible!

Anyone have a strong opinion on this?  I don't if anyone is relying on the type returned from evaluating of a model at a single value for the independent variable(s).

--Matt

I'm not stating that the documentation is wrong per se. But I think it is a bit misleading at least. If the data parameter ("x=...") is provided, I would expect that the return value has the same type, as well as the same mathematical dimension (size()) as that given data.

Implicitly I would expect that there is some function -- or model -- and one would like to evaluate it at the provided values. Regardless of what the function/model is. This is the part that somewhat astounded me, as can be seen from the test snippet.

To me it seems very annoying, if not plainly wrong, to effectively overload the return type of a method depending on the subtype of the object.

Cheers, Christoph

Matt Newville

unread,
Feb 12, 2019, 11:47:01 AM2/12/19
to lmfit-py
Hi,

On Tue, Feb 12, 2019 at 9:01 AM Christoph Rosemann <mymindis...@gmail.com> wrote:

Hi Matt,

On Tuesday, February 12, 2019 at 3:11:01 PM UTC+1, Matt Newville wrote:

Yeah, that is a problem.  I think that `Model.eval()` would have to be changed to 
    `return np.asarray(func(**self.make_funcargs(params, kwargs))`

This would complicate (somewhat) the case where `Model.eval()` is given a float as `x` (as in "evaluate this model at a particular value for the independent variable").   Currently, that returns a float, and with this change it would return an ndarray of length 1.
But that is what the documentation says, so at least that is defensible!

Anyone have a strong opinion on this?  I don't if anyone is relying on the type returned from evaluating of a model at a single value for the independent variable(s).

--Matt

I'm not stating that the documentation is wrong per se. But I think it is a bit misleading at least. If the data parameter ("x=...") is provided, I would expect that the return value has the same type, as well as the same mathematical dimension (size()) as that given data.

Yeah, that might seem like the simple, obvious choice.  Reality is slightly more complicated ;).  That is, it might seem like `x` should obviously be either a scalar float or an ndarray, but we try hard to allow `x` to be truly independent.  For sure, it could be a pandas Series, but there can be multiple independent variables, not all have to be numeric.  Independent variables can be any type,  including user defined objects.

That means we cannot coerce the result of evaluating the model function to match the type of `x`.   The result of the model function has to be coercable to a 1d numpy array.



Implicitly I would expect that there is some function -- or model -- and one would like to evaluate it at the provided values. Regardless of what the function/model is. This is the part that somewhat astounded me, as can be seen from the test snippet.

Well, then it could be viewed as sane that ConstantModel returns a float, right?  It deliberately does not depend on `x`.  I don't have a strong opinion...


To me it seems very annoying, if not plainly wrong, to effectively overload the return type of a method depending on the subtype of the object.

But that is not what happens.  The model function is evaluated using its inputs, and its result is returned.  Currently, it really is not more complicated than that.  It could be more complicated in that we could force the result to be an ndarray.  To be clear, for a ConstantModel, that would be an ndarray of length 1.



Cheers, Christoph

--
You received this message because you are subscribed to the Google Groups "lmfit-py" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lmfit-py+u...@googlegroups.com.
To post to this group, send email to lmfi...@googlegroups.com.
Visit this group at https://groups.google.com/group/lmfit-py.
To view this discussion on the web visit https://groups.google.com/d/msgid/lmfit-py/d4491830-c53c-450b-8377-b375cc0dc532%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Hope that helps, 

--Matt
Reply all
Reply to author
Forward
0 new messages