making a 3D quiver plot using matplotlib by reading in data - python
I am trying to make a 3D quiver plot using matplotlib 2.2.5. I provide a simple sample code below to show my attempt. I want to make a quiver plot using fx(x,y,z), fy(x,y,z) and fz(x,y,z). These correspond to the vector field f = (fx,fy,fz). I input the data for fx,fy,fz as 3 .dat files where each .dat file is 1 column of numbers.
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt #I'm using matplotlib 2.2.5
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
fx = np.genfromtxt('fx.dat')
fy = np.genfromtxt('fy.dat')
fz = np.genfromtxt('fz.dat')
N = 10
Fx = fx[::N,::N]
Fy = fy[::N,::N]
Fz = fz[::N,::N]
nrows, ncols = Fx.shape
nx = 1
ny = 1
nz = 1
x = np.linspace(-nx, nx, ncols)
y = np.linspace(-ny, ny, ncols)
z = np.linspace(-nz, nz, ncols)
xi, yi, zi = np.meshgrid(x, y, z, indexing='ij')
plt.quiver(xi, yi, zi, Fx, Fy, Fz, edgecolor='k', facecolor='black', linewidth=.5)
plt.axis('scaled')
plt.show()
The data is generated and stored as follows (using fortran):
!generate data
DO i = -nx,nx !nx = 1
DO j = -ny,ny !ny = 1
DO k = -nz,nz !nz = 1
fx(i,j,k) = i + 2.*j + 3.*k !this is a function fx that depends on x,y,z; fx(x,y,z)
fy(i,j,k) = i - 4.*j + k !this is a function fy that depends on x,y,z; fy(x,y,z)
fz(i,j,k) = i + 2*j + k !this is a function fz that depends on x,y,z; fz(x,y,z)
END DO
END DO
END DO
!store data
DO i = -nx,nx
DO j = -ny,ny
DO k = -nz,nz
WRITE(1,*) fx(i,j,k) !stores fx(x,y,z)
WRITE(2,*) fy(i,j,k) !stores fy(x,y,z)
WRITE(3,*) fz(i,j,k) !stores fz(x,y,z)
END DO
END DO
END DO
I'm assuming here you are trying to plot the quivers starting from the (origin (0,0,0)).
Using a random sample with coordinates between -1 and 1 (hoping it will match your data sample), this would go this way:
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
fx = np.genfromtxt('fx.dat')
fy = np.genfromtxt('fy.dat')
fz = np.genfromtxt('fz.dat')
N = 10
Fx = fx[:N]
Fy = fy[:N]
Fz = fz[:N]
Note that I used a simple ":": based on your explanation, your .dat files have only one dimension. You use multiples colon only if you have at least 2 dimensions.
plt.quiver(0, 0, 0, Fx, Fy, Fz, edgecolor='k', facecolor='black', linewidth=.5) #To plot starting from the origin
ax.set_xlim(-1,1)
ax.set_ylim(-1,1)
ax.set_zlim(-1,1)
plt.show()
If you want to plot starting from your mesh (ie np.linspace), you can alter the code as follow (though I'm not sure this is what you are trying to achieve):
nx = 1
ny = 1
nz = 1
x = np.linspace(-nx, nx, N)
y = np.linspace(-ny, ny, N)
z = np.linspace(-nz, nz, N)
plt.quiver(x, y, z, Fx, Fy, Fz, edgecolor='k', facecolor='black', linewidth=.5)
ax.set_xlim(-2,2) #I altered the bounds to match the new coordinates
ax.set_ylim(-2,2)
ax.set_zlim(-2,2)
Note: this code has been tested on matplotlib 3.0.1 only
Related
3D plane in Python
I used the following code to try and plot a 3D plane of on its x axis the height (is also the momentum arm) and on its y axis the mass (in kg) which has a linear connection with the force used. The Z axis is the resulting momentum. Unfortunately I get the following error: ValueError: Argument Z must be 2-dimensional. However I do believe that Z, thus the momentum is dependent on both the mass and the height, thus is Z 2d. import matplotlib.pyplot as plt import numpy as np from mpl_toolkits import mplot3d g = 9.81 m = np.linspace(0, 1, 301) H_1 = np.arange(100, 401, 1) for i, kg in enumerate(m): Fg = -m[i]*g M = np.zeros(len(H_1)) for i, mm in enumerate(H_1): F1 = np.array([0, Fg]) F2 = np.array([Fg * np.sin(np.arctan(200 / H_1[i])), Fg * np.cos(np.arctan(200 / H_1[i]))]) Fres = np.add(F1, F2) M_arm = np.array([0, H_1[i]]) M[i] = np.cross(M_arm, Fres)/10e3 x,y = np.meshgrid(H_1,m) z = M fig = plt.figure() ax = fig.add_subplot(projection='3d') ax.plot_surface(x, y, z) ax.set_xlabel('hoogte toren in (mm)') ax.set_ylabel('massa') ax.set_zlabel('momentum') plt.show()
Check this out: import matplotlib.pyplot as plt import numpy as np from mpl_toolkits import mplot3d g = 9.81 m = np.linspace(0, 1, 301) H_1 = np.arange(100, 401, 1) Fg = -m * g M = np.zeros(len(H_1)) for i, mm in enumerate(H_1): F1 = np.array([0, Fg[i]]) F2 = np.array([Fg[i] * np.sin(np.arctan(200 / H_1[i])), Fg[i] * np.cos(np.arctan(200 / H_1[i]))]) Fres = np.add(F1, F2) M_arm = np.array([0, H_1[i]]) M[i] = np.cross(M_arm, Fres) / 10e3 x, y = np.meshgrid(H_1, m) z = M fig = plt.figure() ax = fig.add_subplot(projection='3d') ax.plot_surface(x, y, z) ax.set_xlabel('hoogte toren in (mm)') ax.set_ylabel('massa') ax.set_zlabel('momentum') plt.show() I made the following changes to your code: Moved the calculation of Fg outside the loop. Used the correct index i to access the elements of m and Fg in the loop. Used the correct array index i to access the elements of H_1 in the loop. Removed the unnecessary enumerate call in the inner loop. Used the correct array index i to access the elements of M in the loop. These changes should fix the errors in your code and produce the expected plot. :)
Colored gradient on multiple lines from a csv in 3D plot?
Disclaimer: I'm a total newb to this, 2nd day so pls bear with me, thank you in advance! So, I managed to get my 3D plot to have multiple lines, but I would like to give them some color gradients. I've managed to get it onto one example line, but I cannot convert it to my own plots. My plots come from a .csv I followed this question for the gradients: https://stackoverflow.com/a/8505774/20387853 (Answer by Yann) but I can't seem to understand how to merge the two for i in range bits (one from my old code with the new code) (if it even can be?) I also dont understand ax.plot(x[i:i+2],y[i:i+2]) so I couldn't adjust this like I thought I could. SO ATM i have two scripts Script 1 - in which I'm trying to merge my two data sets. import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import sys import pandas points = pandas.read_csv('D:Documents\PYTHON_FILES/test3d.csv') def highResPoints(x,y,factor=10): # r is the distance spanned between pairs of points r = [0] for i in range(1,len(x)): dx = x[i]-x[i-1] dy = y[i]-y[i-1] r.append(np.sqrt(dx*dx+dy*dy)) r = np.array(r) # rtot is a cumulative sum of r, it's used to save time rtot = [] for i in range(len(r)): rtot.append(r[0:i].sum()) rtot.append(r.sum()) dr = rtot[-1]/(NPOINTS*RESFACT-1) xmod=[x[0]] ymod=[y[0]] rPos = 0 # current point on walk along data rcount = 1 while rPos < r.sum(): x1,x2 = x[rcount-1],x[rcount] y1,y2 = y[rcount-1],y[rcount] dpos = rPos-rtot[rcount] theta = np.arctan2((x2-x1),(y2-y1)) rx = np.sin(theta)*dpos+x1 ry = np.cos(theta)*dpos+y1 xmod.append(rx) ymod.append(ry) rPos+=dr while rPos > rtot[rcount+1]: rPos = rtot[rcount+1] rcount+=1 if rcount>rtot[-1]: break return xmod,ymod #CONSTANTS NPOINTS = 10 COLOR='red' RESFACT=10 MAP='winter' # choose carefully, or color transitions will not appear smoooth cm = plt.get_cmap(MAP) ################ These are old data sets, just to use for this example x = points['x'].values y = points['y'].values z = points['z'].values x2 = points['x2'].values y2 = points['y2'].values z2 = points['z2'].values fig = plt.figure() #ax1 = fig.add_subplot(111,projection='3d') # regular resolution color map ax = fig.add_subplot(111, projection='3d') ax.plot(x, y, z, c='red',marker='v', linewidth=1.0, markersize=2) ax.plot(x2, y2, z2, c='blue', marker='o', linewidth=1.0, markersize=2) ax.set_prop_cycle(color=[cm(1.*i/(NPOINTS-1)) for i in range(NPOINTS-1)]) for i in range(NPOINTS-1): #ax1.plot(x[i:i+2],y[i:i+2]) ax.plot(x[i:i+2],y[i:i+2]) ########################The part I want to merge in #for i in range(1, 5): #if i == 1: i = '' #x is your first value not x1 #ax.plot(points[f"x{i}"], points[f"y{i}"], points[f"z{i}"], c='red', marker='o', linewidth=1.0, markersize=2) ######################### fig.savefig('colorgradienttest.png') plt.show() [Link to Image] I want to make the blue and red lines have a color gradient like the example 3rd line (markers are not important) Script 2 - to which I want to apply the gradient (the one with the .csv) from mpl_toolkits.mplot3d import Axes3D import sys import matplotlib.pyplot as plt import pandas import numpy as np points = pandas.read_csv('D:Documents\PYTHON_FILES/test3d.csv') fig = plt.figure() ax = fig.add_subplot(111, projection='3d') #OPTION 1 - not sure why this isn't working for me so Im not using it yet #for idx in range(29): # suffix = '' if idx == 0 else str(idx + 1) # ranges start at 0 # x = points[f"x{suffix}"].values # y = points[f"y{suffix}"].values # z = points[f"z{suffix}"].values #ax.plot(x, y, z, c='red', marker='o', linewidth=1.0, markersize=2) #OPTION 2 - current approach <<<<<<<<<<<<<<<< want to apply gradient to this segment for i in range(1, 5): if i == 1: i = '' #x is your first value not x1 ax.plot(points[f"x{i}"], points[f"y{i}"], points[f"z{i}"], c='red', marker='o', linewidth=1.0, markersize=2) plt.show()
Rounding the edges of a cylinder in matplotlib poly3D
I have the following code which produces a cylinder-like object using matplotlib: from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt from mpl_toolkits.mplot3d.art3d import Poly3DCollection import numpy as np fig = plt.figure() ax = fig.gca(projection='3d') nphi,nz=7,20 r=1 # radius of cylinder phi = np.linspace(0,360, nphi)/180.0*np.pi z= np.linspace(0,1.0,nz) print z cols=[] verts2 = [] for i in range(len(phi)-1): cp0= r*np.cos(phi[i]) cp1= r*np.cos(phi[i+1]) sp0= r*np.sin(phi[i]) sp1= r*np.sin(phi[i+1]) for j in range(len(z)-1): z0=z[j] z1=z[j+1] verts=[] verts.append((cp0, sp0, z0)) verts.append((cp1, sp1, z0)) verts.append((cp1, sp1, z1)) verts.append((cp0, sp0, z1)) verts2.append(verts) value=np.random.rand() #print value col=plt.cm.rainbow(0.9) #print col cols.append(col) poly3= Poly3DCollection(verts2, facecolor=cols,edgecolor = "none" ) poly3.set_alpha(0.8) ax.add_collection3d(poly3) ax.set_xlabel('X') ax.set_xlim3d(-1, 1) ax.set_ylabel('Y') ax.set_ylim3d(-1, 1) ax.set_zlabel('Z') ax.set_zlim3d(0, 1) plt.show() This code produces the following image: However as you can see the are sharp corners in the figure. Is there anyway to make these edges rounder so that the figure looks like a proper cylinder with a circular cross-section as opposed to a hexagonal cross-section?
The third argument to np.linspace controls how many values you want it to generate. Thus, nphi controls the number of values in phi, and nz controls the number of values in z: phi = np.linspace(0,360, nphi)/180.0*np.pi z = np.linspace(0,1.0,nz) So if you increase nphi, then you'll get more points along the circle: cp0 = r*np.cos(phi[i]) sp0 = r*np.sin(phi[i]) For example, try changing nphi, nz = 7,20 to nphi, nz = 70, 2. Note that there is no need for nz to be greater than 2 since the sides of the cylinder are flat in the z direction. By the way, the double for-loop can be replaced by: PHI, Z = np.meshgrid(phi, z) CP = r * np.cos(PHI) SP = r * np.sin(PHI) XYZ = np.dstack([CP, SP, Z]) verts = np.stack( [XYZ[:-1, :-1], XYZ[:-1, 1:], XYZ[1:, 1:], XYZ[1:, :-1]], axis=-2).reshape(-1, 4, 3) So, for example, from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt from mpl_toolkits.mplot3d.art3d import Poly3DCollection import numpy as np fig = plt.figure() ax = fig.gca(projection='3d') nphi, nz = 70, 2 r = 1 # radius of cylinder phi = np.linspace(0, 360, nphi) / 180.0 * np.pi z = np.linspace(0, 1.0, nz) PHI, Z = np.meshgrid(phi, z) CP = r * np.cos(PHI) SP = r * np.sin(PHI) XYZ = np.dstack([CP, SP, Z]) verts = np.stack( [XYZ[:-1, :-1], XYZ[:-1, 1:], XYZ[1:, 1:], XYZ[1:, :-1]], axis=-2).reshape(-1, 4, 3) cmap = plt.cm.rainbow cols = cmap(np.random.random()) poly3 = Poly3DCollection(verts, facecolor=cols, edgecolor="none") poly3.set_alpha(0.8) ax.add_collection3d(poly3) ax.set_xlabel('X') ax.set_xlim3d(-1, 1) ax.set_ylabel('Y') ax.set_ylim3d(-1, 1) ax.set_zlabel('Z') ax.set_zlim3d(0, 1) plt.show() yields
How do you create a 3D surface plot with missing values matplotlib?
I am trying to create a 3D surface energy diagram where an x,y position on a grid contains an associated z level. The issue is that the grid is not uniform (ie, there is not a z component for every x,y position). Is there a way to refrain from plotting those values by calling them NaN in the corresponding position in the array? Here is what I have tried so far: import numpy as np from matplotlib import pyplot as plt from mpl_toolkits.mplot3d import Axes3D import pylab from matplotlib import cm #Z levels energ = np.array([0,3.5,1,-0.3,-1.5,-2,-3.4,-4.8]) #function for getting x,y associated z values? def fun(x,y,array): return array[x] #arrays for grid x = np.arange(0,7,0.5) y = np.arange(0,7,0.5) #create grid X, Y = np.meshgrid(x,y) zs = np.array([fun(x,y,energ) for x in zip(np.ravel(X))]) Z = zs.reshape(X.shape) plt3d = plt.figure().gca(projection='3d') #gradients now with respect to x and y, but ideally with respect to z only Gx, Gz = np.gradient(X * Y) G = (Gx ** 2 + Gz ** 2) ** .5 # gradient magnitude N = G / G.max() # normalize 0..1 plt3d.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=cm.jet(N), edgecolor='k', linewidth=0, antialiased=False, shade=False) plt.show() I cannot post image here of this plot but if you run the code you will see it But I would like to not plot certain x,y pairs, so the figure should triangle downward to the minimum. Can this be accomplished by using nan values? Also would like spacing between each level, to be connected by lines. n = np.NAN #energ represents the z levels, so the overall figure should look like a triangle. energ = np.array([[0,0,0,0,0,0,0,0,0,0,0,0,0],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,2.6,n,2.97,n,2.6,n,2.97,n,2.6,n,3.58,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,1.09,n,1.23,n,1.09,n,1.23,n,1.7,n,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,-0.65,n,-0.28,n,-0.65,n,0.33,n,n,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,n,-2.16,n,-2.02,n,-1.55,n,n,n,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,n,n,-3.9,n,-2.92,n,n,n,n,n,],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,n,n,n,-4.8,n,n,n,n,n,n,]]) plt3d = plt.figure().gca(projection='3d') Gx, Gz = np.gradient(X * energ) # gradients with respect to x and z G = (Gx ** 2 + Gz ** 2) ** .5 # gradient magnitude N = G / G.max() # normalize 0..1 x = np.arange(0,13,1) y = np.arange(0,13,1) X, Y = np.meshgrid(x,y) #but the shapes don't seem to match up plt3d.plot_surface(X, Y, energ, rstride=1, cstride=1, facecolors=cm.jet(N), edgecolor='k', linewidth=0, antialiased=False, shade=False ) Using masked arrays generates the following error: local Python[7155] : void CGPathCloseSubpath(CGMutablePathRef): no current point. n = np.NAN energ = np.array([[0,0,0,0,0,0,0,0,0,0,0,0,0],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,2.6,n,2.97,n,2.6,n,2.97,n,2.6,n,3.58,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,1.09,n,1.23,n,1.09,n,1.23,n,1.7,n,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,-0.65,n,-0.28,n,-0.65,n,0.33,n,n,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,n,-2.16,n,-2.02,n,-1.55,n,n,n,n],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,n,n,-3.9,n,-2.92,n,n,n,n,n,],[n,n,n,n,n,n,n,n,n,n,n,n,n],[n,n,n,n,n,n,-4.8,n,n,n,n,n,n,]]) x = np.arange(0,13,1) y = np.arange(0,13,1) X, Y = np.meshgrid(x,y) #create masked arrays mX = ma.masked_array(X, mask=[[0,0,0,0,0,0,0,0,0,0,0,0,0],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,0,1,0,1,0,1,0,1,0,1,0,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,0,1,0,1,0,1,0,1,0,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,0,1,0,1,0,1,0,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,0,1,0,1,0,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,0,1,0,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,0,1,1,1,1,1,1]]) mY = ma.masked_array(Y, mask=[[0,0,0,0,0,0,0,0,0,0,0,0,0],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,0,1,0,1,0,1,0,1,0,1,0,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,0,1,0,1,0,1,0,1,0,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,0,1,0,1,0,1,0,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,0,1,0,1,0,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,0,1,0,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,0,1,1,1,1,1,1]]) m_energ = ma.masked_array(energ, mask=[[0,0,0,0,0,0,0,0,0,0,0,0,0],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,0,1,0,1,0,1,0,1,0,1,0,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,0,1,0,1,0,1,0,1,0,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,0,1,0,1,0,1,0,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,0,1,0,1,0,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,0,1,0,1,1,1,1,1],[1,1,1,1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,0,1,1,1,1,1,1]]) plt3d = plt.figure().gca(projection='3d') plt3d.plot_surface(mX, mY, m_energ, rstride=1, cstride=1, edgecolor='k', linewidth=0, antialiased=False, shade=False) plt.show()
I was playing around with the code from this forum post, and I was able to make the graph have missing values. You can try the code yourself! I got it to work using float("nan") for the missing values. import plotly.graph_objects as go import numpy as np x = np.arange(0.1,1.1,0.1) y = np.linspace(-np.pi,np.pi,10) #print(x) #print(y) X,Y = np.meshgrid(x,y) #print(X) #print(Y) result = [] for i,j in zip(X,Y): result.append(np.log(i)+np.sin(j)) result[0][0] = float("nan") upper_bound = np.array(result)+1 lower_bound = np.array(result)-1 fig = go.Figure(data=[ go.Surface(z=result), go.Surface(z=upper_bound, showscale=False, opacity=0.3,colorscale='purp'), go.Surface(z=lower_bound, showscale=False, opacity=0.3,colorscale='purp')]) fig.show()
Plotting the temperature distribution on a sphere with python
I have the following problem: a have N points on a sphere specified by a array x, with x.shape=(N,3). This array contains their cartesian coordinates. Furthermore, at each point, I have a specified temperature. This quantity is saved in an array T, with T.shape=(N,). Is there any straight forward way to map this temperature distribution into the plane using different colors? If it simplifies the task, the position can also be given in polar coordinates (\theta,\phi).
To plot your data, you can use Basemap. The only problem is, that both contour and contourf routines needs gridded data. Here is example with naive (and slow) IDW-like interpolation on sphere. Any comments are welcome. import numpy as np from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt def cart2sph(x, y, z): dxy = np.sqrt(x**2 + y**2) r = np.sqrt(dxy**2 + z**2) theta = np.arctan2(y, x) phi = np.arctan2(z, dxy) theta, phi = np.rad2deg([theta, phi]) return theta % 360, phi, r def sph2cart(theta, phi, r=1): theta, phi = np.deg2rad([theta, phi]) z = r * np.sin(phi) rcosphi = r * np.cos(phi) x = rcosphi * np.cos(theta) y = rcosphi * np.sin(theta) return x, y, z # random data pts = 1 - 2 * np.random.rand(500, 3) l = np.sqrt(np.sum(pts**2, axis=1)) pts = pts / l[:, np.newaxis] T = 150 * np.random.rand(500) # naive IDW-like interpolation on regular grid theta, phi, r = cart2sph(*pts.T) nrows, ncols = (90,180) lon, lat = np.meshgrid(np.linspace(0,360,ncols), np.linspace(-90,90,nrows)) xg,yg,zg = sph2cart(lon,lat) Ti = np.zeros_like(lon) for r in range(nrows): for c in range(ncols): v = np.array([xg[r,c], yg[r,c], zg[r,c]]) angs = np.arccos(np.dot(pts, v)) idx = np.where(angs == 0)[0] if idx.any(): Ti[r,c] = T[idx[0]] else: idw = 1 / angs**2 / sum(1 / angs**2) Ti[r,c] = np.sum(T * idw) # set up map projection map = Basemap(projection='ortho', lat_0=45, lon_0=15) # draw lat/lon grid lines every 30 degrees. map.drawmeridians(np.arange(0, 360, 30)) map.drawparallels(np.arange(-90, 90, 30)) # compute native map projection coordinates of lat/lon grid. x, y = map(lon, lat) # contour data over the map. cs = map.contourf(x, y, Ti, 15) plt.title('Contours of T') plt.show()
One way to do this is to set facecolors by mapping your heat data through the colormap. Here's an example: from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import numpy as np from matplotlib import cm fig = plt.figure() ax = fig.add_subplot(111, projection='3d') u = np.linspace(0, 2 * np.pi, 80) v = np.linspace(0, np.pi, 80) # create the sphere surface x=10 * np.outer(np.cos(u), np.sin(v)) y=10 * np.outer(np.sin(u), np.sin(v)) z=10 * np.outer(np.ones(np.size(u)), np.cos(v)) # simulate heat pattern (striped) myheatmap = np.abs(np.sin(y)) ax.plot_surface(x, y, z, cstride=1, rstride=1, facecolors=cm.hot(myheatmap)) plt.show() Here, my "heatmap" is just stripes along the y-axis, which I made using the function np.abs(np.sin(y)), but anything that goes form 0 to 1 will work (and, of course, it needs to match the shapes on x, etc.