老实说dcape这个函数之前就是为了计算wrfout设计的,如果用metpy的一维计算可以算到天荒地老
起初是在wrf论坛看到有人问dcape用python怎么算,后面顺手写了就合并到skyborn里了

朋友,如果你看到了dcape函数记得点个赞
废话不多说,我们开始吧
本教程演示如何:
wrfout)。calculate_dcape 函数计算下沉对流有效位能(DCAPE)。API 说明
skyborn.calc.calculate_dcape(
pressure, # hPa, 1D(level,) 或 3D(level, lat, lon) temperature, # °C, 与 pressure 同形状 dewpoint, # °C, 与 pressure 同形状 )
!pip install skyborn -i https://pypi.mirrors.ustc.edu.cn/simple/
Looking in indexes: https://pypi.mirrors.ustc.edu.cn/simple/
Collecting skyborn
Downloading https://mirrors.ustc.edu.cn/pypi/packages/0b/9e/653b69973e8593c7f21bdd18bacca1b7796702c205711b843c1381b69ad6/skyborn-0.4.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (2.7 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.7/2.7 MB 17.9 MB/s eta 0:00:00a 0:00:01
[?25hRequirement already satisfied: numpy in /opt/conda/lib/python3.11/site-packages (from skyborn) (1.26.4)
Requirement already satisfied: pandas in /opt/conda/lib/python3.11/site-packages (from skyborn) (2.2.3)
Requirement already satisfied: xarray in /opt/conda/lib/python3.11/site-packages (from skyborn) (2024.3.0)
Requirement already satisfied: matplotlib in /opt/conda/lib/python3.11/site-packages (from skyborn) (3.9.1)
Requirement already satisfied: netCDF4 in /opt/conda/lib/python3.11/site-packages (from skyborn) (1.6.3)
Requirement already satisfied: metpy in /opt/conda/lib/python3.11/site-packages (from skyborn) (1.6.3)
Requirement already satisfied: tqdm in /opt/conda/lib/python3.11/site-packages (from skyborn) (4.67.0)
Requirement already satisfied: statsmodels in /opt/conda/lib/python3.11/site-packages (from skyborn) (0.14.4)
Requirement already satisfied: scipy in /opt/conda/lib/python3.11/site-packages (from skyborn) (1.14.1)
Requirement already satisfied: scikit-learn in /opt/conda/lib/python3.11/site-packages (from skyborn) (1.6.0)
Requirement already satisfied: dask in /opt/conda/lib/python3.11/site-packages (from skyborn) (2024.8.1)
Requirement already satisfied: click>=8.1 in /opt/conda/lib/python3.11/site-packages (from dask->skyborn) (8.1.7)
Requirement already satisfied: cloudpickle>=3.0.0 in /opt/conda/lib/python3.11/site-packages (from dask->skyborn) (3.1.0)
Requirement already satisfied: fsspec>=2021.09.0 in /opt/conda/lib/python3.11/site-packages (from dask->skyborn) (2025.2.0)
Requirement already satisfied: packaging>=20.0 in /opt/conda/lib/python3.11/site-packages (from dask->skyborn) (24.1)
Requirement already satisfied: partd>=1.4.0 in /opt/conda/lib/python3.11/site-packages (from dask->skyborn) (1.4.2)
Requirement already satisfied: pyyaml>=5.3.1 in /opt/conda/lib/python3.11/site-packages (from dask->skyborn) (6.0.2)
Requirement already satisfied: toolz>=0.10.0 in /opt/conda/lib/python3.11/site-packages (from dask->skyborn) (1.0.0)
Requirement already satisfied: importlib-metadata>=4.13.0 in /opt/conda/lib/python3.11/site-packages (from dask->skyborn) (8.5.0)
Requirement already satisfied: contourpy>=1.0.1 in /opt/conda/lib/python3.11/site-packages (from matplotlib->skyborn) (1.3.1)
Requirement already satisfied: cycler>=0.10 in /opt/conda/lib/python3.11/site-packages (from matplotlib->skyborn) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in /opt/conda/lib/python3.11/site-packages (from matplotlib->skyborn) (4.55.3)
Requirement already satisfied: kiwisolver>=1.3.1 in /opt/conda/lib/python3.11/site-packages (from matplotlib->skyborn) (1.4.7)
Requirement already satisfied: pillow>=8 in /opt/conda/lib/python3.11/site-packages (from matplotlib->skyborn) (9.4.0)
Requirement already satisfied: pyparsing>=2.3.1 in /opt/conda/lib/python3.11/site-packages (from matplotlib->skyborn) (3.2.0)
Requirement already satisfied: python-dateutil>=2.7 in /opt/conda/lib/python3.11/site-packages (from matplotlib->skyborn) (2.9.0.post0)
Requirement already satisfied: pint>=0.17 in /opt/conda/lib/python3.11/site-packages (from metpy->skyborn) (0.24.4)
Requirement already satisfied: pooch>=1.2.0 in /opt/conda/lib/python3.11/site-packages (from metpy->skyborn) (1.8.2)
Requirement already satisfied: pyproj>=3.0.0 in /opt/conda/lib/python3.11/site-packages (from metpy->skyborn) (3.5.0)
Requirement already satisfied: traitlets>=5.0.5 in /opt/conda/lib/python3.11/site-packages (from metpy->skyborn) (5.14.3)
Requirement already satisfied: pytz>=2020.1 in /opt/conda/lib/python3.11/site-packages (from pandas->skyborn) (2024.1)
Requirement already satisfied: tzdata>=2022.7 in /opt/conda/lib/python3.11/site-packages (from pandas->skyborn) (2024.2)
Requirement already satisfied: cftime in /opt/conda/lib/python3.11/site-packages (from netCDF4->skyborn) (1.6.4)
Requirement already satisfied: joblib>=1.2.0 in /opt/conda/lib/python3.11/site-packages (from scikit-learn->skyborn) (1.4.2)
Requirement already satisfied: threadpoolctl>=3.1.0 in /opt/conda/lib/python3.11/site-packages (from scikit-learn->skyborn) (3.5.0)
Requirement already satisfied: patsy>=0.5.6 in /opt/conda/lib/python3.11/site-packages (from statsmodels->skyborn) (1.0.1)
Requirement already satisfied: zipp>=3.20 in /opt/conda/lib/python3.11/site-packages (from importlib-metadata>=4.13.0->dask->skyborn) (3.21.0)
Requirement already satisfied: locket in /opt/conda/lib/python3.11/site-packages (from partd>=1.4.0->dask->skyborn) (1.0.0)
Requirement already satisfied: platformdirs>=2.1.0 in /opt/conda/lib/python3.11/site-packages (from pint>=0.17->metpy->skyborn) (4.3.6)
Requirement already satisfied: typing_extensions>=4.0.0 in /opt/conda/lib/python3.11/site-packages (from pint>=0.17->metpy->skyborn) (4.12.2)
Requirement already satisfied: flexcache>=0.3 in /opt/conda/lib/python3.11/site-packages (from pint>=0.17->metpy->skyborn) (0.3)
Requirement already satisfied: flexparser>=0.4 in /opt/conda/lib/python3.11/site-packages (from pint>=0.17->metpy->skyborn) (0.4)
Requirement already satisfied: requests>=2.19.0 in /opt/conda/lib/python3.11/site-packages (from pooch>=1.2.0->metpy->skyborn) (2.32.3)
Requirement already satisfied: certifi in /opt/conda/lib/python3.11/site-packages (from pyproj>=3.0.0->metpy->skyborn) (2024.12.14)
Requirement already satisfied: six>=1.5 in /opt/conda/lib/python3.11/site-packages (from python-dateutil>=2.7->matplotlib->skyborn) (1.17.0)
Requirement already satisfied: charset-normalizer<4,>=2 in /opt/conda/lib/python3.11/site-packages (from requests>=2.19.0->pooch>=1.2.0->metpy->skyborn) (3.4.0)
Requirement already satisfied: idna<4,>=2.5 in /opt/conda/lib/python3.11/site-packages (from requests>=2.19.0->pooch>=1.2.0->metpy->skyborn) (3.10)
Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/conda/lib/python3.11/site-packages (from requests>=2.19.0->pooch>=1.2.0->metpy->skyborn) (2.2.3)
Installing collected packages: skyborn
Successfully installed skyborn-0.4.1
import os
import numpy as np
import xarray as xr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from netCDF4 import Dataset
from wrf import getvar, to_np
from skyborn.calc import calculate_dcape
wrf_file = "/home/mw/input/typhoon9537/wrfout_d01_2019-08-08_21_00_00"
if not os.path.exists(wrf_file):
raise FileNotFoundError(f"未找到文件:{wrf_file}")
nc = Dataset(wrf_file)
print("文件已打开,变量:", list(nc.variables.keys())[:10], "...")
文件已打开,变量: ['Times', 'XLAT', 'XLONG', 'LU_INDEX', 'ZNU', 'ZNW', 'ZS', 'DZS', 'VAR_SSO', 'BATHYMETRY_FLAG'] ...
SKYBorn 的 calculate_dcape 需要三个输入:
pressure:气压,单位 hPatemperature:温度,单位 °Cdewpoint:露点温度,单位 °C在 wrf-python 中:
getvar(nc, "pressure") 返回 hPagetvar(nc, "tc") 返回 °C(temp/tk 返回 K,不要直接用)getvar(nc, "td") 返回 °C# 读取第一个时次(timeidx=0)
p_hpa = getvar(nc, "pressure", timeidx=0) # (bottom_top, south_north, west_east),单位 hPa
t_c = getvar(nc, "tc", timeidx=0) # 温度,单位 °C
td_c = getvar(nc, "td", timeidx=0) # 露点温度,单位 °C
print("p_hpa:", p_hpa.shape, "range", float(p_hpa.min()), "~", float(p_hpa.max()), "hPa")
print("t_c :", t_c.shape, "range", float(t_c.min()), "~", float(t_c.max()), "°C")
print("td_c :", td_c.shape, "range", float(td_c.min()), "~", float(td_c.max()), "°C")
p_hpa: (34, 437, 447) range 56.15993881225586 ~ 1005.2364501953125 hPa
t_c : (34, 437, 447) range -86.68009948730469 ~ 31.644989013671875 °C
td_c : (34, 437, 447) range -80.44786071777344 ~ 28.186927795410156 °C
先取网格中心点的一根垂直廓线,验证函数在 1D 输入下的行为。
from metpy.calc import downdraft_cape
nj, ni = p_hpa.shape[1], p_hpa.shape[2]
j0, i0 = nj // 2, ni // 2
p_profile = p_hpa[:, j0, i0]
t_profile = t_c[:, j0, i0]
td_profile = td_c[:, j0, i0]
dcape_profile = calculate_dcape(
to_np(p_profile),
to_np(t_profile),
to_np(td_profile)
)
print(f"单点 (j={j0}, i={i0}) 的 DCAPE = {dcape_profile:.1f} J/kg")
dc, _, _= downdraft_cape(p_profile, t_profile,td_profile)
print(f"单点 (j={j0}, i={i0}) 的 DCAPE = {dc:.1f} J/kg")
单点 (j=218, i=223) 的 DCAPE = 201.2 J/kg
单点 (j=218, i=223) 的 DCAPE = 202.0 joule / kilogram J/kg
可见单点验证下我们的计算结果与metpy的结果是较为接近的,下面开始批量计算
本文件网格为 (695, 1011) ,可能需要稍等一下
# 计算 DCAPE
dcape = calculate_dcape(p_hpa, t_c, td_c)
print("DCAPE 形状:", dcape.shape)
print(f"DCAPE 范围:{np.nanmin(dcape):.1f} ~ {np.nanmax(dcape):.1f} J/kg")
DCAPE 形状: (437, 447)
DCAPE 范围:0.0 ~ 1429.7 J/kg
lats = getvar(nc, "XLAT", timeidx=0)
lons = getvar(nc, "XLONG", timeidx=0)
fig, ax = plt.subplots(
1, 1, figsize=(12, 8),
subplot_kw={"projection": ccrs.PlateCarree()}
)
# 绘制填色图
cf = ax.pcolormesh(
lons, lats, dcape,
transform=ccrs.PlateCarree(),
cmap="YlOrRd",
shading="auto"
)
# 添加地图要素
ax.coastlines(resolution="10m", linewidth=0.8)
ax.add_feature(cfeature.BORDERS, linestyle=":")
ax.add_feature(cfeature.LAKES, alpha=0.5)
ax.add_feature(cfeature.RIVERS, alpha=0.5)
gl = ax.gridlines(draw_labels=True, linewidth=0.5, color="gray", alpha=0.5, linestyle="--")
gl.top_labels = False
gl.right_labels = False
# 色标
cbar = plt.colorbar(cf, ax=ax, shrink=0.8, pad=0.02)
cbar.set_label("DCAPE (J kg$^{-1}$)")
ax.set_title("WRF DCAPE (SKYBorn)\n2024-09-13 21:00 UTC")
plt.tight_layout()
plt.show()

output
output_nc = "wrf_dcape_output.nc"
dcape.to_dataset(name="DCAPE").to_netcdf(output_nc)
print(f"已保存:{output_nc}")
已保存:wrf_dcape_output.nc
如果以上教程对你有帮助请多多点赞收藏分享支持一下