Plot surface python with different width in mesh - python

I' m trying to plot a 3d surface with python in fact i have this code:
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib.pyplot as plt
from numpy import *
def f(x,y):
r=x**2 + y**2
return r
n=4.
b=1.
a=-b
h=(2*b)/n
print h
hx=h ##This line##
fig = plt.figure()
ax = Axes3D(fig)
X = arange(a, b+hx, hx)
Y = arange(a, b+h, h)
n = len(X)
m = len(Y)
Z = zeros([n,m])
for i in arange(n):
for j in arange(m):
Z[i,j] = f(X[i],Y[j])
X, Y = meshgrid(X, Y)
ax.plot_surface(Y, X, Z, rstride=1, cstride=1, cmap=cm.jet)
ax.set_xlabel("X Axis")
ax.set_ylabel("Y Axis")
ax.set_zlabel("Z Axis")
plt.show()
This runs Ok and show me the graph I am looking. But when I change ##This line## into hx=h/2. And run it, the graph goes to hell, it's horrible and impossible to understand. I want to have a closer grid in X than Y axis. How I can do this??
Of course this is an example I am solving a partial differential equation, and i need to have a grid closer in one axis than the other one to have numerical estability.

You have flipped your dimensions
Z = zeros([m,n])
for i in arange(n):
for j in arange(m):
Z[j,i] = f(X[i],Y[j])
X, Y = meshgrid(X, Y)
works for any ratio of n to m.
With the function you have, you can use numpy's broadcasting and write this whole section as
X, Y = meshgrid(X, Y)
Z = f(X,Y)
which is both easier to read and faster.
I would re-write this whole block of code as:
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib.pyplot as plt
from numpy import *
def f(x,y):
r=x**2 + y**2
return r
n = 5
m = 10
b = 1.
a = -b
fig = plt.figure()
ax = Axes3D(fig)
X = linspace(a,b,n)
Y = linspace(a,b,m)
X, Y = meshgrid(X, Y)
Z = f(X,Y)
ax.plot_surface(Y, X, Z, rstride=1, cstride=1, cmap=cm.jet)
ax.set_xlabel("X Axis")
ax.set_ylabel("Y Axis")
ax.set_zlabel("Z Axis")
plt.show()

Related

How to plot a one to many function on matplotlib in python

Very simple, if I plot x^2+y^2=z it makes this shape on python it will make this shape:
When I would like to plot it this way:
Below is my code, I am new so I copied it from the internet and have changed the line with the function to plot.
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-4*np.pi,4*np.pi,50)
y = np.linspace(-4*np.pi,4*np.pi,50)
z = x**2+y**2
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot(x,y,z)
plt.show()
Also, how do I make it more high definition and smooth, this is a graph of z=sin(x)
You need to define a 2D mathematical domain with numpy.meshgrid, then you can compute the surface on that domain:
X, Y = np.meshgrid(x, y)
Z = X**2 + Y**2
In order to increase the smoothness of the surface, you have in increase the number of point N you use to compute x and y arrays:
Complete code
import matplotlib.pyplot as plt
import numpy as np
N = 50
x = np.linspace(-4*np.pi, 4*np.pi, N)
y = np.linspace(-4*np.pi, 4*np.pi, N)
X, Y = np.meshgrid(x, y)
Z = X**2 + Y**2
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, Z)
plt.show()

Matplotlib and SGD [duplicate]

I am trying to follow a MATLAB example of meshgrid + interpolation. The example code is found HERE. On that site, I am going through the following example: Example – Displaying Nonuniform Data on a Surface.
Now, I would like to produce a similar plot in Python (Numpy + Matplotlib) to what is shown there in MATLAB. This is the plot that MATLAB produces:
I am having trouble with doing this in Python. Here is my code and my output in Python 2.7:
from matplotlib.mlab import griddata
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
x = np.random.rand(200)*16 - 8
y = np.random.rand(200)*16 - 8
r = np.sqrt(x**2 + y**2)
z = np.sin(r)/r
xi = np.linspace(min(x),max(x), 100)
yi = np.linspace(min(y),max(y), 200)
X,Y = np.meshgrid(xi,yi)
Z = griddata(x, y, z, X, Y, interp='linear')
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1,cmap=cm.jet)
Here is the result of my attempt at doing this with matplotlib and NumPy..
Could someone please help me recreate the MATLAB plot in matplotlib, as either a mesh or a surface plot?
So it seems that the major differences in the look have to do with the default number of lines plotted by matlab, which can be adjusted by increasing rstride and cstride. In terms of color, in order for the colormap to be scaled properly it is probably best in this case to set your limits, vmin and vmax because when automatically set, it will use the min and max of Z, but in this case, they are both nan, so you could use np.nanmin and np.nanmax.
from matplotlib.mlab import griddata
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
x = np.random.rand(200)*16 - 8
y = np.random.rand(200)*16 - 8
r = np.sqrt(x**2 + y**2)
z = np.sin(r)/r
xi = np.linspace(min(x),max(x), 100)
yi = np.linspace(min(y),max(y), 200)
X,Y = np.meshgrid(xi,yi)
Z = griddata(x, y, z, X, Y, interp='linear')
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, rstride=5, cstride=5, cmap=cm.jet, vmin=np.nanmin(Z), vmax=np.nanmax(Z), shade=False)
scat = ax.scatter(x, y, z)
In matplotlib unfortunately I get some annoying overlapping/'clipping' problems, where Axes3d doesn't always properly determine the order in which object should be displayed.

How to make my surface plot appear using Axes3D?

I'm trying to create a surface plot using Python Matplotlib. I've read the documentation in an attempt to figure out where my code was wrong or if I've left anything out, but was having trouble.
The code that I've written is
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def computeCost(X, y, theta):
m = len(y)
predictions = np.dot(X, theta)
squareErros = (predictions - y) ** 2
J = (1 / (2 * m)) * sum(squareErrors)
return J
data = np.loadtxt("./data1.txt", delimiter=',')
X = data[:, 0].reshape(-1, 1)
y = data[:, 1].reshape(-1, 1)
m = len(y)
X = np.concatenate((np.ones((m, 1)), X), axis=1)
theta0_vals = np.linspace(-10, 10, 100) # size (100,)
theta1_vals = np.linspace(-1, 4, 100) # size (100,)
J_vals = np.zeros((len(theta0_vals), len(theta1_vals)))
for i in range(len(x_values)):
for j in range(len(y_values)):
t = np.array([theta0_vals[i], theta1_vals[j]]).reshape(-1, 1)
J_vals[i][j] = computeCost(X, y, t) # size (100, 100)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(theta0_vals, theta1_vals, J_vals)
plt.show()
When I invoke plt.show() I get no output. The surface plot that I'm expecting to see is similar to this:
Would anybody be kind enough to let me know where my usage of the surface plot library went wrong? Thank you.
EDIT
I've tried to run the demo code provided here and it works fine. Here's the code for that:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
# Make data.
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
# Customize the z axis.
ax.set_zlim(-1.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
I think I've figured out the issue by changing a couple of the last lines of code from
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(theta0_vals, theta1_vals, J_vals)
to
ax = plt.axes(projection='3d')
surf = ax.plot_surface(theta0_vals, theta1_vals, J_vals, rstride=1, cstride=1, cmap='viridis', edgecolor='none')
Making this change gives me a surface plot such that:
The link that gave me reference to this was this.

Using matplotlib to make 3D plot

Just trying to make a 3D plot of a constant (0). So I have
width = 1
dx = 0.1
X = np.arange(-width, width, dx)
Y = np.arange(-width, width, dx)
X, Y = np.meshgrid(X, Y)
Z = []
for i in range(len(X)):
Z.append(np.zeros(len(X[i])))
But when I try to run Axes3D.plot_wireframe(X,Y,Z) I get plot_wireframe() missing 1 required positional argument: 'Z'. I need help understanding why this is, because Z is a 2D array like it should be, and I can't find many helpful examples with 3D plotting with matplotlib.
The main point is that you cannot run Axes3D.plot_wireframe(X,Y,Z) by itself. Instead you need to create an instance of Axes3D and call its method [*]. Just like in the 2D case where you wouldn't call matplotlib.axes.Axes.plot(x,y) but ax.plot(x,y) where ax is the instance created e.g. via fig.add_subplot.
An example for the wireframe plot can be found here.
The following code (using the code from the question)
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
width = 1
dx = 0.1
X = np.arange(-width, width, dx)
Y = np.arange(-width, width, dx)
X, Y = np.meshgrid(X, Y)
Z = []
for i in range(len(X)):
Z.append(np.zeros(len(X[i])))
ax.plot_wireframe(X, Y, Z)
plt.show()
produses the following plot
[*] To be precise here; you can call the class method plot_wireframe, but you would then need to supply it with the instance like
Axes3D.plot_wireframe(ax, X, Y, Z)
I found this example online.
I've pasted it in your code example and I got the following code + plot:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
width = 1
dx = 0.1
X = np.arange(-width, width, dx)
Y = np.arange(-width, width, dx)
X, Y = np.meshgrid(X, Y)
Z = []
for i in range(len(X)):
Z.append(np.zeros(len(X[i])))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_wireframe(X, Y, Z)
plt.show()
Hope this helps! I ran it with python 3.5, using the spyder IDE.
Cheers,
Dave

Fixing jagged edges of 3D plot, selecting an appropriate mask

So I have some 3D data that I am able to plot just fine except the edges look jagged.
The relevant code:
import numpy as np
from matplotlib import cm
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
x = np.arange(-1, 1, 0.01)
y = np.arange(-1, 1, 0.01)
x, y = np.meshgrid(x, y)
rho = np.sqrt(x**2 + y**2)
# Attempts at masking shown here
# My Mask
row=0
while row<np.shape(x)[0]:
col=0
while col<np.shape(x)[1]:
if rho[row][col] > 1:
rho[row][col] = None
col=col+1
row=row+1
# Calculate & Plot
z = rho**2
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(x, y, z, rstride=8, cstride=8, cmap=cm.bone, alpha=0.15, linewidth=0.25)
plt.show()
Produces:
This is so close to what I want except the edges are jagged.
If I disable my mask in the code above & replace it with rho = np.ma.masked_where(rho > 1, rho) it gives:
It isn't jagged but not want I want in the corners.
Any suggestions on different masking or plotting methods to get rid of this jaggedness?
Did you consider using polar coordinates (like in this example) ?
Something like:
import numpy as np
from matplotlib import cm
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# create supporting points in polar coordinates
r = np.linspace(0,1.25,50)
p = np.linspace(0,2*np.pi,50)
R,P = np.meshgrid(r,p)
# transform them to cartesian system
x, y = R * np.cos(P), R * np.sin(P)
rho = np.sqrt(x**2 + y**2)
# Calculate & Plot
z = rho**2
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(x, y, z, rstride=1, cstride=1, cmap=cm.bone, alpha=0.15, linewidth=0.25)
plt.show()

Categories