首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >代码实战 | 使用skyborn计算并可视化 WRF 的 DCAPE

代码实战 | 使用skyborn计算并可视化 WRF 的 DCAPE

作者头像
用户11172986
发布2026-06-24 11:55:18
发布2026-06-24 11:55:18
900
举报
文章被收录于专栏:气python风雨气python风雨

代码实战 | 使用skyborn计算并可视化 WRF 的 DCAPE

前言

老实说dcape这个函数之前就是为了计算wrfout设计的,如果用metpy的一维计算可以算到天荒地老

起初是在wrf论坛看到有人问dcape用python怎么算,后面顺手写了就合并到skyborn里了

朋友,如果你看到了dcape函数记得点个赞

废话不多说,我们开始吧

本教程演示如何:

  1. 使用 wrf-python 读取 WRF 输出文件(wrfout)。
  2. 提取气压(hPa)、温度(°C)和露点温度(°C)。
  3. 调用 SKYBorncalculate_dcape 函数计算下沉对流有效位能(DCAPE)。
  4. 使用 Cartopy + Matplotlib 绘制空间分布图。

API 说明

代码语言:javascript
复制
skyborn.calc.calculate_dcape(

pressure, # hPa, 1D(level,) 或 3D(level, lat, lon) temperature, # °C, 与 pressure 同形状 dewpoint, # °C, 与 pressure 同形状 )

返回:1D 输入 → float (J/kg);3D 输入 → 2D ndarray / xr.DataArray

代码语言:javascript
复制
!pip install skyborn -i https://pypi.mirrors.ustc.edu.cn/simple/
代码语言:javascript
复制
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

1. 导入依赖

代码语言:javascript
复制
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

2. 打开 WRF 输出文件

代码语言:javascript
复制
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], "...")
代码语言:javascript
复制
文件已打开,变量: ['Times', 'XLAT', 'XLONG', 'LU_INDEX', 'ZNU', 'ZNW', 'ZS', 'DZS', 'VAR_SSO', 'BATHYMETRY_FLAG'] ...

3. 提取三维气象场

SKYBorn 的 calculate_dcape 需要三个输入:

  • pressure:气压,单位 hPa
  • temperature:温度,单位 °C
  • dewpoint:露点温度,单位 °C

在 wrf-python 中:

  • getvar(nc, "pressure") 返回 hPa
  • getvar(nc, "tc") 返回 °C(temp/tk 返回 K,不要直接用)
  • getvar(nc, "td") 返回 °C
代码语言:javascript
复制
# 读取第一个时次(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")
代码语言:javascript
复制
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

3.1 示例:单点探空剖面(1D)

先取网格中心点的一根垂直廓线,验证函数在 1D 输入下的行为。

代码语言:javascript
复制
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")
代码语言:javascript
复制
单点 (j=218, i=223) 的 DCAPE = 201.2 J/kg
单点 (j=218, i=223) 的 DCAPE = 202.0 joule / kilogram J/kg

可见单点验证下我们的计算结果与metpy的结果是较为接近的,下面开始批量计算

4. 计算空间 DCAPE 场(3D)

本文件网格为 (695, 1011) ,可能需要稍等一下

代码语言:javascript
复制
# 计算 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")
代码语言:javascript
复制
DCAPE 形状: (437, 447)
DCAPE 范围:0.0 ~ 1429.7 J/kg

4.1 获取经纬度

代码语言:javascript
复制
lats = getvar(nc, "XLAT", timeidx=0)
lons = getvar(nc, "XLONG", timeidx=0)

5. 可视化 DCAPE 空间分布

代码语言:javascript
复制
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

output

6. 保存结果为 NetCDF(可选)

代码语言:javascript
复制
output_nc = "wrf_dcape_output.nc"
dcape.to_dataset(name="DCAPE").to_netcdf(output_nc)
print(f"已保存:{output_nc}")
代码语言:javascript
复制
已保存:wrf_dcape_output.nc

小结

如果以上教程对你有帮助请多多点赞收藏分享支持一下

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-06-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 气python风雨 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 代码实战 | 使用skyborn计算并可视化 WRF 的 DCAPE
    • 前言
  • 返回:1D 输入 → float (J/kg);3D 输入 → 2D ndarray / xr.DataArray
    • 1. 导入依赖
    • 2. 打开 WRF 输出文件
    • 3. 提取三维气象场
      • 3.1 示例:单点探空剖面(1D)
    • 4. 计算空间 DCAPE 场(3D)
      • 4.1 获取经纬度
    • 5. 可视化 DCAPE 空间分布
    • 6. 保存结果为 NetCDF(可选)
    • 小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档