How to display a contour plot of a parametrical function in Python? - python

I have a function g(psi, k) where psi is a two components array and k is a real parameter. I would like to display the g function in a 3D contour plot with respect to the coordinates psi given a selected parameter k. How can I do that in Python?
I tried using the function contour3D with a wrapper function in the following way:
import numpy as np
import matplotlib.pyplot as plt
k = 32 # Change this value to display different plots
# Wrapper of the g function
def f(x, y):
psi = np.array([x, y])
return g(psi, k)
x = np.linspace(-6, 6, 30)
y = np.linspace(-6, 6, 30)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.contour3D(X, Y, Z, 50, cmap='binary')
plt.show()
But I get the following error relative to the line Z = f(X, Y):
ValueError: setting an array element with a sequence.
Running simply:
print(f(-0.33, -0.5))
I obtain a real value as expected:
28.08105396614395
How can I fix it? Is there any other way more straightforward to display the plot of g(psi, 32)?

Your function g(psi, k) is probably only working with psi being a 1D array, meaning only accepting x and y being scalars. Either call f in a loop, or vectorize the g function. Here is how to call the function f in a loop:
Z = np.empty(shape=(X.shape))
for row, (xx, yy) in enumerate(zip(X,Y)): # into rows
for col, (xxx, yyy) in enumerate(zip(xx,yy)): # rows to single values
Z[row, col] = f(xxx, yyy)

Related

How can I get Isocontour's xy coordinates for contour plot?

I am trying to get isosurface's x-y coordinates from 3D plot. Here is my attempt;
import matplotlib.pyplot as plt
from numpy import pi, cos, sin, linspace, meshgrid
x = linspace(0,50,1000)
y = linspace(0,50,1000)
n = 5
L = 50
t = 0
def gyroid(x, y, n, L, t):
tanım1 = (sin(2*pi*n*x/L) * cos(2*pi*n*y/L) + sin(2*pi*n*y/L) + cos(2*pi*n*x/L))
return tanım1*tanım1 - t**2
XX, YY = meshgrid(x, y)
z = gyroid(XX, YY, n, L, t)
thickness = 0.1
contour = plt.contour(XX, YY, z,levels=[thickness])
# Attempt to get x-y coordinates
dat0= contour.allsegs[0][0]
plt.plot(dat0[:,0],dat0[:,1])
The gyroid function is normally looks like;
3D plot
I am getting isocontour for z = 0.1 plane;
Void plot
I need xy pairs of these voids. But when I try, the code is only getting lower left coordinates.
It is clear that function is strongly nonlinear, but is there any way to retrieve these coordinates?
Thanks for your responses in advance.
You specify contour.allsegs[0][0] so you get the very first line of the first contour line.
for lines in contour.allsegs:
for line in lines:
X, Y = line[:,0], line[:,1]
plt.plot(X, Y)

How to plot this 2D sinusoidal parametric function

I have a 2D sinusoidal function and I want to plot its boundary threshold of t=0. Could someone give me a hint on how to do it?
f (x, y) = sin(10x) + cos(4y) − cos(3xy)
x ∈ [0, 1], y ∈ [0, 2], with a boundary threshold of t = 0
The expected plot should look like this: Plot A dashed lines
Actually the function I am referring to is a toy one from paper "Active Learning For Identifying Function Threshold Boundaries"(https://papers.nips.cc/paper/2005/file/8e930496927757aac0dbd2438cb3f4f6-Paper.pdf)
Page 4 of that paper
Update: I tried the following code but apparently it does not give what I want. The top view is a straight line from (0,0) to (1,2), instead of some curves...
ax = plt.axes(projection='3d')
# Data for a three-dimensional line
xline = np.linspace(0, 1, 1000)
yline = np.linspace(0, 2, 1000)
zline = np.sin(10*xline)+np.cos(4*yline)-np.cos(3*xline*yline)
ax.plot3D(xline, yline, zline, 'gray')
Welcome to stackoverflow. Your math is wrong. Your function f is a function of two variables, f(x, y). Hence you need to evaluate it on a grid (all combinations of valid x and y values), if you want to find the solutions for f = 0 computationally. Your code is currently evaluating f only on the y = 2x axis (hence the "straight line from (0,0) to (1, 2) in top-down view").
import numpy as np
import matplotlib.pyplot as plt
def f(x, y):
return np.sin(10*x)+np.cos(4*y)-np.cos(3*x*y)
x = np.arange(0, 1, 1e-3)
y = np.arange(0, 2, 1e-3)
XX, YY = np.meshgrid(x, y)
ZZ = f(XX, YY)
plt.contour(XX, YY, ZZ, levels=[0.])
plt.show()

Plotting piecewise contour graph in Python

I want to plot a piecewise function in Python where there are two variables x and y. This means I would need some kind of contour graph. In Matlab one may use
syms x y
eq1 = 0.1*(x/2)^2-0.3*(y/4)^2;
eq2 = 0.15*(x/3)^2-0.25*(y/2)^2;
ezplot(eq1,[-5 5 -10 10]);
hold on
ezplot(eq2,[-4 4 -5 5]);
where ezplot plots eq1 = 0 over xmin < x < xmax and ymin < y < ymax. Is there any (simple) equivalent function(s) in Python?
I have looked at the solutions in this post. Their problem only involves one variable x so it's not helpful in my case.
You can separate the different pieces by using numpy's masked array.
At first define your functions, the x and y ranges and their 2D versions for the contour plot:
import numpy as np
import matplotlib.pyplot as plt
from numpy.ma import masked_array as marr
def eq1(x, y):
return 0.1*(x/2)**2-0.3*(y/4)**2
def eq2(x, y):
return 0.15*(x/3)**2-0.25*(y/2)**2
x = np.linspace(-5, 5, 101)
y = np.linspace(-10, 10, 201)
xx, yy = np.meshgrid(x, y)
Now we need a 2D mask (or some, depending on the number of pieces of the piecewise function) to separate definition ranges of the different pieces of the function:
maskx = ((xx>=-4) * (xx<=4))
masky = ((yy>=-5) * (yy<=5))
mask = maskx * masky
This can be applied to different masked arrays:
res1 = marr(eq1(xx, yy), mask)
res2 = marr(eq2(xx, yy), ~mask)
Plotting a masked array leaves all the area blank where the mask is True:
fig, axs = plt.subplots(1, 2, sharey=True)
axs[0].contour(xx, yy, res1)
axs[0].contour(xx, yy, res2)
axs[0].set_title('contour')
axs[1].contourf(xx, yy, res1)
axs[1].contourf(xx, yy, res2)
axs[1].set_title('contourf')

3D-plot of the error function in a linear regression

I would like to visually plot a 3D graph of the error function calculated for a given slope and y-intercept for a linear regression.
This graph will be used to illustrate a gradient descent application.
Let’s suppose we want to model a set of points with a line. To do this we’ll use the standard y=mx+b line equation where m is the line’s slope and b is the line’s y-intercept. To find the best line for our data, we need to find the best set of slope m and y-intercept b values.
A standard approach to solving this type of problem is to define an error function (also called a cost function) that measures how “good” a given line is. This function will take in a (m,b) pair and return an error value based on how well the line fits the data. To compute this error for a given line, we’ll iterate through each (x,y) point in the data set and sum the square distances between each point’s y value and the candidate line’s y value (computed at mx+b). It’s conventional to square this distance to ensure that it is positive and to make our error function differentiable. In python, computing the error for a given line will look like:
# y = mx + b
# m is slope, b is y-intercept
def computeErrorForLineGivenPoints(b, m, points):
totalError = 0
for i in range(0, len(points)):
totalError += (points[i].y - (m * points[i].x + b)) ** 2
return totalError / float(len(points))
Since the error function consists of two parameters (m and b) we can visualize it as a two-dimensional surface.
Now my question, how can we plot such 3D-graph using python ?
Here is a skeleton code to build a 3D plot. This code snippet is totally out of the question context but it show the basics for building a 3D plot.
For my example i would need the x-axis being the slope, the y-axis being the y-intercept and the z-axis, the error.
Can someone help me build such example of graph ?
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import random
def fun(x, y):
return x**2 + y
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = y = np.arange(-3.0, 3.0, 0.05)
X, Y = np.meshgrid(x, y)
zs = np.array([fun(x,y) for x,y in zip(np.ravel(X), np.ravel(Y))])
Z = zs.reshape(X.shape)
ax.plot_surface(X, Y, Z)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
The above code produce the following plot, which is very similar to what i am looking for.
Simply replace fun with computeErrorForLineGivenPoints:
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import collections
def error(m, b, points):
totalError = 0
for i in range(0, len(points)):
totalError += (points[i].y - (m * points[i].x + b)) ** 2
return totalError / float(len(points))
x = y = np.arange(-3.0, 3.0, 0.05)
Point = collections.namedtuple('Point', ['x', 'y'])
m, b = 3, 2
noise = np.random.random(x.size)
points = [Point(xp, m*xp+b+err) for xp,err in zip(x, noise)]
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ms = np.linspace(2.0, 4.0, 10)
bs = np.linspace(1.5, 2.5, 10)
M, B = np.meshgrid(ms, bs)
zs = np.array([error(mp, bp, points)
for mp, bp in zip(np.ravel(M), np.ravel(B))])
Z = zs.reshape(M.shape)
ax.plot_surface(M, B, Z, rstride=1, cstride=1, color='b', alpha=0.5)
ax.set_xlabel('m')
ax.set_ylabel('b')
ax.set_zlabel('error')
plt.show()
yields
Tip: I renamed computeErrorForLineGivenPoints as error. Generally, there is no need to name a function compute... since almost all functions compute something. You also do not need to specify "GivenPoints" since the function signature shows that points is an argument. If you have other error functions or variables in your program, line_error or total_error might be a better name for this function.

Fixed point iteration and plotting in Python

Given a function g(x), I want to find a fixed point to this function using
fixed point iteration. Except for finding the point itself, I want to plot the graph to the function using matplotlib.pyplot, and include the vertical and horizontal bars that show how the iteration closes in on the fixed point (if one exists). Example picture
All help appreciated!
/programming newbie
EDIT: Since I'm no too comfortable with generator objects yet, I've written the following code. It doesn't quite work though: what's wrong with it?
from matlibplot.axes import vlines, hlines
def fixpt(f, x, epsilon=1.0E-4, N=500, store=False):
y = f(x)
n = 0
if store: Values = [(x, y)]
while abs(y-x) >= epsilon and n < N:
x = f(x)
n += 1
y = f(x)
if store: Values.append((x, y))
vlines(x, min(x, y), max(x, y), color='b')
hlines(y, min(y, x), max(y, x), color='b')
if store:
return y, Values
else:
if n >= N:
return "No fixed point for given start value"
else:
return x, n, y
def fixedpoint(f,x):
while x != f(x):
yield x
x = f(x)
yield x
Usage: fixedpoint(g,some_starting_value).
Vertical and horizontal bars depend on plotting library. Specify which one you use.
Your function looks fine. I am not familiar with vlines and hlines. I used your store arg to get the points, and plot them outside the function (it is generally better to separate problems like this).
I used only the plot function from matplotlib.pyplot, and the show function to display the graph.
from matplotlib import pyplot as plt
import numpy as np
def fixpt(f, x, epsilon=1.0E-4, N=500, store=False):
y = f(x)
n = 0
if store: Values = [(x, y)]
while abs(y-x) >= epsilon and n < N:
x = f(x)
n += 1
y = f(x)
if store: Values.append((x, y))
if store:
return y, Values
else:
if n >= N:
return "No fixed point for given start value"
else:
return x, n, y
# define f
def f(x):
return 0.2*x*x
# find fixed point
res, points = fixpt(f, 3, store = True)
# create mesh for plots
xx = np.arange(0, 6, 0.1)
#plot function and identity
plt.plot(xx, f(xx), 'b')
plt.plot(xx, xx, 'r')
# plot lines
for x, y in points:
plt.plot([x, x], [x, y], 'g')
plt.plot([x, y], [y, y], 'g')
# show result
plt.show()
Here is how I thought it through :
from pylab import *
def f(x):
return 8*x/(1 + 2*x)
def cobweb(x0, n, ax):
xs = [x0]
ys = [0]
for i in range(1,n):
if i % 2 == 0:
xs.append(ys[-1])
ys.append(ys[-1])
else:
xs.append(xs[-1])
ys.append(f(xs[-1]))
ax.plot(xs, ys, 'k--', lw=2.0)
x = linspace(0, 4, 100)
fig = figure()
ax = fig.add_subplot(111)
ax.plot(x, x, 'k', lw=2.0)
ax.plot(x, f(x), 'r', lw=2.0)
cobweb(0.5, 50, ax)
ax.set_xlabel(r'$x$')
ax.set_ylabel(r'$f(x)$')
grid()
show()

Categories