plotting two variable function in python - python

I have to plot a two variable function to check model degeneracy. My code looks like this following a tutorial:
from numpy import exp,arange
from pylab import meshgrid,cm,imshow,contour,clabel,colorbar,axis,title,show
import math
# the function that I'm going to plot
def z_func(x1,x2):
L = exp(-(1-x1)**2 - 100((x2-x1**2)**2))
return L
x1 = arange(-5.0,5.0,0.1)
x2 = arange(-5.0,5.0,0.1)
X1,X2 = meshgrid(x1, x2) # grid of point
Z = z_func(X1, X2) # evaluation of the function on the grid
im = imshow(Z,cmap=cm.RdBu) # drawing the function
# adding the Contour lines with labels
cset = contour(Z,arange(-1,1.5,0.2),linewidths=2,cmap=cm.Set2)
clabel(cset,inline=True,fmt='%1.1f',fontsize=10)
colorbar(im) # adding the colobar on the right
# latex fashion title
title('$z=exp(-(1-x1)^2 - 100(x2-x1^2)^2)$')
show()
and I am getting the following error:
File "multi.py", line 14, in <module>
Z = z_func(X1, X2) # evaluation of the function on the grid
File "multi.py", line 8, in z_func
L = exp(-(1-x1)**2 - 100((x2-x1**2)**2))
TypeError: 'int' object is not callable
I think there is problem how i define my function, How to fix this error and plot the function?

Related

plot multiple curves on same plot inside function

I have a following function with takes 2 arguments psi,lam and returns 1 array y.
lam=np.arange(0,1,0.1)
psi=np.deg2rad(np.arange(0,361,1))
def test(psi,lam):
y=[]
for i in range(len(lam)):
sin_psi = np.sin(psi)
cos_psi = np.cos(psi)
sin_beta = lam*sin_psi
cos_beta = np.sqrt(1.0 - sin_beta**2)
ssin_pb = sin_psi*sin_beta
y.append((lam*(cos_psi/cos_beta)**2 - ssin_pb)/cos_beta + cos_psi)
plt.plot(psi,y[i])
return y
I would like the function to return range(len(lam))=10 plots of y on the vertical axis against psi on x axis.
However, it seems to be only plotting the same curve multiple times. Not sure what I am missing?
import matplotlib.pyplot as plt
import numpy as np
lam=np.arange(0,1,0.1)
psi=np.deg2rad(np.arange(0,361,1))
def test(angle,var):
sin_psi = np.sin(psi)
cos_psi = np.cos(psi)
sin_beta = var*sin_psi
cos_beta = np.sqrt(1.0 - sin_beta**2)
ssin_pb = sin_psi*sin_beta
return ((var*(cos_psi/cos_beta)**2 - ssin_pb)/cos_beta + cos_psi)
for i in lam:
plt.plot(psi,test(psi,i))
plt.show()
I moved the variable outside of the function, this way you may also use it for other cases. The only other thing is that you should call plt.show() after you're done drawing.
Your code has several problems the main being that the return function was inside the loop interrupting it after the first iteration. Imitating your code structure as closely as possible, we can rewrite the code as:
import numpy as np
import matplotlib.pyplot as plt
def test(psi,lam):
y=[]
for curr_lam in lam:
sin_psi = np.sin(psi)
cos_psi = np.cos(psi)
sin_beta = curr_lam*sin_psi
cos_beta = np.sqrt(1.0 - sin_beta**2)
ssin_pb = sin_psi*sin_beta
val = (curr_lam * (cos_psi/cos_beta)**2 - ssin_pb)/cos_beta + cos_psi
y.append(val)
plt.plot(psi, val)
plt.show()
return y
lam=np.arange(0, 1, 0.1)
psi=np.deg2rad(np.arange(0,361,1))
y = test(psi, lam)
print(y)
Sample output:
As Johan mentioned in the comments, you should also directly iterate over list/arrays. If you need to combine arrays, use
for x1, x2 in zip(arr1, arr2):
If you absolutely need the index value, use
for i, x in enumerate(arr):

How can I draw a line from one point to a list multiple points

I'm quite new(ish) to python, so sorry if my syntax is basic or just downright bad.
I'm trying to create a simple 2D Line of Sight script where one point draws a line to all the other points using Matplotlib.
list of points in Matplotlib
Currently, I have a list of points, but I'm having trouble writing the For loop for it. My idea was to create a For loop to draw the lines from the origin to all the x,y coords as defined in positions, but it unfortunately doesn't work.
quality = 5
x = np.linspace(-1,1,quality)
y = np.linspace(-1,1,quality)
X,Y = np.meshgrid(x,y)
positions = np.vstack([Y.ravel(), X.ravel()])
plt.scatter(*positions[::-1])
plt.show()
origin = [0,0]
for i in range(len(positions)):
for j in range(len(positions[i])):
x1 = positions[0][j]
y1 = positions[1][j]
line = shapely.geometry.LineString([origin, [x1, y1]])
But when i run this script, all i get is this output.
What I'm trying to accomplish is something similar to the image below that I've done in another software.
points connect to all points
'shapely' is something I've never used before, but I've tried to recreate it by introducing a live riley, and I had to assign the coordinate information on shapely to a variable in matplotlib. The answer I was referring to is this.
import numpy as np
import matplotlib.pyplot as plt
from shapely.geometry import LineString
quality = 5
x = np.linspace(-1,1,quality)
y = np.linspace(-1,1,quality)
X,Y = np.meshgrid(x,y)
positions = np.vstack([Y.ravel(), X.ravel()])
plt.scatter(*positions[::-1])
origin = (0, 0)
for i in range(len(positions)):
for j in range(len(positions[i])):
x1 = positions[0][j]
y1 = positions[1][j]
line = LineString([origin, (x1, y1)])
x2, y2 = line.xy
plt.plot(0, 0, x2, y2)
plt.show()

plotting vector equations with increasing variables on both axes python

i have been attempting a vector plot (by using quiver) in which every location on the grid is assigned a vector dependant on the location and equations but i am stuck on trying to use a range of both axis parameters (x1 and x3), getting an error:TypeError: only length-1 arrays can be converted to Python scalars
this is the code as built so far and any help would be amazing:
def SVmotion(t,A,beta,f,j):
x1= np.arange(0,10001,100)
x3= np.arange(0,10001,100)
w=2*np.pi*f
k=w/beta
k1=k*np.sin(j)
k3=k*np.cos(j)
k_beta_x = k1*x1+k3*x3
theta = k_beta_x-w*t
Usvx1 = k3*A*complex(-np.sin(theta),np.cos(theta))
Usvx3 = k1*A*complex(-np.sin(theta),np.cos(theta))
Usvx1_real=Usvx1.real
Usvx3_real=Usvx3.real
return Usvx1_real, Usvx3_real
fig ,ax = plt.subplots()
ax.quiver(x1,x3,Usvx1_real,Usvx3_real)
SVmotion(0,1,3000,2,0)
The issue is that 'theta' is an array. Please check if the following helps.
import numpy as np
def SVmotion(t,A,beta,f,j):
x1= np.arange(0,10001,100)
x3= np.arange(0,10001,100)
w=2*np.pi*f
k=w/beta
k1=k*np.sin(j)
k3=k*np.cos(j)
k_beta_x = k1*x1+k3*x3
theta = k_beta_x-w*t
for t in theta:
Usvx1 = k3*A*complex(-np.sin(t),np.cos(t))
Usvx3 = k1*A*complex(-np.sin(t),np.cos(t))
Usvx1_real=Usvx1.real
Usvx3_real=Usvx3.real
return Usvx1_real, Usvx3_real
SVmotion(0,1,3000,2,0)
#(0.003627598728468422, 0.0)

Improving for loop performance and customizing graphs

I have created a code that returns the output that I am after - 2 graphs with multiple lines on each graph. However, the code is slow and quite big (in terms of how many lines of code it takes). I am interested in any improvements I can make that will help me to get such graphs faster, and make my code more presentable.
Additionally, I would like to add more to my graphs (axis names and titles is what I am after). Normally, I would use plt.xlabel,plt.ylabel and plt.title to do so, however I couldn't quite understand how to use them here. The aim here is to add a line to each graph after each loop ( I have adapted this piece of code to do so).
I should note that I need to use Python for this task (so I cannot change to anything else) and I do need Sympy library to find values that are plotted in my graphs.
My code so far is as follows:
import matplotlib.pyplot as plt
import sympy as sym
import numpy as np
sym.init_printing()
x, y = sym.symbols('x, y') # defining our unknown probabilities
al = np.arange(20,1000,5).reshape((196,1)) # values of alpha/beta
prob_of_strA = []
prob_of_strB = []
colours=['r','g','b','k','y']
pen_values = [[0,-5,-10,-25,-50],[0,-25,-50,-125,-250]]
fig1, ax1 = plt.subplots()
fig2, ax2 = plt.subplots()
for j in range(0,len(pen_values[1])):
for i in range(0,len(al)): # choosing the value of beta
A = sym.Matrix([[10, 50], [int(al[i]), pen_values[0][j]]]) # defining matrix A
B = sym.Matrix([[pen_values[1][j], 50], [int(al[i]), 10]]) # defining matrix B
sigma_r = sym.Matrix([[x, 1-x]]) # defining the vector of probabilities
sigma_c = sym.Matrix([y, 1-y]) # defining the vector of probabilities
ts1 = A * sigma_c ; ts2 = sigma_r * B # defining our utilities
y_sol = sym.solvers.solve(ts1[0] - ts1[1],y,dict = True) # solving for y
x_sol = sym.solvers.solve(ts2[0] - ts2[1],x,dict = True) # solving for x
prob_of_strA.append(y_sol[0][y]) # adding the value of y to the vector
prob_of_strB.append(x_sol[0][x]) # adding the value of x to the vector
ax1.plot(al,prob_of_strA,colours[j],label = ["penalty = " + str(pen_values[0][j])]) # plotting value of y for a given penalty value
ax2.plot(al,prob_of_strB,colours[j],label = ["penalty = " + str(pen_values[1][j])]) # plotting value of x for a given penalty value
ax1.legend() # showing the legend
ax2.legend() # showing the legend
prob_of_strA = [] # emptying the vector for the next round
prob_of_strB = [] # emptying the vector for the next round
You can save a couple of lines by initializing your empty vectors inside the loop. You don't have to bother re-defining them at the end.
for j in range(0,len(pen_values[1])):
prob_of_strA = []
prob_of_strB = []
for i in range(0,len(al)): # choosing the value of beta
A = sym.Matrix([[10, 50], [int(al[i]), pen_values[0][j]]]) # defining matrix A
B = sym.Matrix([[pen_values[1][j], 50], [int(al[i]), 10]]) # defining matrix B
sigma_r = sym.Matrix([[x, 1-x]]) # defining the vector of probabilities
sigma_c = sym.Matrix([y, 1-y]) # defining the vector of probabilities
ts1 = A * sigma_c ; ts2 = sigma_r * B # defining our utilities
y_sol = sym.solvers.solve(ts1[0] - ts1[1],y,dict = True) # solving for y
x_sol = sym.solvers.solve(ts2[0] - ts2[1],x,dict = True) # solving for x
prob_of_strA.append(y_sol[0][y]) # adding the value of y to the vector
prob_of_strB.append(x_sol[0][x]) # adding the value of x to the vector
ax1.plot(al,prob_of_strA,colours[j],label = ["penalty = " + str(pen_values[0][j])]) # plotting value of y for a given penalty value
ax2.plot(al,prob_of_strB,colours[j],label = ["penalty = " + str(pen_values[1][j])]) # plotting value of x for a given penalty value
ax1.legend() # showing the legend
ax2.legend() # showing the legend

Numpy roots function and pyplot plot

I want to plot the two solutions of quadratic equation as a function of a parameter ( function coeff(t) ). I am using function numpy.roots (I am sure that all roots are real in this case), and I am trying to invoke it from within pyplot.plot as below:
import numpy as np
import matplotlib.pyplot as plt
r = 3.74
def coeff(pp):
return np.array([pp-1,r+1-0.5*pp,-r])
def sroot(t):
return np.roots(coeff(t))
a = np.linspace(0,0.9,100)
fig = plt.figure()
plt.plot(a,sroot(a)[0,:])
plt.plot(a,sroot(a)[1,:])
plt.show()
I get error message:
File "quest.py", line 18, in <module>
plt.plot(a,sroot(a)[0,:])
File "quest.py", line 10, in sroot
return np.roots(coeff(t))
File "/usr/lib64/python2.7/site-packages/numpy/lib/polynomial.py", line 218, in roots
p = p.astype(float)
I understand that the numpy.roots takes only list of parameters and is unable to recognize a row in array 3xlen(a). Is there a way to do it in one line, preferably inside the pyplot.plot? I would like to avoid using loop.
This is because you transform all of your coefficient at once and try to call the numpy roots solver on all of them. np.roots only accept 1-d array and solves a single polynomial. Here is a script that does what you want:
import numpy as np
import matplotlib.pyplot as plt
# Parameters
r = 3.74
T = np.linspace(0.0,0.9,100)
# Coefficients
C = np.zeros((len(T),3))
C[:,0] = T-1
C[:,1] = r + 1 - 0.5*T
C[:,2] = r
# Roots
R = np.zeros((len(T),2))
for i in range(len(T)):
R[i] = np.roots(C[i])
# Plot
fig = plt.figure()
plt.plot(T,R[:,0])
plt.plot(T,R[:,1])
plt.show()

Categories

Resources