Python - Can't implement Scipy fitting script - python

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!

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.

Related

Python class call a method from a class object

How can I fix attribute error in this situation? I have a pandas dataframe where I make some data slicing and transformation and I want to plot the results of the persistence_model function like below.
Edit:
I want to customize a function with specific title of the plot, y and x axis and create a horizontal line on the same plot from the results of persitence_model function.
class ResidualErrors():
def __init__(self, data: pd.Series):
self.data = data
def _persistence_forecast_model_nrows(self, test_rows):
slicer = test_rows + 1
errors = self.data[-slicer:].diff().dropna()
return errors
def _persistence_forecast_model_percrows(self, train_perc):
n = len(self.data)
ntrain = int(n * train_perc)
errors = self.data[ntrain:].diff().dropna()
return errors
def persistence_model(self, test_rows=None, train_perc=None):
if (not test_rows) and (not train_perc):
raise TypeError(r"Please provide 'test_rows' or 'train_perc' arguments.")
if test_rows and train_perc:
raise TypeError(r"Please choose one argument either 'test_rows' or 'train_perc'.")
if test_rows:
return self._persistence_forecast_model_nrows(test_rows)
else:
return self._persistence_forecast_model_percrows(train_perc)
#classmethod
def plot_residuals(obj):
obj.plot()
plt.show()
Desired output
res = ResidualErrors(data).persistence_model(test_rows=10)
res.plot_residuals()
>> AttributeError: 'Series' object has no attribute 'plot_residuals'
You need to be more aware of what methods return. The first step creates a ResidualErrors object:
res = ResidualErrors(data)
The second step creates a DataFrame or Series:
obj = res.persistence_model(test_rows=10)
You can call plot_residuals on res but not on obj, as you are currently doing:
res.plot_residuals(obj)

TypeError: cannot unpack non-iterable GetColorImage object

i have following situation:
cratecolor.py: (code stripped to its minimum...)
import ... ...
class GetColorImage:
def __init__(self, ia=None):
self.path = None
self.img = None
self.img0 = None
self.s = None
self.basetime = 0
self.count = 0
self.stride = 32
self.ia = ia
self.img_size = 640
self.auto = True
self.getImage()
def getImage(self):
self.ia.remote_device.node_map.ExposureTime.value = 350
self.ia.remote_device.node_map.Gain.value = 150
...
...
print(color, l) # prints: 1 59.64829339143065
return color, l
main.py: (code stripped to its minimum)
...
...
# code exectued on a qthread:
def getcolor(self, idin):
color, lightness = cratecolor.GetColorImage(ia=self.ia) #******
print(color, lightness)
In the line marked with ***** i get the error message color, lightness = cratecolor.GetColorImage(ia=self.ia) TypeError: cannot unpack non-iterable GetColorImage object but i dont get why.
any help appreciated.
You cannot return values from an __init__ function, so you instead must either:
Call the getImage() method when creating the class
Define an __iter__ method for the class to automatically allow you to assign it to multiple variables.
The second one is probably the better solution. Here is the method you would add to the class for it to work:
def __iter__(self):
return iter(self.getImage())
To unpack a object, you must ensure that it is iterable:
>>> class Foo:
... def __iter__(self): return iter(range(2))
...
>>> a, b = Foo()
>>> a
0
>>> b
1
So, you should make your class iteratable:
class GetColorImage:
...
def __iter__(self):
return iter(self.getImage())
You're returning a GetColorImage object, not the two values you're actually looking for. The return statement in getImage() just returns the values to your constructor and does nothing with them. The constructor finishes and the whole GetColorImage object is returned. If you try to return something else from the constructor, you'll get an error.
You could just create the object and then call getImage():
colorObj = cratecolor.GetColorImage(ia=self.ia)
color, lightness = colorObj.getImage()
As pointed out below, you can just chain them if you don't need the object:
color, lightness = cratecolor.GetColorImage(ia=self.ia).getImage()

Replacing multiple `if-else` with single `if-else` in a class [duplicate]

This question already has answers here:
How to call Python functions dynamically [duplicate]
(11 answers)
Calling a function of a module by using its name (a string)
(18 answers)
Closed 3 years ago.
So this is more of a trivial problem of writing a clean Python3 code. Let's say I have a class function which can create many function types based on the user input.
import numpy as np
class functions(object):
def __init__(self, typeOfFunction, amplitude, omega, start = None, stop = None,
pulsewidth = None):
self.typeOfFunction = typeOfFunction
self.amplitude = amplitude
self.omega = omega
self.period = 2 * np.pi/omega
self.start = start
self.stop = stop
self.pulsewidth = pulsewidth
def sine_function(self, t):
func = self.amplitude * np.sin(self.omega*t)
return func
def cosine_function(self, t):
func = self.amplitude * np.cos(self.omega*t)
return func
def unit_step_function(self, t):
func = self.amplitude * np.where(t > self.start, 1, 0)
return func
Now my question is let us say we want to write 3 other functions:
Differentiation
Integration
Evaluation at a given time.
Now my problem is that in each of these function I have to put conditions such as these:
def evaluate_function(self, time):
if(self.typeOfFunction == 'sine'):
funcValue = self.sine_function(time)
elif(self.typeOfFunction == 'cosine'):
funcValue = self.cosine_function(time)
elif(self.typeOfFunction == 'unit_step_function'):
funcValue = self.unit_step_function(time)
I want to do it only once in the __init__ method and at subsequent steps just pass the arguments instead of writing if-else:
def __init__(self, typeOfFunction, amplitude, omega, start = None, stop = None,
pulsewidth = None):
self.typeOfFunction = typeOfFunction
self.amplitude = amplitude
self.omega = omega
self.period = 2 * np.pi/omega
self.start = start
self.stop = stop
self.pulsewidth = pulsewidth
#DO SOMETHING THAT MAKES THE TYPE OF FUNCTION EMBEDDED
IN THE CLASS IN A CLASS VARIABLE
And then:
def evaluate_function(self, time):
value = self.doSomething(time)
return value
How can this be done? If duplicate question exists please inform me in the comments.
You can use the method getattr(CLASS_OBJECT, METHOD_ORVARIABLE_NAME) like this:
method = getattr(self, self.typeOfFunction)
and then call method:
method()
or for short:
getattr(self, self.typeOfFunction)()
Also you can check if the attribute you are getting exist or not:
if hasattr(self, self.typeOfFunction):
getattr(self, self.typeOfFunction)()
I think you want a mapping with a dict.
Something like this:
class functions(object):
def evaluate_function(self, which, time):
mapping = {'sine': self.sine_function,
'cosine': self.cosine_function,
# ...more functions here...
}
return mapping[which](time)
# rest of class here...

Printing an object python class

I wrote the following program:
def split_and_add(invoer):
rij = invoer.split('=')
rows = []
for line in rij:
rows.append(process_row(line))
return rows
def process_row(line):
temp_coordinate_row = CoordinatRow()
rij = line.split()
for coordinate in rij:
coor = process_coordinate(coordinate)
temp_coordinate_row.add_coordinaterow(coor)
return temp_coordinate_row
def process_coordinate(coordinate):
cords = coordinate.split(',')
return Coordinate(int(cords[0]),int(cords[1]))
bestand = file_input()
rows = split_and_add(bestand)
for row in range(0,len(rows)-1):
rij = rows[row].weave(rows[row+1])
print rij
With this class:
class CoordinatRow(object):
def __init__(self):
self.coordinaterow = []
def add_coordinaterow(self, coordinate):
self.coordinaterow.append(coordinate)
def weave(self,other):
lijst = []
for i in range(len(self.coordinaterow)):
lijst.append(self.coordinaterow[i])
try:
lijst.append(other.coordinaterow[i])
except IndexError:
pass
self.coordinaterow = lijst
return self.coordinaterow
However there is an error in
for row in range(0,len(rows)-1):
rij = rows[row].weave(rows[row+1])
print rij
The outcome of the print statement is as follows:
[<Coordinates.Coordinate object at 0x021F5630>, <Coordinates.Coordinate object at 0x021F56D0>]
It seems as if the program doesn't acces the actual object and printing it. What am i doing wrong here ?
This isn't an error. This is exactly what it means for Python to "access the actual object and print it". This is what the default string representation for a class looks like.
If you want to customize the string representation of your class, you do that by defining a __repr__ method. The typical way to do it is to write a method that returns something that looks like a constructor call for your class.
Since you haven't shown us the definition of Coordinate, I'll make some assumptions here:
class Coordinate(object):
def __init__(self, x, y):
self.x, self.y = x, y
# your other existing methods
def __repr__(self):
return '{}({}, {})'.format(type(self).__name__, self.x, self.y)
If you don't define this yourself, you end up inheriting __repr__ from object, which looks something like:
return '<{} object at {:#010x}>'.format(type(self).__qualname__, id(self))
Sometimes you also want a more human-readable version of your objects. In that case, you also want to define a __str__ method:
def __str__(self):
return '<{}, {}>'.format(self.x, self.y)
Now:
>>> c = Coordinate(1, 2)
>>> c
Coordinate(1, 2)
>>> print(c)
<1, 2>
But notice that the __str__ of a list calls __repr__ on all of its members:
>>> cs = [c]
>>> print(cs)
[Coordinate(1, 2)]

Mathematical equation manipulation in Python

I want to develop a GUI application which displays a given mathematical equation. When you click upon a particular variable in the equation to signify that it is the unknown variable ie., to be calculated, the equation transforms itself to evaluate the required unknown variable.
For example:
a = (b+c*d)/e
Let us suppose that I click upon "d" to signify that it is the unknown variable. Then the equation should be re-structured to:
d = (a*e - b)/c
As of now, I just want to know how I can go about rearranging the given equation based on user input. One suggestion I got from my brother was to use pre-fix/post-fix notational representation in back end to evaluate it.
Is that the only way to go or is there any simpler suggestion?
Also, I will be using not only basic mathematical functions but also trignometric and calculus (basic I think. No partial differential calculus and all that) as well. I think that the pre/post-fix notation evaluation might not be helpful in evaluation higher mathematical functions.
But that is just my opinion, so please point out if I am wrong.
Also, I will be using SymPy for mathematical evaluation so evaluation of a given mathematical equation is not a problem, creating a specific equation from a given generic one is my main problem.
Using SymPy, your example would go something like this:
>>> import sympy
>>> a,b,c,d,e = sympy.symbols('abcde')
>>> r = (b+c*d)/e
>>> l = a
>>> r = sympy.solve(l-r,d)
>>> l = d
>>> r
[(-b + a*e)/c]
>>>
It seems to work for trigonometric functions too:
>>> l = a
>>> r = b*sympy.sin(c)
>>> sympy.solve(l-r,c)
[asin(a/b)]
>>>
And since you are working with a GUI, you'll (probably) want to convert back and forth from strings to expressions:
>>> r = '(b+c*d)/e'
>>> sympy.sympify(r)
(b + c*d)/e
>>> sympy.sstr(_)
'(b + c*d)/e'
>>>
or you may prefer to display them as rendered LaTeX or MathML.
If you want to do this out of the box, without relying on librairies, I think that the problems you will find are not Python related. If you want to find such equations, you have to describe the heuristics necessary to solve these equations.
First, you have to represent your equation. What about separating:
operands:
symbolic operands (a,b)
numeric operands (1,2)
operators:
unary operators (-, trig functions)
binary operators (+,-,*,/)
Unary operators will obviously enclose one operand, binary ops will enclose two.
What about types?
I think that all of these components should derivate from a single common expression type.
And this class would have a getsymbols method to locate quickly symbols in your expressions.
And then distinguish between unary and binary operators, add a few basic complement/reorder primitives...
Something like:
class expression(object):
def symbols(self):
if not hasattr(self, '_symbols'):
self._symbols = self._getsymbols()
return self._symbols
def _getsymbols(self):
"""
return type: list of strings
"""
raise NotImplementedError
class operand(expression): pass
class symbolicoperand(operand):
def __init__(self, name):
self.name = name
def _getsymbols(self):
return [self.name]
def __str__(self):
return self.name
class numericoperand(operand):
def __init__(self, value):
self.value = value
def _getsymbols(self):
return []
def __str__(self):
return str(self.value)
class operator(expression): pass
class binaryoperator(operator):
def __init__(self, lop, rop):
"""
#type lop, rop: expression
"""
self.lop = lop
self.rop = rop
def _getsymbols(self):
return self.lop._getsymbols() + self.rop._getsymbols()
#staticmethod
def complementop():
"""
Return complement operator:
op.complementop()(op(a,b), b) = a
"""
raise NotImplementedError
def reorder():
"""
for op1(a,b) return op2(f(b),g(a)) such as op1(a,b) = op2(f(a),g(b))
"""
raise NotImplementedError
def _getstr(self):
"""
string representing the operator alone
"""
raise NotImplementedError
def __str__(self):
lop = str(self.lop)
if isinstance(self.lop, operator):
lop = '(%s)' % lop
rop = str(self.rop)
if isinstance(self.rop, operator):
rop = '(%s)' % rop
return '%s%s%s' % (lop, self._getstr(), rop)
class symetricoperator(binaryoperator):
def reorder(self):
return self.__class__(self.rop, self.lop)
class asymetricoperator(binaryoperator):
#staticmethod
def _invert(operand):
"""
div._invert(a) -> 1/a
sub._invert(a) -> -a
"""
raise NotImplementedError
def reorder(self):
return self.complementop()(self._invert(self.rop), self.lop)
class div(asymetricoperator):
#staticmethod
def _invert(operand):
if isinstance(operand, div):
return div(self.rop, self.lop)
else:
return div(numericoperand(1), operand)
#staticmethod
def complementop():
return mul
def _getstr(self):
return '/'
class mul(symetricoperator):
#staticmethod
def complementop():
return div
def _getstr(self):
return '*'
class add(symetricoperator):
#staticmethod
def complementop():
return sub
def _getstr(self):
return '+'
class sub(asymetricoperator):
#staticmethod
def _invert(operand):
if isinstance(operand, min):
return operand.op
else:
return min(operand)
#staticmethod
def complementop():
return add
def _getstr(self):
return '-'
class unaryoperator(operator):
def __init__(self, op):
"""
#type op: expression
"""
self.op = op
#staticmethod
def complement(expression):
raise NotImplementedError
def _getsymbols(self):
return self.op._getsymbols()
class min(unaryoperator):
#staticmethod
def complement(expression):
if isinstance(expression, min):
return expression.op
else:
return min(expression)
def __str__(self):
return '-' + str(self.op)
With this basic structure set up, you should be able to describe a simple heuristic to solve very simple equations. Just think of the simple rules you learned to solve equations, and write them down. That should work :)
And then a very naive solver:
def solve(left, right, symbol):
"""
#type left, right: expression
#type symbol: string
"""
if symbol not in left.symbols():
if symbol not in right.symbols():
raise ValueError('%s not in expressions' % symbol)
left, right = right, left
solved = False
while not solved:
if isinstance(left, operator):
if isinstance(left, unaryoperator):
complementor = left.complement
right = complementor(right)
left = complementor(left)
elif isinstance(left, binaryoperator):
if symbol in left.rop.symbols():
left = left.reorder()
else:
right = left.complementop()(right, left.rop)
left = left.lop
elif isinstance(left, operand):
assert isinstance(left, symbolicoperand)
assert symbol==left.name
solved = True
print symbol,'=',right
a,b,c,d,e = map(symbolicoperand, 'abcde')
solve(a, div(add(b,mul(c,d)),e), 'd') # d = ((a*e)-b)/c
solve(numericoperand(1), min(min(a)), 'a') # a = 1
Things have sure changed since 2009. I don't know how your GUI application is going, but this is now possible directly in IPython qtconsole (which one could embed inside a custom PyQt/PySide application, and keep track of all the defined symbols, to allow GUI interaction in a separate listbox, etc.)
(Uses the sympyprt extension for IPython)
What you want to do isn't easy. Some equations are quite straight forward to rearrange (like make b the subject of a = b*c+d, which is b = (a-d)/c), while others are not so obvious (like make x the subject of y = x*x + 4*x + 4), while others are not possible (especially when you trigonometric functions and other complications).
As other people have said, check out Sage. It does what you want:
You can solve equations for one variable in terms of others:
sage: x, b, c = var('x b c')
sage: solve([x^2 + b*x + c == 0],x)
[x == -1/2*b - 1/2*sqrt(b^2 - 4*c), x == -1/2*b + 1/2*sqrt(b^2 - 4*c)]
Sage has support for symbolic math. You could just use some of the equation manipulating functions built-in:
http://sagemath.org/

Categories