Plot 3D graph using Python - python

I trying to plot a graph of a function f(x, y) = x**x*y, but I'm getting an error:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
def f(x,y):
return x**x*y
x = np.arange(-4.0, 4.0, 0.1)
y = np.arange(-4.0, 4.0, 0.1)
z = f(x, y)
X, Y, Z = np.meshgrid(x, y, z)
fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(X, Y, Z)
plt.xlabel('x')
plt.ylabel('y')
plt.show()
First error is:
/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:2: RuntimeWarning: invalid value encountered in power
And the second is:
ValueError: Argument Z must be 2-dimensional.

You can try:
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
The meshgrid function returns coordinate matrices from coordinate vectors.. Then, you can apply the function and plot it.
For the "RuntimeWarning: invalid value encountered in power" warning, that is related to the decimal power on numpy objects. Please have a look at this topic NumPy, RuntimeWarning: invalid value encountered in power for more details.
Full code:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
def f(x,y):
return x**x*y
x = np.arange(-4.0, 4.0, 0.1)
y = np.arange(-4.0, 4.0, 0.1)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(X, Y, Z)
plt.xlabel('x')
plt.ylabel('y')
plt.show()
Output:

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.

3D plot in maplotlib

I try to visualize 3D surface using Matplolib.
I got a RESULTS.csv file with results:
T1,T2,Energy
0,0.0,0.0,0.0
1,0.0,-1.0,0.02326751
2,0.0,1.0,0.0232677
3,0.0,-2.0,0.09329646
4,0.0,2.0,0.0932964
5,0.0,-3.0,0.20991799
6,0.0,3.0,0.2099179
7,0.0,-4.0,0.37299244
8,0.0,4.0,0.37299269
9,0.0,-5.0,0.58232459
10,0.0,5.0,0.58232482
11,0.0,-6.0,0.83765862
12,0.0,6.0,0.83765867
13,-1.0,0.0,0.02297095
14,1.0,0.0,0.02297112
15,-1.0,-1.0,0.09457491
16,-1.0,1.0,-0.00195612
17,1.0,-1.0,-0.00195583
18,1.0,1.0,0.09457513
19,-1.0,-2.0,0.21270257
20,-1.0,2.0,0.01988884
21,1.0,-2.0,0.01988887
22,1.0,2.0,0.21270261
23,-1.0,-3.0,0.37714697
24,-1.0,3.0,0.08936601
25,1.0,-3.0,0.08936597
26,1.0,3.0,0.37714726
27,-1.0,-4.0,0.58764634
28,-1.0,4.0,0.20399978
29,1.0,-4.0,0.20399997
30,1.0,4.0,0.58764618
Subsequently, I wrote a script:
#!/usr/bin/env python
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
FRAME = pd.read_csv('RESULTS.csv')
fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(-4, 4, 1.0)
xlen = len(X)
Y = np.arange(-4, 4, 1.0)
ylen = len(Y)
X, Y = np.meshgrid(X, Y)
Z = np.array(FRAME['Energy'])
colortuple = ('y', 'b')
colors = np.empty(X.shape, dtype=str)
for y in range(ylen):
for x in range(xlen):
colors[x, y] = colortuple[(x + y) % len(colortuple)]
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=colors,
linewidth=0, antialiased=False)
ax.set_zlim3d(-1, 1)
ax.w_zaxis.set_major_locator(LinearLocator(6))
plt.show()
Unfortunately it doesn't work in an expecting way and am getting the following error in return:
File "./test.py", line 27, in <module>
linewidth=0, antialiased=False)
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 1586, in plot_surface
X, Y, Z = np.broadcast_arrays(X, Y, Z)
File "/usr/local/lib/python2.7/site-packages/numpy/lib/stride_tricks.py", line 191, in broadcast_arrays
shape = _broadcast_shape(*args)
File "/usr/local/lib/python2.7/site-packages/numpy/lib/stride_tricks.py", line 126, in _broadcast_shape
b = np.broadcast(*args[:32])
ValueError: shape mismatch: objects cannot be broadcast to a single shape
Any tips how to fix this error?
Why do you need this buggy "pandas"-module at all?
Everytime I see someone perform "pandas" operations together with numpy and matplotlib there appear absurd errors..
If you read your .csv-file conventionally with xlrd and add each cell value to a numpy array, and all 3 arrays "X", "Y" and "Z" have same length, there is no problem plotting it...
See matplotlib example
http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
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)
print len(X)
print len(Y)
print len(Z) #all 3 arrays must have same length!
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
ax.set_zlim(-1.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()

Plotting surface - enhacing the output

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
def figure():
fig = plt.figure()
axes = fig.gca(projection='3d')
x = np.arange(-1.5, 1.5, 0.1)
y = np.arange(-1.5, 1.5, 0.1)
x, y = np.meshgrid(x, y)
f = lambda x, y: 1/np.log(y - (x-1)**0.5)
axes.plot_wireframe(x, y, f(x, y))
plt.show()
figure()
How can I "zoom" in to the figure (make it appear larger)?
Is there a way to make the figure look smoother when using axes.plot_surface instead?
In this scenario, I would prefer np.linspace over np.arange.
Many of the function values in your range are complex. Those values cannot be displayed. Here I use axes.set_xlim and axes.set_ylim to zoom into the real part of your function.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
def figure():
fig = plt.figure(figsize=(8,6))
axes = fig.gca(projection='3d')
x = np.linspace(-1.5, 1.5, 100)
y = np.linspace(-1.5, 1.5, 100)
x, y = np.meshgrid(x, y)
f = lambda x, y: 1/np.log(y - (x-1)**0.5)
axes.plot_wireframe(x, y, f(x, y))
axes.set_xlim(1,1.5)
axes.set_ylim(0,1.5)
figure()

Plot surface python with different width in mesh

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()

Categories