Python ValueError plot - python

This is my first time using python (and stackoverflow) , and it keeps showing "ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"
Can anyone please tell me what I am doing wrong ?
It is supposed to show three graphs.
K,r,a,h,e,m=9,0.5,0.3,0.05,0.1,0.1
def dz(N,P):
return (r*N*(1-N/K)-a*N*P/(1+a*h*N),e*a*N*P/(1+a*h*N)-m*P)
N0,P0=6,4
pas=10**(-3)
def z(t):
u,x,y=0,N0,P0
if t>0 :
while t-u>pas:
x,y,u=x+pas*dz(x,y)[0],y+pas*dz(x,y)[1],u+pas
return x+(t-u)*dz(x,y)[0],y+(t-u)*dz(x,y)[1]
else :
while u-t>pas:
x,y,u=x-pas*dz(x,y)[0],y-pas*dz(x,y)[1],u-pas
return x+(t-u)*dz(x,y)[0],y+(t-u)*dz(x,y)[1]
def N(t):
return z(t)[0]
def P(t):
return z(t)[1]
close()
figure('N(t), P(t), P(N)')
t=linspace(0,15,100)
autoscale(enable=True, axis=u'both', tight=None)
plot(t,N(t),'b--',t,P(t),'r--',N(t),P(t),'k')
axis('scaled')
grid(True)
problem solved, please see answers.

You need to write some code for exercise first. For example understand how to write and use the functions and what is/are passed to the functions before you begin to write some awesome code. It is what people would say Rome wasn't built in a day.
Back to your code: The way you want the function Z(t) treat t is as a single variable. However, when you use N(t) and call Z(t), t is passed to Z(t) as an array.
Solution: add a for loop after you specify t, to calculate each N(t_i) for each t_i in the array t, and then change the plot part accordingly; alternatively, you have to change the "if else" part in the definition of z(t), into the way that treats t as an array (for example loop through t).

First of all thank you for your solution/comments.
I don't have an error message anymore. And my graphs are showing what they should.
Do you have any tips to make the code faster ? Because it still takes a lot of time to show the graphs (and my very old/slow PC doesn't like that).
Here is the new code (yes, I know, it is really long for such a simple code, but it works) :
from pylab import *
K,r,a,h,e,m=20,0.5,0.3,0.05,0.1,0.1
def dz(N,P):
return (r*N*(1-N/K)-a*N*P/(1+a*h*N),e*a*N*P/(1+a*h*N)-m*P)
N0=10
P0=3
print('conditions initiales :')
print('N0=')
print(N0)
print(' P0=')
print(P0)
pas=10**(-3)
def z(t):
u,x,y=0,N0,P0
if t>0 :
while t-u>pas:
x,y,u=x+pas*dz(x,y)[0],y+pas*dz(x,y)[1],u+pas
return x+(t-u)*dz(x,y)[0],y+(t-u)*dz(x,y)[1]
else :
while u-t>pas:
x,y,u=x-pas*dz(x,y)[0],y-pas*dz(x,y)[1],u-pas
return x+(t-u)*dz(x,y)[0],y+(t-u)*dz(x,y)[1]
def N(t):
return z(t)[0]
def P(t):
return z(t)[1]
close()
figure('N(t), P(t), P(N)')
n=100
t=linspace(0,100,n)
N1=zeros(n)
P1=zeros(n)
for i in range(len(t)):
N1[i]=N(t[i])
P1[i]=P(t[i])
subplot(2,2,1)
plot(t,N1,'b--')
title('N(t)')
xlabel('t')
ylabel('N')
autoscale(enable=True, axis=u'both', tight=True)
grid(True)
subplot(2,2,2)
plot(t,P1,'r--')
title('P(t)')
xlabel('t')
ylabel('P')
autoscale(enable=True, axis=u'both', tight=True)
grid(True)
subplot(2,2,3)
plot(N1,P1,'k')
xlabel('N')
ylabel('P')
autoscale(enable=True, axis=u'both', tight=True)
grid(True)
Thank you for your help and have a wonderful day.

Related

Python Error: "divide by zero encountered in log" in function, how to adjust? (Beginner here)

For my current assignment, I am to establish the stability of intersection/equilibrium points between two nullclines, which I have defined as follows:
def fNullcline(F):
P = (1/k)*((1/beta)*np.log(F/(1-F))-c*F+v)
return P
def pNullcline(P):
F = (1/delta)*(pD-alpha*P+(r*P**2)/(m**2+P**2))
return F
I also have a method "stability" that applies the Hurwitz criteria on the underlying system's Jacobian:
def dPdt(P,F):
return pD-delta*F-alpha*P+(r*P**2)/(m**2+P**2)
def dFdt(P,F):
return s*(1/(1+sym.exp(-beta*(-v+c*F+k*P)))-F)
def stability(P,F):
x = sym.Symbol('x')
ax = sym.diff(dPdt(x, F),x)
ddx = sym.lambdify(x, ax)
a = ddx(P)
# shortening the code here: the same happens for b, c, d
matrix = [[a, b],[c,d]]
eigenvalues, eigenvectors = np.linalg.eig(matrix)
e1 = eigenvalues[0]
e2 = eigenvalues[1]
if(e1 >= 0 or e2 >= 0):
return 0
else:
return 1
The solution I was looking for was later provided. Basically, values became too small! So this code was added to make sure no too small values are being used for checking the stability:
set={0}
for j in range(1,210):
for i in range(1,410):
x=i*0.005
y=j*0.005
x,y=fsolve(System,[x,y])
nexist=1
for i in set:
if(abs(y-i))<0.00001:
nexist=0
if(nexist):
set.add(y)
set.discard(0)
I'm still pretty new to coding so the function in and on itself is still a bit of a mystery to me, but it eventually helped in making the little program run smoothly :) I would again like to express gratitude for all the help I have received on this question. Below, there are still some helpful comments, which is why I will leave this question up in case anyone might run into this problem in the future, and can find a solution thanks to this thread.
After a bit of back and forth, I came to realise that to avoid the log to use unwanted values, I can instead define set as an array:
set = np.arange(0, 2, 0.001)
I get a list of values within this array as output, complete with their according stabilities. This is not a perfect solution as I still get runtime errors (in fact, I now get... three error messages), but I got what I wanted out of it, so I'm counting that as a win?
Edit: I am further elaborating on this in the original post to improve the documentation, however, I would like to point out again here that this solution does not seem to be working, after all. I was too hasty! I apologise for the confusion. It's a very rocky road for me. The correct solution has since been provided, and is documented in the original question.

how to make a clause in pyswip

can any one here help me to make prolog clauses inside python using pyswip like this
database:
man(peter).
woman(adam).
man(jonathan).
man(paul).
woman(cloe).
father(jonathan, peter).
father(pierre, adam).
brother(pierre, paul).
father(pierre, cloe).
these are functions
child(X, Y) :- father(Y,X).
son(X, Y) :- man(X) , father(Y, X).
daughter(X, Y) :- woman(X), father(Y, X).
brother(X, Y) :- man(X), father(Z, Y), father(Z, X).
sister(X, Y) :- woman(X), father(Z, Y), father(Z, X).
how can i define these prolog functions inside python through pyswip
I don't have time to make a detailed answer right now, I'll update it latter but here's a simple example of an interface in python I had done to a prolog program that played reversi.
#!/usr/bin/python
import sys
from pyswip import Prolog, Functor, Variable, Query
prolog = Prolog()
prolog.consult('./reversi_game.pl')
prolog.consult('./alphabeta.pl')
start_board = Functor("startBoard", 1)
b = Variable()
start_board_query = Query(start_board(b))
start_board_query.nextSolution()
print()
print_board(list(b.get_value())) # an 8*8 grid filled with 0 except at the 4 center squares that have x's and o's
start_board_query.closeQuery()
set_to_x = Functor("setToX", 1)
xp = Variable()
set_player_query = Query(set_to_x(xp))
set_player_query.nextSolution()
x_player = xp.get_value()
print()
print(x_player) # 'x'
set_player_query.closeQuery()
So what it is going on here? To define the predicate interface you create a Functor, giving it a string which is the name of the predicate in Prolog and its arity, you create as many variables as you need and pass them to your Functor creating a Query from it.
You can then proceed calling nextSolution() on the Query object for as long as you want depending on how many solutions you need, if I remember correctly the result will be None when it fails and it stops giving any solutions. Then use the get_value() function to extract the values of the variables of your predicate.
You can also check this out:
https://github.com/yuce/pyswip/tree/master/examples
Hope it helps.
EDITED:
I know this "promised a bit more detailed answer" is a bit late now, but anyways.

Algorithm - return aliasing frequency

In Python, I'm trying to write an algorithm alias_freq(f_signal,f_sample,n), which behaves as follows:
def alias_freq(f_signal,f_sample,n):
f_Nyquist=f_sample/2.0
if f_signal<=f_Nyquist:
return n'th frequency higher than f_signal that will alias to f_signal
else:
return frequency (lower than f_Nyquist) that f_signal will alias to
The following is code that I have been using to test the above function (f_signal, f_sample, and n below are chosen arbitrarily just to fill out the code)
import numpy as np
import matplotlib.pyplot as plt
t=np.linspace(0,2*np.pi,500)
f_signal=10.0
y1=np.sin(f_signal*t)
plt.plot(t,y1)
f_sample=13.0
t_sample=np.linspace(0,int(f_sample)*(2*np.pi/f_sample),f_sample)
y_sample=np.sin(f_signal*t_sample)
plt.scatter(t_sample,y_sample)
n=2
f_alias=alias_freq(f_signal,f_sample,n)
y_alias=np.sin(f_alias*t)
plt.plot(t,y_alias)
plt.xlim(xmin=-.1,xmax=2*np.pi+.1)
plt.show()
My thinking is that if the function works properly, the plots of both y1 and y_alias will hit every scattered point from y_sample. So far I have been completely unsuccessful in getting either the if statement or the else statement in the function to do what I think it should, which makes me believe that either I don't understand aliasing nearly as well as I want to, or my test code is no good.
My questions are: Prelimarily, is the test code I'm using sound for what I'm trying to do? And primarily, what is the alias_freq function that I am looking for?
Also please note: If some Python package has a function just like this already built in, I'd love to hear about it - however, part of the reason I'm doing this is to give myself a device to understand phenomena like aliasing better, so I'd still like to see what my function should look like.
As far as I understood the question correctly, the frequency of the aliased signal is abs(sampling_rate * n - f_signal), where n is the closest integer multiple to f_signal.
Thus:
n = round(f_signal / float(f_sample))
f_alias = abs(f_sample * n - f_signal)
This should work for frequencies under and over Nyquist.
I figured out the answer to my and just realized that I forgot to post it here, sorry. Turns out it was something silly - Antii's answer is basically right, but the way I wrote the code I need a f_sample-1 in the alias_freq function, where I just had an f_sample. There's still a phase shift thing that happens sometimes, but just plugging in either 0 or pi for the phase shift has worked for me every time, I think it's just due to even or odd folding. The working function and test code is below.
import numpy as np
import matplotlib.pyplot as plt
#Given a sample frequency and a signal frequency, return frequency that signal frequency will be aliased to.
def alias_freq(f_signal,f_sample,n):
f_alias = np.abs((f_sample-1)*n - f_signal)
return f_alias
t=np.linspace(0,2*np.pi,500)
f_signal=13
y1=np.sin(f_signal*t)
plt.plot(t,y1)
f_sample=7
t_sample=np.linspace(0,int(f_sample)*(2*np.pi/f_sample),f_sample)
y_sample=np.sin((f_signal)*t_sample)
plt.scatter(t_sample,y_sample)
f_alias=alias_freq(f_signal,f_sample,3)
y_alias=np.sin(f_alias*t+np.pi)#Sometimes with phase shift, usually np.pi for integer f_signal and f_sample, sometimes without.
plt.plot(t,y_alias)
plt.xlim(xmin=-.1,xmax=2*np.pi+.1)
plt.show()
Here is a Python aliased frequency calculator based on numpy
def get_aliased_freq(f, fs):
"""
return aliased frequency of f sampled at fs
"""
import numpy as np
fn = fs / 2
if np.int(f / fn) % 2 == 0:
return f % fn
else:
return fn - (f % fn)

Python return statement in PlotAnimation function

I have a problem in a function to be used in matplotlib FuncAnimation.
I'm aware this is not 100% related to the PlotAnimation code. It is more related to how return works. Anyway, here it go:
I need to plot several lines in the same graph - but I don't know in advance how many lines. So, I created a list of plots (called lines) like that:
fig = plt.figure()
ax = plt.axes(xlim=(0, 1), ylim=(0, 1), aspect='equal')
lines=[]
for i in range(len(disc)):
line, = ax.plot([], [], '-', lw=1.5)
lines.append(line)
Let's say len(disc) is equal to or greater than 3. If I do this:
def animate(i):
global disc
for i in range(len(disc)):
lines[i].set_data(disc[i].x, disc[i].y)
return line[0], line[1], line[2]
anim = animation.FuncAnimation(fig, animate, blit=True)
plt.show()
All works perfecly (except for the fact that, if len(disc) is greated than 3, I miss some of the lines in the plot).
However, I don't know len(disc) beforehand. So, my question is: Is there a way to use something like that:
return lines
(or something like that; I know the above doesn't work), replacing the return statement in the animate function above?
The first thing I can think of is using a for loop
return lines[0:len(lines)]
I don't know, if I got this right, as I don't use matplotlib myself, but from the documentation I got an idea.
Why does return lines not work? It should be equal to
return lines[0], lines[1], ..., lines[len(lines)-1]
Maybe an iterator helps here. The keyword is yield:
def def animate(i):
global disc
for i in range(len(disc)):
lines[i].set_data(disc[i].x, disc[i].y)
yield from lines # in Python 2.x use: yield iter(lines)
Whereas I don't think, this is the correct/desired way to got, I cannot think of another solution for now.
Do you really need to return something? The documentation doesn't mention a required return-value.

For loop inside a function

I'm still learning Python, and I'd love to know a way to make the following work:
a_function(
for n,item in enumerate(list):
inside_function(code code code,
code code code,
code code code))
So there's a function nested inside another function, and I need to play out the inside function a number of times, but not the outside one. The code I'm working with is not mine so I can't change the way these functions work.
I can edit with the actual code if anyone needs it, it's something from PyChart.
Edit: actual code:
ar = area.T(y_coord = category_coord.T(data, 0),
x_grid_style=line_style.gray50_dash1,
x_grid_interval=chartlength/5, x_range = (0,chartlength),
x_axis=axis.X(label="X label"),
y_axis=axis.Y(label="Y label"))
chart_object.set_defaults(interval_bar_plot.T, direction="horizontal",
width=5, cluster_sep = 0, data=data)
ar.add_plot(
for n,item in enumerate(compactlist):
interval_bar_plot.T(line_styles = [None, None],
fill_styles = [fill_style.red, None],
label=compactlist[n], cluster=(n,len(compactlist)))
)
can = canvas.default_canvas()
can.set_title("Chromosome comparison")
can.set_author("Foo")
ar.draw()
The ar.add_plot function creates a working area in the canvas (as I understand it), while the interval_bar_plot function creates the bars, one by one. So I need multiple interval_bar_plot functions but only the one add_plot, or it simply repeats the first bar n times.
Edit: and the error:
File "intvlbar.py", line 105
for n,item in enumerate(compactlist):
^
SyntaxError: invalid syntax
What you are trying to do is pass several bar plot objects to the add_plot method (documented in here). One way you can do this is to pass them each explicitly. For example:
ar.add_plot(bar1, bar2, bar3)
Examples of this are in the sample code sections of the PyChart documentation for bar plots and interval bar plots, for example.
You do not want to do this because your compactlist might be inconveniently long or of varying length between runs. Another option is to use argument unpacking. Create a list containing your bar plot objects:
bars = [interval_bar_plot.T(line_styles = [None, None],
fill_styles = [fill_style.red, None],
label=compactlist[n], cluster=(n,len(compactlist)))
for n,item in enumerate(compactlist)]
Now call add_plot with your bars:
ar.add_plot(*bars)
The error you are getting is because the for loop does not return anything in itself. But the for loop is placed inside the function call ar.add_plot() where the parameters should go. So python is telling you "ar.add_plot() needs parameters, but this for loop isn't going to give them to me"
What parameters does ar.add_plot() need?
You need something closer to this (though this probably isn't correct):
ar.add_plot()
for n,item in enumerate(compactlist):
interval_bar_plot.T(line_styles = [None, None],
fill_styles = [fill_style.red, None],
label=compactlist[n], cluster=(n,len(compactlist)

Categories