How to plot a 2d structured mesh in matplotlib - python

I am trying to use matplotlib to plot the structured mesh (See the figure below)
import numpy as np
import matplotlib.pyplot as plt
x, y = np.meshgrid(np.linspace(0,1, 11), np.linspace(0, 0.6, 7))
plt.scatter(x, y)
plt.show()
I got a discrete points, but I have no idea how to connect them to get something like this:
The desired result is:
I appreciate any help

I'd use two linecollections for this:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
x, y = np.meshgrid(np.linspace(0,1, 11), np.linspace(0, 0.6, 7))
plt.scatter(x, y)
segs1 = np.stack((x,y), axis=2)
segs2 = segs1.transpose(1,0,2)
plt.gca().add_collection(LineCollection(segs1))
plt.gca().add_collection(LineCollection(segs2))
plt.show()
Also see How to plot using matplotlib (python) colah's deformed grid?
Because if the grid is not deformed, it would be more efficient to draw a single linecollection, like
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
x, y = np.meshgrid(np.linspace(0,1, 11), np.linspace(0, 0.6, 7))
segs1 = np.stack((x[:,[0,-1]],y[:,[0,-1]]), axis=2)
segs2 = np.stack((x[[0,-1],:].T,y[[0,-1],:].T), axis=2)
plt.gca().add_collection(LineCollection(np.concatenate((segs1, segs2))))
plt.autoscale()
plt.show()

You can np.transpose the points you already have, while using a line plot() rather than scatter().
import numpy as np
import matplotlib.pyplot as plt
x, y = np.meshgrid(np.linspace(0,1, 11), np.linspace(0, 0.6, 7))
plt.plot(x, y) # use plot, not scatter
plt.plot(np.transpose(x), np.transpose(y)) # add this here
plt.show()
You can of course have it colored in black with c='k'

IIUC, vlines and hlines would do:
plt.vlines(np.linspace(0,1,11), 0, 0.6)
plt.hlines(np.linspace(0,0.6,7), 0, 1)
If you already have mesh x,y:
plt.vlines(x[0], *y[[0,-1],0])
plt.hlines(y[:,0], *x[0, [0,-1]])
Out:

Related

How to plot multiple parametric plots in a single figure?

I need to plot a family of parametric curves in a single figure for each alpha values as mentioned in the code
import numpy as np
from sympy import *
from sympy.plotting import plot_parametric
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
a=45
t = symbols('t')
for alpha in np.arange(0.5,3,.1):
M=a*sqrt(cos(2*t)+sqrt(pow(alpha,4)+pow(sin(2*t),2)))
x = M*cos(t)
y = M*sin(t)
plot_parametric(x, y, (t, 0, 2*pi))
The code returns a sequence of 2D plots for each alpha value. Instead, I want to plot the whole set of plots in one figure, something like this image attached
Any solution?
from numpy import arange, cos, linspace, pi, sin, sqrt
from matplotlib.pyplot import colorbar, Normalize, show, subplots
from matplotlib.cm import ScalarMappable, viridis
a=45
t= linspace(0, 2*pi, 2001)
norm = Normalize(vmin=0.5, vmax=3)
cmap = viridis
sm = ScalarMappable(cmap=cmap, norm=norm)
fig, (ax_xy, ax_tM) = subplots(1, 2, figsize=(10, 4), constrained_layout=1)
for alpha in arange(0.5,3,.1):
color = cmap(norm(alpha))
M=a*sqrt(cos(2*t)+sqrt(pow(alpha,4)+pow(sin(2*t),2)))
x = M*cos(t)
y = M*sin(t)
ax_tM.plot(t, M, color=color)
ax_xy.plot(x, y, color=color)
colorbar(sm, aspect=40)
show()

Plot a plane in 3D python plot [duplicate]

I was unsuccessful browsing web for a solution for the following simple question:
How to draw 3D polygon (say a filled rectangle or triangle) using vertices values?
I have tried many ideas but all failed, see:
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.collections import PolyCollection
import matplotlib.pyplot as plt
fig = plt.figure()
ax = Axes3D(fig)
x = [0,1,1,0]
y = [0,0,1,1]
z = [0,1,0,1]
verts = [zip(x, y,z)]
ax.add_collection3d(PolyCollection(verts),zs=z)
plt.show()
I appreciate in advance any idea/comment.
Updates based on the accepted answer:
import mpl_toolkits.mplot3d as a3
import matplotlib.colors as colors
import pylab as pl
import numpy as np
ax = a3.Axes3D(pl.figure())
for i in range(10000):
vtx = np.random.rand(3,3)
tri = a3.art3d.Poly3DCollection([vtx])
tri.set_color(colors.rgb2hex(np.random.rand(3)))
tri.set_edgecolor('k')
ax.add_collection3d(tri)
pl.show()
Here is the result:
I think you've almost got it. Is this what you want?
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import matplotlib.pyplot as plt
fig = plt.figure()
ax = Axes3D(fig, auto_add_to_figure=False)
fig.add_axes(ax)
x = [0,1,1,0]
y = [0,0,1,1]
z = [0,1,0,1]
verts = [list(zip(x,y,z))]
ax.add_collection3d(Poly3DCollection(verts))
plt.show()
You might also be interested in art3d.pathpatch_2d_to_3d.
The above solution is for Python 2, and gives an error 'TypeError: object of type 'zip' has no len()' when run with python 3.
See Plotting 3D Polygons in Python 3 for discussion on updating this to Python 3.
Here's some working code from there:
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import matplotlib.pyplot as plt
fig = plt.figure()
ax = Axes3D(fig)
x = [0, 1, 1, 0]
y = [0, 0, 1, 1]
z = [0, 1, 0, 1]
verts = [list(zip(x, y, z))]
print(verts)
ax.add_collection3d(Poly3DCollection(verts), zs='z')
plt.show()

How can I plot surface on mplot3d for data like (x,y,z)=(0,0,1),(0,0,2)

How can I plot surface on mplot3d for data like
(x,y,z)=(0,0,1),(0,0,2)......
I'm currently using mplot3d on python and I have a scatter data like
(x,y,z) = (0,1,3),(0,8,9),(1,5,24)......
I tried ax.scatter(xp,yp,zp), then scatter graph can be shown.
But when i try ax.plot_trisurf(xp,yp,zp) for all the data, and plt.show() then nothing appears on graph.
How can I plot surface graph from this data?
Any help would be appreciated, thanks.
As you currently have it, x = (0,1,3), y = (0,8,9) and z=(1,5,24). I think you actually need to use zip on your coordinates:
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib.pyplot as plt
x,y,z = zip((0,1,3),(0,8,9),(1,5,24))
print x
# (0, 0, 1)
print y
# (1, 8, 5)
print z
# (3, 9, 24)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_trisurf(x, y, z, cmap=cm.jet, linewidth=0.2)
plt.show()

How to change plot from connecting points to vertical sticks?

The following code will create a plot by connecting points.
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 5, 0.1);
y = np.sin(x)
plt.plot(x, y)
plt.show()
How can I change the plot to vertical sticks instead of connecting points? I.e., change to the type of plot of the following example:
Thanks.
Use plt.bar
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 5, 0.1);
y = np.sin(x)
plt.bar(x, y, width=0.08,edgecolor='None',color='k',align='center')
plt.show()

Smoothed 2D histogram using matplotlib and imshow

I try to do a 2D histogram plot and to obtain a "smooth" picture by a sort of interpolation. Thus I do the following combining plt.hist2d and plt.imshow
import matplotlib.pyplot as plt
import numpy as np
data = np.loadtxt("parametre_optMC.dat", skiprows=50, usecols=(1,2))
h, x, y, p = plt.hist2d(data[:,0], data[:,1], bins = 20)
plt.imshow(h, origin = "lower", interpolation = "gaussian")
plt.savefig("test.pdf")
As you can see on the picture below, the two plots are superimposed and that is the problem for which I need some help
Adding clf works but I lose axes dimenions :
import matplotlib.pyplot as plt
import numpy as np
data = np.loadtxt("parametre_optMC.dat", skiprows=50, usecols=(1,2))
h, x, y, p = plt.hist2d(data[:,0], data[:,1], bins = 20)
plt.clf()
plt.imshow(h, origin = "lower", interpolation = "gaussian")
plt.savefig("test.pdf")
Perhaps it would be better to plot a kernel density estimate?
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
data = np.random.multivariate_normal([0, 0], [(1, .6), (.6, 1)], 100)
f, ax = plt.subplots(figsize=(7, 7))
sns.kdeplot(data, shade=True, ax=ax)
To your first question:
You need to clear data from a previous plot, putting the following before you plot should do this:
plt.clf()
plt.close()
To your second question:
To change the axis values I'd suggest the extent parameter (see this answer).
e.g. something like:
plt.imshow(h, origin = "lower", interpolation = "gaussian",extent=[-100,100,-75,75])
You need to add the 'extent' parameter to you imshow command. imshow accepts a grid of arbitrary values but does not know the dimensions.

Categories