【问题标题】:Handling cyclic data with matplotlib contour/contourf使用 matplotlib 轮廓/轮廓处理循环数据
【发布时间】:2015-05-07 04:56:02
【问题描述】:

我正在尝试创建风向的等高线/等高线图 - 问题是 0/360 度不连续性对这两个功能造成严重破坏 - 试图插入间隙并用 all 中间值(见下文)。我尝试了各种插值/移位的想法,但没有任何结果。有没有人知道如何解决这个问题?

最小工作代码示例:

levels=np.array([1000.,975.,950.,925.,900.,875.,850.,825.,800.,775.,750.,700.,650.,600.,
550.,500.,450.,400.,350.,300.,250.,225.,200.,175.,150.])
arr = np.load("arr.npy")

fig = plt.figure(figsize=(6,10))
ax = plt.subplot(111)
clevs = np.arange(-360.,360.,45.)
clevs1 = np.linspace(np.min(arr),np.max(arr),100.)

cs = plt.contour(lons,levels,arr,clevs,colors = 'k')
for c in cs.collections: c.set_linestyle('solid')
ax.set_xlabel("Longitude")
ax.set_ylabel("Pressure Level (hPa)")
ax.set_yscale("log")
plt.gca().invert_yaxis()
ax.set_yticks(levels[::2])
ax.set_yticklabels(levels[::2].astype(int))
cs1 = plt.contourf(lons,levels,arr,clevs1,cmap=plt.cm.hsv)
divider = make_axes_locatable(plt.gca())
cax = divider.append_axes("bottom", "4%", pad="8.5%")
cbar = plt.colorbar(cs1, orientation="horizontal", cax = cax)
cbar.set_ticks(clevs[::1])
cbar.set_label(r"Wind Heading")

plt.clabel(cs, inline = 1, fontsize = 18, fmt = '%1.f', manual = True)
plt.tight_layout()
plt.show()

数据here

【问题讨论】:

    标签: python numpy matplotlib contour


    【解决方案1】:

    想象一下你可能如何插入这样一个数据集:你不可能从略低于 360° 的角度连续移动到 0°,除非你展开这些值(参见 np.unwrap)接近 0° 的值将被重新解释为相同的值 +360°。但是然后你再次增加 all 轮廓,你最终会达到接近 2x360° 的轮廓水平,然后是另一个边缘。

    对于您的数据集的性质,它是物理的并且与风向相关,这绝对不是您想要的,因为您最终会一直处于无限循环中,为轮廓添加跳跃。那是因为轮廓并不真正适合这种数据

    不,出于这个原因,有 wind barbs 和颤抖图,例如这个,基于您的数据集:

    生成该图片的代码很简单:

    x = np.load('arr.npy')
    z = x/180*np.pi
    u = np.cos(z)
    v = np.sin(z)
    plt.imshow(z, cmap='hot')
    plt.quiver(u,v)
    

    在我自己的研究中,我什至对箭头本身都不感兴趣,因为在我的工作中 180° 与 0° 相同,所以我只画棍子,没有倒钩,没有头。

    我知道这在技术上不是您希望的答案,但轮廓不适合这个。如果您真的想要“轮廓”,您可以将数据集拆分为区域(例如0 <= angle <20 等),然后为每个区域仅绘制具有中途角度的箭头(因此每个域,都有几个箭头指向例如 10° 方向),但这样你会丢失定量数据。 另一种方法是仅对上述每个域进行着色,并在其中添加文本标签以指示其值。这样一来,您就不会在 360-0 边界的边缘看到一系列紧密排列的等高线。

    【讨论】:

      【解决方案2】:

      我知道的唯一解决方案是将您的数据分成两部分,移位,分别打开它们并在绘图时再次组合它们:

      import matplotlib.pyplot as plt
      import numpy as np
      
      phase_1d      = np.arange(0,360,10)
      phase_levels  = np.arange(0.,360.,30.)
      
      phase_2d,yy   = np.meshgrid([phase_1d,phase_1d],[phase_1d,phase_1d])
      
      phase_2d_uw   = np.unwrap(np.deg2rad(phase_2d)-np.pi)
      phase_2d_uw_1 = np.rad2deg(phase_2d_uw+np.pi)
      phase_2d_uw_2 = np.rad2deg(phase_2d_uw-np.pi)
      #
      #-----------------------------------------------------------
      #
      plt.subplot(1,3,1)
      plt.imshow(phase_2d,vmin=0,vmax=360)
      
      plt.subplot(1,3,2)
      plt.imshow(phase_2d_uw_1,vmin=0,vmax=360)
      
      plt.subplot(1,3,3)
      plt.imshow(phase_2d_uw_2,vmin=0,vmax=360)
      
      plt.show()
      #
      #-----------------------------------------------------------
      #
      plt.subplot(1,2,1)
      cl1=plt.contour(phase_2d,levels=phase_levels,colors='black',linestyles='dashed')
      plt.clabel(cl1,fmt='%.0f',inline='True')
      
      plt.subplot(1,2,2)
      cl2=plt.contour(phase_2d_uw_1,levels=phase_levels,colors='black',linestyles='dashed')
      plt.clabel(cl2,fmt='%.0f',inline='True')
      
      plt.subplot(1,2,2)
      cl2=plt.contour(phase_2d_uw_2,levels=phase_levels,colors='black',linestyles='dashed')
      plt.clabel(cl2,fmt='%.0f',inline='True')
      plt.show()        
      

      【讨论】:

        【解决方案3】:

        我知道回答太晚了,但我一直在为这个问题苦苦挣扎,没有回答。

        只需取角度的 sin()、cos() 值并计算该值的颜色

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-24
          • 1970-01-01
          • 2014-11-20
          • 1970-01-01
          相关资源
          最近更新 更多