Classes, attributes and functions in lmfit library

Question:

I have a general problem that I don’t know how to navigate library modules to get the result that I want. Here is an example of what I mean:
Let’s say I use lmfit library to do a fitting of a function:

from lmfit import Model, Parameters

#importing data

x=[-1.5933, -1.58, -1.5667, -1.5533, -1.54, -1.5267, -1.5133, -1.5, -1.4867, -1.4733, -1.46, -1.4467, -1.4333, -1.42, -1.4067, -1.3933, -1.38, -1.3667, -1.3533, -1.34, -1.3267, -1.3133, -1.3, -1.2867, -1.2733, -1.26, -1.2467, -1.2333, -1.22, -1.2067, -1.1933, -1.18, -1.1667, -1.1533, -1.14, -1.1267, -1.1133, -1.1, -1.0867, -1.0733, -1.06, -1.0467, -1.0333, -1.02, -1.0067, -0.9933, -0.98, -0.9667, -0.9533, -0.94, -0.9267, -0.9133, -0.9, -0.8867, -0.8733, -0.86, -0.8467, -0.8333, -0.82, -0.8067, -0.7933, -0.78, -0.7667, -0.7533, -0.74, -0.7267, -0.7133, -0.7, -0.6867, -0.6733, -0.66, -0.6467, -0.6333, -0.62, -0.6067, -0.5933, -0.58, -0.5667, -0.5533, -0.54, -0.5267, -0.5133, -0.5, -0.4867, -0.4733, -0.46, -0.4467, -0.4333, -0.42, -0.4067]

y=[0.0205, 0.0197, 0.0214, 0.0144, 0.0159, 0.0129, 0.0105, 0.0116, 0.0105, 0.0088, 0.0094, 0.0114, 0.009, 0.0102, 0.0099, 0.009, 0.0102, 0.0114, 0.0127, 0.011, 0.0134, 0.0143, 0.019, 0.0215, 0.0272, 0.0245, 0.0341, 0.0379, 0.0436, 0.0504, 0.0607, 0.0744, 0.0793, 0.0834, 0.1061, 0.1202, 0.1339, 0.1357, 0.1751, 0.1773, 0.1738, 0.1885, 0.201, 0.1995, 0.2058, 0.2039, 0.1893, 0.1856, 0.1693, 0.16, 0.1486, 0.1212, 0.1118, 0.0928, 0.0879, 0.0655, 0.0505, 0.0465, 0.039, 0.0308, 0.0304, 0.0259, 0.0221, 0.0205, 0.0212, 0.0196, 0.017, 0.0148, 0.0159, 0.0181, 0.0172, 0.0183, 0.0156, 0.0165, 0.0163, 0.0186, 0.0136, 0.0129, 0.0143, 0.0125, 0.0142, 0.0096, 0.0111, 0.0136, 0.0101, 0.0106, 0.009, 0.0094, 0.0079, 0.0081]


#creating params object from Parameters class
params=Parameters()

#writing initial parameters
params.add('a', value=-2.8e-04)
params.add('b', value=0.003)
params.add('int', value=0.2, min=0.01)
params.add('pos', value=-1, min=-1.2, max=0.8)
params.add('G', value=0.05, min = 0.005, max=0.5)

def gaussian(x, int1, pos1, G1):
    return int1*exp(-(x-pos1)**2/G1**2)


model = Model(gaussian)
result = model.fit(y, params, x=x)
print(result.fit_report())

Now, if I want to specifically select one of the standard errors of the best fit results, I would do something like this:

result.params['a'].stderr

I know this is correct as I have tried it and it works, but I don’t know how I can conclude this myself by reading the original library code. In the example above, is "result" an object of the Model class? Is stderr an attribute?

Thank you!

Asked By: Amyx

||

Answers:

When you do

from lmfit import Model
mymodel = Model(gaussian)

then mymodel is an instance of an lmfit.Model. This object has a method called fit. When you run that with

result = mymodel.fit(y, params, x=x)

then result is the value returned by Model.fit. For lmfit.Model.fit, that return object is an instance of an lmfit.model.ModelResult. In Python, you cannot really know what the object returned by any method will be except by a) running the method and inspecting the results, or b) reading the actual documentation for that method and seeing what it promises the return object will be and trusting that documentation and trusting that you did not get some exception raised while running that method.

The lmfit documentation for Model.fit does say and point to the return value will be a ModelResult. It lists a pile of methods and attributes that this object will have. You can also inspect all of this yourself at runtime with type(result) and dir(result), which answer the questions of "what kind of thing is result?" and "what things does this result have?".

For a ModelResult, one of the attributes it has is params which is an lmfit.Parameters object — essentially a dictionary (+ a bit more that is not super-relevant here) with keys being "names of fitting parameters" and values being "fitting parameter objects". This will match very closely the params you passed in (which is also an instance of lmfit.Parameters) but will have values and attributes updated to reflect the result of running the fit method — the output Parameters. So

result.params['a']

is a lmfit Parameter, representing one of the values varied in a fit (though your model would not really have a Parameter named a, it would have Parameters with names int1, pos1, and G1). This lmfit.Parameter object will have several attributes: value for the parameter value (for the fit result, this will be the best-fit value), stderr with an estimate of the standard error, and several other attributes. As before, you can read the documentation for what those attributes are or explore this and any other object with dir().

None of this is particular to lmfit, it is just how Python works. Everything is an object, some are "standard types", some are custom-built, some are simple, and some are complicated. Objects have attributes (other objects). Some of those attributes are callable, and then called "methods". Running methods will return other objects, though some return None which is kind of like not returning anything at all.

Answered By: M Newville
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.