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). 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°. But then you increase all contours again and you'd end up at contourlevels close to 2x360° and then yet another edge.
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.
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 (e.g. 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 e.g. the 10° direction), but this way you'd loose quantitative data.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With