Yuri R. Tonin
Yuri R. Tonin

Reputation: 49

Python - Can't implement Scipy fitting script

I am trying to implement the Scipy script from section "Simplifying the syntax" here: http://scipy-cookbook.readthedocs.io/items/FittingData.html

My code is quite long, so I'll post only the parts that seem to be the problem.

I get the following error message: TypeError: unsupported operand type(s) for *: 'int' and 'Parameter', which I understand why it happens: it's the product in this part: return self.amplitude() * np.exp(-1*self.decay_const()*x)

class Plot():

    def __init__(self,slice_and_echo,first_plot,right_frame):

        self.slice_and_echo = slice_and_echo
        self.first_plot     = first_plot
        self.right_frame    = right_frame

        self.amplitude = Parameter(1)
        self.decay_const = Parameter(1)

    def function(self,x):
        print(self.amplitude)
        print(self.amplitude())
        return self.amplitude() * np.exp(-1*self.decay_const()*x)

    def create_plot(self):
        plot_figure = Figure(figsize=(10,10), dpi=100)
        self.the_plot = plot_figure.add_subplot(111)

        self.the_plot.plot(self.echoes,self.average,'ro')

        print(self.amplitude())

        self.fit_parameters = self.fit(self.function,[self.amplitude,self.decay_const],self.average)
        print(self.fit_parameters)


    def fit(self,function, parameters, y, x=None):

        def f(params):
            i = 0
            for p in parameters:
                p.set(params[i])
                i += 1
            return y - function(x)

        if x is None: x = np.arange(y.shape[0])

        p = [param for param in parameters]

        return optimize.leastsq(f, p)

and the Parameter() class is the same as in the link:

class Parameter:
    def __init__(self, value):
            self.value = value

    def set(self, value):
            self.value = value

    def __call__(self):
            return self.value

The issue seems to be that, when I call self.amplitude() inside of the create_plot(self): method, the value it returns is an integer (which is what I want!). But that doesn't happen when I call it inside of the function(self,x) method; when I print it inside this method I get: <__main__.Parameter object at 0x1162845c0> instead of the integer 1.

Why would it return different values when called from different methods in the same class? What am I missing here?

Thank you!

Upvotes: 0

Views: 53

Answers (1)

9dogs
9dogs

Reputation: 1476

You got a typo in list comprehension. Your code states:

p = [param for param in parameters]

and the example code states:

p = [param() for param in parameters]

Note that in your case you are generating a list of objects of type Parameter instead of a list of numbers.

By the way, check out module called lmfit - it simplifies fitting routines by great deal.

Upvotes: 1

Related Questions