The plot3d figure in matplotlib is somewhat canted - python

I am using matplotlib to get a water fall figure, but the results look very strange. Anyone have any idea what could be wrong with it?
Here I attached the figures. The second one is the same data but in an ordinary plot. In the waterfall figure, why the color is not fully filled?
Here is the code:
def water_fall_1(x,y,Z):
#x=[...]
#y=[...]
#Z=[[z1],[z2],...z[ny]]
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import PolyCollection
from matplotlib.colors import colorConverter
from mpl_toolkits.mplot3d import Axes3D
figs=[]
for jc in range(len(y)):
figs.append(list(zip(x,Z[jc])))
x=np.array(x)
y=np.array(y)
Z=np.array(Z)
xmin=np.floor(np.min((x.astype(np.float))))
xmax=np.ceil(np.max((x.astype(np.float))))
ymin=np.min((y.astype(np.float)))
ymax=np.max((y.astype(np.float)))
zmin=(np.min((Z.astype(np.float))))
zmax=np.max((Z.astype(np.float)))
fig=plt.figure()
ax = Axes3D(fig)
poly = PolyCollection(figs, facecolors=colorConverter.to_rgba("r", alpha=0.5))
ax.add_collection3d(poly, zs=y.astype(np.float), zdir='y')
ax.set_xlim(xmin,xmax)
ax.set_ylim(ymin,ymax)
ax.set_zlim(zmin,zmax)
ax.set_xlabel('$\omega$')
ax.set_ylabel('$T$')
#ax.set_zlabel('$\\frac{1}{2}$')
plt.show()

The curve is fully filled. I.e. the surface in between the points of the curve is red.
Consider the following example:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import PolyCollection
from mpl_toolkits.mplot3d import Axes3D
bottom=-0.3
x = np.linspace(0,6, num=50)
z = np.sinc(x-4)
verts = zip(x,z)
#verts=verts + [(x.max(),bottom),(x.min(),bottom)]
fig=plt.figure()
ax = Axes3D(fig)
poly = PolyCollection([verts], facecolors="r", alpha=0.5)
ax.add_collection3d(poly, zs=1, zdir='y')
ax.set_xlim(x.min(),x.max())
ax.set_ylim(0,2)
ax.set_zlim(bottom,z.max())
plt.show()
which produces the following plot, where everything between the points of the curve is filled as expected.
If we now want to have the area between the curve and some bottom line filled, we would need to add some points,
verts=verts + [(x.max(),bottom),(x.min(),bottom)]
such that the bottom line is part of the curve and can thus be filled as well.

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

Showing end point of the 3d line: Python 3D plot

I made a 3D plot using the following code in python. Here three arrays x, y and z are used for the plot. I want to show the last point of the arrays (or the end point of the 3D line) in the plot. I used the approach I would use in 2d plotting, i.e., I asked for plotting only the last points of each array using this command ax.plot(x[-1],y[-1],z[-1],'o'). But it doesn't work.
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import
x=np.linspace(0,2*np.pi)
y=np.sin(x)
z=np.cos(x)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot(x, y, z, lw=1)
ax.plot(x[-1],y[-1],z[-1],'o') # This line doesn't work
plt.show()
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import
x=np.linspace(0,2*np.pi)
y=np.sin(x)
z=np.cos(x)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot(x, y, z, lw=1)
ax.scatter(x[-1],y[-1],z[-1],'-') # This should do the job
plt.show()
Add Color and Label
ax.scatter(x[-1],y[-1],z[-1],'-',c="yellow",label="End Point")
plt.legend()
plt.show()
Additional explanation on why you were having an error:
You were telling python to draw you a ax.plot for 1 point. Which is impossible, because you cant draw a line using 1 point only. Therefore, you tell it to draw a scatter.

Matplotlib: transformation of variables for narrow orbit

I have an annoyingly narrow orbit in phase space that looks like this:
What kind of transformation of the variables can I do to get a nice circular orbit in this case?
My code is this:
import numpy as np
import matplotlib.pylab as plt
x,y = np.loadtxt("data.txt").T
plt.plot(x,y)
plt.show()
The data can be found here - link
I'm not sure if this is what you're after. What you can do is shift one of the two coordinates by the quarter of a circle and normalize to the other coordinate.
import numpy as np
import matplotlib.pylab as plt
x,y = np.loadtxt("data/orbit.txt").T
y = np.roll(y, len(y)//4)
y = (y-y.mean())*((x.max()-x.min())/(y.max()-y.min())) +y.mean()
fig, (ax, ax2) = plt.subplots(ncols=2)
ax.set_aspect("equal")
ax.plot(x,y)
t = np.linspace(0,2*np.pi, len(x))
ax2.plot(t,x-x.mean())
ax2.plot(t,y-y.mean())
plt.show()

How to generate a colorbar for manually colored plots in matplotlib?

Suppose I need to control line colors myself for some reason, for example:
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
for i in np.linspace(0, 1, 100):
plt.plot([i,i+1,i+2], color=mpl.cm.viridis(i))
How to generate a colorbar for such a plot?
You would need to create a colorbar without any reference axes. This can be done with the matplotlib.colorbar.ColorbarBase class. See also this example from the gallery.
To use this, you need to create a new axis in the plot, where the colorbar should sit in; one way of doing this is to use make_axes_locatable.
Here is a complete example.
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np
for i in np.linspace(0, 1, 9):
plt.plot([i,i+1,i+2], color=mpl.cm.viridis(i))
divider = make_axes_locatable(plt.gca())
ax_cb = divider.new_horizontal(size="5%", pad=0.05)
cb1 = mpl.colorbar.ColorbarBase(ax_cb, cmap=mpl.cm.viridis, orientation='vertical')
plt.gcf().add_axes(ax_cb)
plt.show()

Plot a sphere that looks like a sphere

So I am sampling from a 3D sphere and want to display it and despite the plt.axis('equal') command it still looks elliptic rather than spheric. Here is my code:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def sphere_sampler(dimension=2,sample_size=1):
phi_1=np.random.uniform(low=0,high=np.pi,size=sample_size)
phi_2=np.random.uniform(low=0,high=2*np.pi,size=sample_size)
sample=np.empty((sample_size,dimension))
sample[:,0]=np.cos(phi_1)
sample[:,1]=np.sin(phi_1)*np.cos(phi_2)
sample[:,2]=np.sin(phi_1)*np.sin(phi_2)
return sample
pre_sample=sphere_sampler(3,1000)
sample=pre_sample.reshape(pre_sample.shape[0],3)
fig=plt.figure()
ax = fig.gca(projection='3d')
ax.scatter(sample[:,0],sample[:,1],sample[:,2])
ax.set_xlim(-1,1)
ax.set_ylim(-1,1)
ax.set_zlim(-1,1)
plt.axis('equal')
plt.show()
Which part of it I am doing wrong? It looks like that something is wrong with display. How can I make the show() method to not to change the scale?
instead of plt.axis('equal'), use:
ax.set_aspect("equal")

Categories