matplotlib 定心等值线图制图

8mmmxcuj  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(84)

我正试图把我的地块集中在太平洋上。

from netCDF4 import Dataset 
import numpy as np
import matplotlib.pyplot as plt
import cartopy, cartopy.crs as ccrs

url = 'https://www.star.nesdis.noaa.gov/pub/sod/mecb/crw/data/5km/v3.1_op/nc/v1.0/daily/ssta/2023/ct5km_ssta_v3.1_20230101.nc#mode=bytes'
file = Dataset(url)
data = file.variables['sea_surface_temperature_anomaly'][:][0]
lat = file.variables['lat'][:]
lon = file.variables['lon'][:]
xi, yi = np.meshgrid(lon, lat)
limites =[-180, 180, -90, 90]

fig = plt.figure(figsize=(12,9))
ax = plt.axes(projection=ccrs.PlateCarree())
ax.coastlines(resolution='10m', color='black')
ax.add_feature(cartopy.feature.BORDERS, edgecolor='black')
ax.set_extent(limites, crs=ccrs.PlateCarree())
cf = plt.contourf(xi, yi, data, 
                  extent=limites, 
                  origin='upper'
                  )

字符串
这就是结果:

的数据
我尝试使用ccrs.PlateCarree(),但发生了以下情况:

ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180))



我期待的情节是这样的...


3npbholx

3npbholx1#

通过使用不同的中心经度更改Map投影,可以更改坐标的含义(物理位置)。当中心经度为lon=0°时,该坐标位于Greenwhich子午线,而当中心经度为180°时,相同的值(lon=0°)位于国际日期变更线。
当然,这样修改Map投影是可以的,但是你还必须修改你提供的数据的坐标(它仍然具有中心经度=0的定义)。或者当使用Matplotlib/Cartopy时,提供正确的转换需要在运行中完成(使用transform=...)。
如果你特别需要Matplotlib的contourf,它需要单调递增的坐标,在这种特定情况下最简单的方法可能是修改数据数组,将其滚动一半宽度,如:

data = np.roll(data, lon.size//2, axis=1)

字符串
上面的方法有点棘手,但在这种情况下有效,因为两个投影之间的差异只是沿着水平轴的偏移。
请注意,同时使用xiyiextent=是多余的,它可以是其中一个。当像这样提供x/y坐标时,它们可以保持1D(不需要手动使用np.meshgrid)。所以我会直接传递lon/lat数组。
举例来说:

map_proj = ccrs.PlateCarree(central_longitude=180)

fig, ax = plt.subplots(
    figsize=(10, 5), layout="compressed", facecolor="w", dpi=100,
    subplot_kw=dict(projection=map_proj),
)

ax.coastlines(resolution='110m', color='k', lw=.5, alpha=.5)
ax.add_feature(cartopy.feature.BORDERS, ec='k', lw=.5, alpha=.5)

im = ax.contourf(
    lon, lat, data, origin='upper', cmap="RdBu_r", 
    levels=np.arange(-3,3.1,0.5), extend="both",
    transform=map_proj,
)

cb = fig.colorbar(im, shrink=.5)


结果:x1c 0d1x
如果你不是特别需要contourf,你也可以考虑pcolormesh,它给出了一个非常相似的结果。使用下面的设置,它会产生连续的颜色渐变,但您可以为类似的离散颜色提供BoundaryNorm,作为contourf方法。
pcolormesh方法可以使用原始数据(没有np.roll),只要您还提供原始投影,Cartopy将正确处理动态转换。
使用pcolormesh在输入数据方面更加灵活,例如,它不需要假设规则的网格。所以在这种情况下,它也可以用于调试。这种灵活性确实需要更复杂的插值,因此在像这样的大型网格上会有明显的性能损失。

map_proj = ccrs.PlateCarree(central_longitude=180)

fig, ax = plt.subplots(
    figsize=(10, 5), layout="compressed", facecolor="w", dpi=100,
    subplot_kw=dict(projection=map_proj),
)

ax.coastlines(resolution='110m', color='k', lw=.5, alpha=.5)
ax.add_feature(cartopy.feature.BORDERS, ec='k', lw=.5, alpha=.5)

im = ax.pcolormesh(

    lon, lat, data, transform=ccrs.PlateCarree(), 
    vmin=-3, vmax=3, cmap="RdBu_r",
)
cb = fig.colorbar(im, shrink=.5, extend="both")



最后一个示例现在可以例如通过将Map投影改变为例如来快速改变为使用等面积投影:

map_proj = ccrs.EqualEarth(central_longitude=180)



最后一个例子的动态重投影会更慢,但它非常简单/方便。通过使用gdalwarp之类的东西预先进行重投影,可能会获得更好的性能。与最终图像相比,数据可能具有更高的分辨率(7200 x3600),在使用Matplotlib绘制之前减小尺寸也会加快速度。

相关问题