简体   繁体   English

使用 matplotlib 轮廓/轮廓处理循环数据

[英]Handling cyclic data with matplotlib contour/contourf

I'm trying to create a contour/contourf plot of wind heading - the problem being that the 0/360deg discontinuity is playing havoc with both functions - trying to interpolate the gap and fill it with all the intervening values (see below).我正在尝试创建风航向的轮廓/轮廓图 - 问题是 0/360 度不连续性对这两个功能造成严重破坏 - 试图插入间隙并用所有中间值填充它(见下文)。 I've tried various interpolation/shifting ideas but nothing has come to fruition.我尝试了各种插值/转换想法,但没有任何结果。 Has anyone got any ideas about how to fix this?有没有人对如何解决这个问题有任何想法?

标题结构

A minimal-working-code example:一个最小工作代码示例:

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

Data here .数据在这里

Imagine how you might possibly interpolate such a dataset: there's no way you could continuously move from just below 360° to 0°, unless you'd unwrap those values (see np.unwrap ) such that values close to 0° would be reinterpreted as those same values +360°.想象一下您可能如何插入这样的数据集:您无法从 360° 以下连续移动到 0°,除非您解开这些值(请参阅np.unwrap ),以便将接近 0° 的值重新解释为那些相同的值 +360°。 But then you increase all contours again and you'd end up at contourlevels close to 2x360° and then yet another edge.但是然后您再次增加所有轮廓,最终会达到接近 2x360° 的轮廓级别,然后是另一个边缘。

For the nature of your dataset, which is physical and related to the wind direction, that is definitely not what you would want, because you would end up in an infinite loop of all the time adding that jump for the contours.对于您的数据集的性质,它是物理的并且与风向相关,这绝对不是您想要的,因为您最终会陷入无限循环,一直为轮廓添加跳跃。 That's because contours aren't really suited for this kind of data .那是因为轮廓并不真正适合这种数据

No, for this reason, there are wind barbs and quiver plots, such as this one, based on your dataset:不,出于这个原因,有风倒钩和箭袋图,例如这个,基于您的数据集:

循环轮廓

The code that generated that picture is simple:生成该图片的代码很简单:

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)

In my own research, I'm not even interested in the arrows themselves, because in my line of work 180° is the same as 0°, so I just draw sticks, without barbs, without heads.在我自己的研究中,我什至对箭头本身不感兴趣,因为在我的工作中 180° 与 0° 相同,所以我只画棍子,没有倒钩,没有头。

I know it's technically not the answer you were hoping for, but contours are just not suited for this.我知道这在技术上不是您希望的答案,但轮廓不适合于此。 If you'd really want "contours", you could split up the dataset in regions (eg 0 <= angle <20 and so on) and then either draw for each of those regions only arrows with the angle halfway (so per domain, several arrows all pointing in eg the 10° direction), but this way you'd loose quantitative data.如果您真的想要“轮廓”,则可以将数据集拆分为区域(例如0 <= angle <20等),然后为每个区域仅绘制角度为中间的箭头(因此每个域,几个箭头都指向例如 10° 方向),但这样你会丢失定量数据。 An alternative would be to just color each of the aforementioned domains and add text labels inside them to indicate their value.另一种方法是为上述每个域着色并在其中添加文本标签以指示它们的值。 That way, you wouldn't see a series of closely packed contourlines at the edge of the 360-0 boundary.这样,您就不会在 360-0 边界的边缘看到一系列紧密排列的轮廓线。

The only solution I'm aware of is to split your data into two parts, shift, unwrap them seperately and combine them again while plotting:我知道的唯一解决方案是将您的数据分成两部分,分别移动、展开它们并在绘图时再次组合它们:

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

I know its way too late to answer but i was struggeling too much with this problem for not answering it.我知道它来不及回答,但我因为没有回答这个问题而苦苦挣扎。

Just take the sin(), cos() value of the angle and compute the color for that value只需取角度的 sin(), cos() 值并计算该值的颜色

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM