【问题标题】:Plotting the temperature distribution on a sphere with python用python绘制球体上的温度分布
【发布时间】:2014-03-02 14:34:37
【问题描述】:

我有以下问题:

a 在由数组 x 指定的球面上有 N 个点,其中 x.shape=(N,3)。该数组包含它们的笛卡尔坐标。此外,在每一点,我都有一个指定的温度。此数量保存在数组 T 中,其中 T.shape=(N,)。

是否有任何直接的方法可以将此温度分布映射到使用不同颜色的平面中?

如果它简化了任务,位置也可以用极坐标(\theta,\phi)给出。

【问题讨论】:

    标签: python matplotlib plot


    【解决方案1】:

    要绘制数据,您可以使用 Basemap。唯一的问题是,contourcontourf 例程都需要网格数据。这是在球体上进行天真(和缓慢)类似 IDW 的插值的示例。欢迎任何cmets。

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

    【讨论】:

      【解决方案2】:

      一种方法是设置facecolors,通过颜色图映射您的热量数据。

      这是一个例子:

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

      在这里,我的“热图”只是沿 y 轴的条纹,这是我使用函数 np.abs(np.sin(y)) 制作的,但是从 0 到 1 的任何东西都可以工作(当然,它需要匹配形状在x等上

      【讨论】:

      • 我怎么能在这里使用我自己的数据
      • @pulp_fiction:最好单独提出一个问题。在我的回答的最后,我概述了如何使用您自己的数据,所以由于这对您没有帮助,我们需要了解您的数据,这将很难通过厘米。
      猜你喜欢
      • 2015-08-01
      • 2018-01-25
      • 2019-04-04
      • 1970-01-01
      • 2013-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多