I have a matplotlib contourf plot of longitudes and pressure levels in the vertical. I am trying to plot streamlines on this using the plt.streamplot function in matplotlib and using U and V wind data.
If I plot only the streamplot, it works fine. But I cannot get the streamlines to overlay on the contour plot.
Here is my code:-
fig, axes = plt.subplots(nrows, ncols, sharex=True, sharey=True)
if (nrows==1 and ncols==1):
axes=[axes]
else:
axes=axes.flat
for i, ax in enumerate(axes):
X,Y = np.meshgrid(x[i],y[i])
levels=np.arange(vmin,vmax,step)
h = ax.contourf(X,Y,z[i],cmap=cmap,levels=levels,extend='both')
w = ax.streamplot(X, Y, W[i], Z[i], linewidth=0.2, color='gray')
And this is the plot I get:
The following is the streamline plot, not sure why the y axis is from 0-120 instead of 0 to 1000:
You use curvilinear coordinate system for contour plot (lat-p).
You have to convert u,v to coordinate system of contour something like here (this is example for lat-lon you have to modify it to use pressure levels):
def myStreamPlot(lon,lat,u,v,color='k',density=2.5):
from scipy.interpolate import griddata
n,m = u.shape[1],u.shape[0]
x = np.linspace(np.nanmin(lon), np.nanmax(lon), n)
y = np.linspace(np.nanmin(lat), np.nanmax(lat), m)
xi, yi = np.meshgrid(x,y)
lon = lon.ravel()
lat = lat.ravel()
u = u.ravel()
v = v.ravel()
gu = griddata(zip(lon,lat), u, (xi,yi))
gv = griddata(zip(lon,lat), v, (xi,yi))
gspd = np.sqrt(gu**2 + gv**2)
SL = plt.streamplot(x,y,gu,gv,linewidth=1.,color=color,density=density)
This code use griddata function of scipy.interpolate: https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html
Related
I have to plot a surface plot which has axes x,y,z and a colormap set by a function of x,y,z [B(x,y,z)].
I have the coordinate arrays:
x=np.arange(-100,100,1)
y=np.arange(-100,100,1)
z=np.arange(-100,100,1)
Moreover, my to-be-colormap function B(x,y,z) is a 3D array, whose B(x,y,z)[i] elements are the (x,y) coordinates at z.
I have tried something like:
Z,X,Y=np.meshgrid(z,x,y) # Z is the first one since B(x,y,z)[i] are the (x,y) coordinates at z.
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
img = ax.scatter(Z, X, Y, c=B(x,y,z), cmap=plt.hot())
fig.colorbar(img)
plt.show()
However, it unsurprisingly plots dots, which is not what I want. Rather, I need a surface plot.
The figure I have obtained:
The kind of figure I want:
where the colors are determined by B(x,y,z) for my case.
You have to:
use plot_surface to create a surface plot.
your function B(x, y, z) will be used to compute the color parameter, a number assigned to each face of the surface.
the color parameter must be normalized between 0, 1. We use matplotlib's Normalize to achieve that.
then, you create the colors by applying the colormap to the normalized color parameter.
finally, you create the plot.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from matplotlib.colors import Normalize
t = np.linspace(0, 2*np.pi)
p = np.linspace(0, 2*np.pi)
t, p = np.meshgrid(t, p)
r1, r2 = 1, 3
x = (r2 + r1 * np.cos(t)) * np.cos(p)
y = (r2 + r1 * np.cos(t)) * np.sin(p)
z = r1 * np.sin(t)
color_param = np.sin(x / 2) * np.cos(y) + z
cmap = cm.jet
norm = Normalize(vmin=color_param.min(), vmax=color_param.max())
norm_color_param = norm(color_param)
colors = cmap(norm_color_param)
fig = plt.figure()
ax = fig.add_subplot(projection="3d")
ax.plot_surface(x, y, z, facecolors=colors)
ax.set_zlim(-4, 4)
plt.show()
I have a function u(x,y,z,t) and I wanted to plot (x,y) animated heatmap with colorbar (u_min, u_max) where t is parameter for time animation. I've analyzed the examples, but it looks complicated. The z parameter will be constant. The defined u(x,y,z,t) is the equation
u(x,y,z,t).
I made this
import matplotlib.pyplot as plt
import numpy as np
def u(x, y, z, t):
alpha = 9*10**-6
a = 0.01
z = a/2
for i in range(1,k):
sin1 = np.sin((i*np.pi*x)/a)
sin2 = np.sin((i*np.pi*y)/a)
sin3 = np.sin((i*np.pi*z)/a)
e = np.exp(-((alpha**2)*(np,pi**2)*((n**2)*(m**2)*(l**2))*t/a**2)
a_n = 80*(2/np.pi)**3*(1/n*m*l)*(1-(-1)**n)*(1-(-1)**m)*(1-(-1)**l)
u += 20 + a_n*sin1*sin2*sin3*e
return u
data = u
fig, ax = plt.subplots()
for j in range(len(data)):
ax.cla()
ax.imshow(data[j])
ax.set_title("frame {}".format(i))
plt.pause(0.1)
Thank you for help.
I have a issue to interpolate my values "c" on cylindrical surface.
The problem is that possibly I dont understand how to indicate surface for gridding with gridddata function..
>import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata as gd
#Creating data in polar coordinates
phi,d = np.linspace(0, 2* np.pi, 20), np.linspace(0,20,20)
PHI,D = np.meshgrid(phi,d)
R = 2
#Transforming in X Y Z coordinates
X = R * np.cos(PHI)
Y = R * np.sin(PHI)
Z = R * D
T=np.linspace(0,10,400)
c=np.sin(T)*np.cos(T/2) #Value c I would like to interpolate
fig1 = plt.figure()
ax = fig1.add_subplot(1,1,1, projection='3d')
xi=np.array(np.meshgrid(X,Y,Z))
img = ax.scatter(X, Y, Z,c=c, cmap=plt.hot()) #To plot data scatter before interpolation
fig1.colorbar(img)
plt.show()
X1,Y1,Z1 =np.meshgrid(X ,Y ,Z) #To define sufrace for interpolation
int = gd((X,Y,Z), c, (X1,Y1,Z1), method='linear')
fig2 = plt.figure() #trying to plot the answer
ax1 = fig2.add_subplot(1,1,1, projection='3d')
ax1.scatter(int)
img = ax1.scatter(X, Y, Z, c=c, cmap=plt.hot())
`
Its gives error: different number of values and points
I dont know how to indicate (X1,Y1,Z1) surface in griddata function
Thanks a lot for any tips ...
I have a set of X,Y data points(from Remote sensing image),and I drew a scatter plot through the tutorial, the link is as follows:Generate a heatmap in MatPlotLib using a scatter data set
But when I try to draw a heat map, an error occurs:Heatmap cannot be displayed.
Is there a way to display two-dimensional data in a heat map, the different colors in the heat map represent the density of the pixels?
This is my code and result:
import rasterio
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from scipy.ndimage.filters import gaussian_filter
def myplot(x, y, s, bins=1000):
heatmap, xedges, yedges = np.histogram2d(x, y, bins=bins)
heatmap = gaussian_filter(heatmap, sigma=s)
extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]
return heatmap.T, extent
fig, axs = plt.subplots(1, 2)
dataset = rasterio.open('E:/Jupyter Notebook/LC81490312016259LGN00/LC8_subset_layerstacking.tif')
red_band = dataset.read(4)
NIR_band = dataset.read(5)
np.seterr(divide='ignore', invalid='ignore')
ndvi = (NIR_band.astype(float)-red_band.astype(float))/(NIR_band.astype(float)+red_band.astype(float))
ndvi_flat = np.ndarray.flatten(ndvi)
red_band_flat = np.ndarray.flatten(red_band)
x = ndvi_flat
y = red_band_flat
sigmas = [0, 16]
for ax, s in zip(axs.flatten(), sigmas):
if s == 0:
ax.plot(x, y, 'k.', markersize=0.1)
#ax.set_aspect('equal')
ax.set_title("Scatter plot")
ax.set_xlabel('NDVI')
ax.set_ylabel('Red Reflectance')
else:
img, extent = myplot(x, y, s)
ax.imshow(img, origin='lower',cmap=cm.jet)
ax.set_title("Smoothing with $\sigma$ = %d" % s)
ax.set_xlabel('NDVI')
ax.set_ylabel('Red Reflectance')
plt.show()
The left image is a black scatter plot (no pixel density information), and the right image is a heat map
The code and the data I need to process are stored in GitHub:https://github.com/Flyinfish-gzh/remote-sensing-data-visualization
I've asked a similar question before (How to set a fixed/static size of circle marker on a scatter plot?), but now I wanna do it in 3D. How can I do that?
thanks
As in the 2D case, you need to draw the spheres yourself. If you want nicely shaped spheres this means to draw many patches and thus gets slow quite quickly.
Here's a basic way of doing it:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
def plot_shere(ax, x, y, z, r, resolution=100, **kwargs):
""" simple function to plot a sphere to a 3d axes """
u = np.linspace(0, 2 * np.pi, resolution)
v = np.linspace(0, np.pi, resolution)
xx = r * np.outer(np.cos(u), np.sin(v)) + x
yy = r * np.outer(np.sin(u), np.sin(v)) + y
zz = r * np.outer(np.ones(np.size(u)), np.cos(v)) + z
ax.plot_surface(xx, yy, zz, rstride=4, cstride=4, **kwargs)
# create some random data (set seed to make it reproducable)
np.random.seed(0)
(x,y,z) = np.random.randint(0,10,(3,5))
r = np.random.randint(2,4,(5,))
# set up the figure
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# loop through the data and plot the spheres
for p in zip(x,y,z,r):
plot_shere(ax, *p, edgecolor='none', color=np.random.rand(3))
# set the axes limits and show the plot
ax.set_ylim([-4,14])
ax.set_xlim([-4,14])
ax.set_zlim([-4,14])
plt.show()
Result: