繁体   English   中英

使用 Cartopy 从数据中屏蔽海洋或陆地

[英]Mask Ocean or Land from data using Cartopy

我想从全球海面温度数据中掩盖陆地区域。 我正在使用 Cartopy 来 plot 数据。

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

f = Dataset('sst.mnmean.nc')
sst = f.variables['sst'][0,:,:]
lats = f.variables['lat'][:]
lons = f.variables['lon'][:]

ax = plt.axes(projection=ccrs.PlateCarree())
ax.coastlines()
plot = ax.contourf(lons, lats, sst, 60, transform=ccrs.PlateCarree())
cb = plt.colorbar(plot)
plt.show()

上面的代码绘制这样的数据:
在此处输入图像描述

我想以此掩盖土地。

我浏览了cartopy文档,并遇到了名为add_feature的方法。 代码如下:

import numpy as np
import matplotlib.pyplot as plt
import cartopy as cart
from mpl_toolkits.basemap import Basemap
from netCDF4 import Dataset

f = Dataset('sst.mnmean.nc')
sst = f.variables['sst'][0,:,:]
lats = f.variables['lat'][:]
lons = f.variables['lon'][:]

ax = plt.axes(projection=cart.crs.PlateCarree())
ax.coastlines()
ax.add_feature(cart.feature.LAND, zorder=100, edgecolor='k')
ax.set_global()
plot = ax.contourf(lons, lats, sst, 60, transform=cart.crs.PlateCarree())
cb = plt.colorbar(plot)
plt.show()

现在情节看起来像这样 要遮盖海洋, cart.feature.LAND cart.feature.OCEAN更改为cart.feature.OCEAN

为了掩盖陆地区域,使用底图会更容易。

from mpl_toolkits.basemap import Basemap
map = Basemap(projection='mill',lon_0=180) # create projection
....                                       # whatever processing needed
map.fillcontinents(color='coral')          # mask land mass

参见底图示例

公认的解决方案并没有真正掩盖数据,plot 只是通过覆盖 map 部分覆盖。 虽然这很好地解决了给定的问题,但有时需要一个实际的掩码来删除数据中不需要的部分。 可以基于用于陆地或海洋的光栅化 map轻松创建这样的蒙版。

使用下面的代码,创建了一个临时图形,其分辨率对应于给定的数据。 绘制土地 map 后,使用tostring_rgb()获得 map 的光栅化图像 该图像类似于二值图像,然后可以直接用于为数据创建掩码

这种解决方案的优点是它可以应用于更一般的问题,例如分别在陆地和海洋上绘制两个不同的数据集。 在绘制类似图像的数据时,好处会有所提高,因为通过考虑光栅化蒙版的颜色梯度,可以使用透明度来实现平滑的边缘。 这可以通过PIL.Image.fromarray(mask)然后convert('L')并最后在给定图像上应用putalpha(mask)轻松完成。

import matplotlib.pyplot as plt
import numpy as np
import cartopy
import netCDF4

# load data
data = netCDF4.Dataset('sst.mnmean.nc')
sst  = data.variables['sst'][0,:,:]
lats = data.variables['lat'][:]
lons = data.variables['lon'][:]

# prepare temporary plot and create mask from rasterized map
proj = {'projection': cartopy.crs.PlateCarree()}
fig, ax = plt.subplots(figsize=(len(lons)/100, len(lats)/100), dpi=100, subplot_kw=proj)
fig.subplots_adjust(left=0.0, bottom=0.0, right=1.0, top=1.0)
ax.set_frame_on(False)

ax.add_feature(cartopy.feature.LAND, facecolor='black')
fig.canvas.draw()
mask = fig.canvas.tostring_rgb()
ncols, nrows = fig.canvas.get_width_height()
plt.close(fig)

mask = np.frombuffer(mask, dtype=np.uint8).reshape(nrows, ncols, 3)
mask = mask.mean(axis=2)
sst  = np.where(mask>0, sst, np.nan)

# create actual plot
fig, ax = plt.subplots(subplot_kw=proj)
ax.contourf(lons, lats, sst, 60, transform=cartopy.crs.PlateCarree(central_longitude=180))
ax.coastlines()
plt.show()

结果图

暂无
暂无

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

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