热图半球图

时间:2016-12-12 16:57:27

标签: python matplotlib 3d heatmap mplot3d

我想将720 x 180的theta和phi值绘制成 θ范围=(-180到180,步长为0.5) phi range =(0到-90,步长为0.5)

这是我拥有的数据集示例:

Theta Phi Values
-180   0    0.2
-180   0.5  0.5
...    ...  ...
-180   -90  1.1
-179.5  0   0.92
...    ...  ...
 0     -90   0.6
...    ...  ...
180   -89.5 0.17
180   -90   0.12

所以最终,我想得到一个类似这样的情节:

Heat map plot[1] 我知道如何使用下面的代码创建半球,但是如何从我的数据框中分配值?

import matplotlib.pyplot as plt
from matplotlib import cm, colors
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

# Create a sphere
r = 2
pi = np.pi
cos = np.cos
sin = np.sin
altitude
phi, theta = np.mgrid[0.0:0.5*pi:180j, 0.0:2.0*pi:720j] # phi = alti, theta = azi
x = r*sin(phi)*cos(theta)
y = r*sin(phi)*sin(theta)
z = r*cos(phi)    
#Set colours and render
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(
    x, y, z,  rstride=4, cstride=4, color='w', alpha=0.1, linewidth=0)    
ax.set_xlim([-2.2,2.2])
ax.set_ylim([-2.2,2.2])
ax.set_zlim([0,3])
ax.set_aspect("equal")
ax.plot_wireframe(x, y, z, color="k")

代码生成这个

enter image description here

1 个答案:

答案 0 :(得分:3)

Axes3D.plot_surface接受2D数组作为输入。它提供facecolors参数,该参数接受与输入数组形状相同的数组。这个数组应该将每个面的颜色作为rgba元组。因此,可以将数组值标准化为最大1的范围,并为其提供matplotlib.cm的色彩映射。

剩下的问题是从提供的3列列表中获取此数组。给定长度为n*m的数据表,其中第一列表示x值,第二列表示y值,第三列表示值,以及排序首先由x表示的位置按y。然后,可以使用(n,m)将最后一列重新整形为n数组,其中xm值和.reshape((m,n)).T y值的数量。< / p>

进一步评论:

  1. 在下面的解决方案中,我需要模仿这个数组并直接使用辐射角度而不是度数。
  2. 点数,180 * 720似乎有点高。为了让窗口不花时间旋转,我减少了这个数字。
  3. 我重新命名角度,使它们与通常的教科书定义匹配,phi =方位角,θ=倾角(从z轴)。
  4. 使用plot_wireframe可能没有多大意义,因为它会隐藏下面的表面。如果需要线框,可以使用要绘制的点数和linewidth关键字参数。将linewidth设置为大的,如3或5,使表面看起来不错,将其设置为1会留下一些线框外观。
  5. 这是完整的解决方案。

    import matplotlib.pyplot as plt
    from matplotlib import cm
    from mpl_toolkits.mplot3d import Axes3D
    import numpy as np
    
    #theta inclination angle
    #phi azimuthal angle
    n_theta = 50 # number of values for theta
    n_phi = 200  # number of values for phi
    r = 2        #radius of sphere
    
    theta, phi = np.mgrid[0.0:0.5*np.pi:n_theta*1j, 0.0:2.0*np.pi:n_phi*1j]
    
    x = r*np.sin(theta)*np.cos(phi)
    y = r*np.sin(theta)*np.sin(phi)
    z = r*np.cos(theta)
    
    # mimic the input array
    # array columns phi, theta, value
    # first n_theta entries: phi=0, second n_theta entries: phi=0.0315..
    inp = []
    for j in phi[0,:]:
        for i in theta[:,0]:
            val = 0.7+np.cos(j)*np.sin(i+np.pi/4.)# put something useful here
            inp.append([j, i, val])
    inp = np.array(inp)
    print inp.shape
    print inp[49:60, :]
    
    #reshape the input array to the shape of the x,y,z arrays. 
    c = inp[:,2].reshape((n_phi,n_theta)).T
    print z.shape
    print c.shape
    
    
    #Set colours and render
    fig = plt.figure(figsize=(10, 8))
    ax = fig.add_subplot(111, projection='3d')
    #use facecolors argument, provide array of same shape as z
    # cm.<cmapname>() allows to get rgba color from array.
    # array must be normalized between 0 and 1
    ax.plot_surface(
        x,y,z,  rstride=1, cstride=1, facecolors=cm.hot(c/c.max()), alpha=0.9, linewidth=1) 
    ax.set_xlim([-2.2,2.2])
    ax.set_ylim([-2.2,2.2])
    ax.set_zlim([0,4.4])
    ax.set_aspect("equal")
    #ax.plot_wireframe(x, y, z, color="k") #not needed?!
    plt.savefig(__file__+".png")
    plt.show()
    

    enter image description here