簡體   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