18、气象学中风场的绘制

前言

数据及代码下载链接➡️:如何绘制自定义颜色的风场图

一、批量读取数据

import os
import xarray as xr

folder_path = "./"
file_pattern = os.path.join(folder_path, "*.nc")

try:
    ds = xr.open_mfdataset(file_pattern)
    u10 = ds["u10"]
    v10 = ds["v10"]
    ds.close()

except Exception as e:
    print(f"读取文件时出现错误:{str(e)}")

二、绘制2022年的平均风场

import xarray as xr
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from matplotlib.offsetbox import AnchoredText
from matplotlib.colors import ListedColormap
import cmaps
import matplotlib.ticker as ticker
from matplotlib.gridspec import GridSpec
from cartopy.mpl.geoaxes import GeoAxes
from mpl_toolkits.axes_grid1 import AxesGrid
import datetime as dt

# 求解纬向风、经向风以及风速的年平均值
u10_ana = u10[1:,:,:].mean(axis=0)
v10_ana = v10[1:,:,:].mean(axis=0)
windspeed_ana = np.sqrt(u10_ana**2+v10_ana**2)
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from matplotlib.gridspec import GridSpec

fig = plt.figure(figsize=(6, 5), dpi=200)
gs = GridSpec(1, 1, figure=fig)
ax = fig.add_subplot(gs[0, 0], projection=ccrs.PlateCarree(central_longitude=180))

leftlon, rightlon, lowerlat, upperlat = (-180, 180, -90, 90)  # 设置全球地图范围
img_extent = [leftlon, rightlon, lowerlat, upperlat]
lon = u10_ana.longitude
lat = u10_ana.latitude

d = ax.quiver(lon[::10], lat[::10], u10_ana[::10, ::10], v10_ana[::10, ::10], windspeed_ana[::10, ::10], color="k",
          )
ax.quiverkey(d, 0.95, 1.1, 5, '5 m/s', labelpos='S', coordinates='axes')
ax.add_feature(cfeature.BORDERS.with_scale('10m'))
ax.add_feature(cfeature.COASTLINE.with_scale('10m'))
ax.set_extent(img_extent, crs=ccrs.PlateCarree())  # 设置地图显示范围为全球

ax.set_xticks([-180, -150, -120, -90, -60, -30, 0, 30, 60, 90, 120, 150, 180], crs=ccrs.PlateCarree())
ax.set_xticklabels(["180°W", "150°W", "120°W", "90°W", "60°W", "30°W", "0°", "30°E", "60°E", "90°E", "120°E", "150°E", "180°"],
                   rotation=0, fontsize=6)
ax.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree())
ax.set_yticklabels(["90°S", "60°S", "30°S", "0°", "30°N", "60°N", "90°N"], rotation=0, fontsize=6)

ax.minorticks_on()
ax.xaxis.set_minor_locator(ticker.MultipleLocator(10))
ax.yaxis.set_minor_locator(ticker.MultipleLocator(10))

plt.show()

在这里插入图片描述

可以看到虽然绘制出了风场的图像,但是由于数据本身分辨率过高导致风场的图像并不是很直观,且风场的图标颜色不是很合适。因此,下面对风场进行微调,绘制出更加规范的图像。

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from matplotlib.gridspec import GridSpec

fig = plt.figure(figsize=(6, 5), dpi=200)
gs = GridSpec(1, 1, figure=fig)
ax = fig.add_subplot(gs[0, 0], projection=ccrs.PlateCarree(central_longitude=180))

leftlon, rightlon, lowerlat, upperlat = (-180, 180, -90, 90)  # 设置全球地图范围
img_extent = [leftlon, rightlon, lowerlat, upperlat]
lon = u10_ana.longitude
lat = u10_ana.latitude

ax.quiver(lon[::20], lat[::20], u10_ana[::20, ::20], v10_ana[::20, ::20], windspeed_ana[::20, ::20], color="black",
          )
ax.quiverkey(d, 0.95, 1.1, 5, '5 m/s', labelpos='S', coordinates='axes')
ax.add_feature(cfeature.BORDERS.with_scale('10m'))
ax.add_feature(cfeature.COASTLINE.with_scale('10m'))
ax.set_extent(img_extent, crs=ccrs.PlateCarree())  # 设置地图显示范围为全球

ax.set_xticks([-180, -150, -120, -90, -60, -30, 0, 30, 60, 90, 120, 150, 180], crs=ccrs.PlateCarree())
ax.set_xticklabels(["180°W", "150°W", "120°W", "90°W", "60°W", "30°W", "0°", "30°E", "60°E", "90°E", "120°E", "150°E", "180°"],
                   rotation=0, fontsize=6)
ax.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree())
ax.set_yticklabels(["90°S", "60°S", "30°S", "0°", "30°N", "60°N", "90°N"], rotation=0, fontsize=6)

ax.minorticks_on()
ax.xaxis.set_minor_locator(ticker.MultipleLocator(10))
ax.yaxis.set_minor_locator(ticker.MultipleLocator(10))

plt.show()

在这里插入图片描述

可以看到当我们调整了ax.quiver(lon[::20], lat[::20], u10_ana[::20, ::20], v10_ana[::20, ::20], windspeed_ana[::20, ::20], color="black")语句之后,图片变得更加规范了,但是风场的颜色依旧没有发生变化,这个又该怎么办呢?
这里解释一下,虽然我们使用函数对箭头的颜色进行了设置,但是Matplotlib还是会根据风速的大小绘制不同颜色的箭头,而如果要绘制统一颜色或者自定义箭头的颜色就需要自定义色标,然后利用cmap这个参数了。下面,展示使用cmap参数将所有箭头设置为黑色。

自定义色标

newcolors = [[0.03921, 0.03921, 0.03529]]
newcmap_1 = ListedColormap(newcolors)
newcmap_1

在这里插入图片描述

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from matplotlib.gridspec import GridSpec

fig = plt.figure(figsize=(6, 5), dpi=200)
gs = GridSpec(1, 1, figure=fig)
ax = fig.add_subplot(gs[0, 0], projection=ccrs.PlateCarree(central_longitude=180))

leftlon, rightlon, lowerlat, upperlat = (-180, 180, -90, 90)  # 设置全球地图范围
img_extent = [leftlon, rightlon, lowerlat, upperlat]
lon = u10_ana.longitude
lat = u10_ana.latitude

d = ax.quiver(lon[::20], lat[::20], u10_ana[::20, ::20], v10_ana[::20, ::20], windspeed_ana[::20, ::20], cmap=newcmap_1)
ax.quiverkey(d,0.875, 1.025, 10, '10 m/s', labelpos='E', coordinates='axes', color="k") # 设置箭头示例颜色
ax.add_feature(cfeature.BORDERS.with_scale('10m'))
ax.add_feature(cfeature.COASTLINE.with_scale('10m'))
ax.set_extent(img_extent, crs=ccrs.PlateCarree())  # 设置地图显示范围为全球

ax.set_xticks([-180, -150, -120, -90, -60, -30, 0, 30, 60, 90, 120, 150, 180], crs=ccrs.PlateCarree())
ax.set_xticklabels(["180°W", "150°W", "120°W", "90°W", "60°W", "30°W", "0°", "30°E", "60°E", "90°E", "120°E", "150°E", "180°"],
                   rotation=0, fontsize=6)
ax.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree())
ax.set_yticklabels(["90°S", "60°S", "30°S", "0°", "30°N", "60°N", "90°N"], rotation=0, fontsize=6)

ax.minorticks_on()
ax.xaxis.set_minor_locator(ticker.MultipleLocator(10))
ax.yaxis.set_minor_locator(ticker.MultipleLocator(10))
ax.set_title("自定义风场颜色(示例一)")
plt.show()

在这里插入图片描述

将箭头更改为其他颜色

newcolors = [[0.545098, 0.941176, 0.878431]]
newcmap_2 = ListedColormap(newcolors)

newcmap_2

在这里插入图片描述

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from matplotlib.gridspec import GridSpec

fig = plt.figure(figsize=(6, 5), dpi=200)
gs = GridSpec(1, 1, figure=fig)
ax = fig.add_subplot(gs[0, 0], projection=ccrs.PlateCarree(central_longitude=180))

leftlon, rightlon, lowerlat, upperlat = (-180, 180, -90, 90)  # 设置全球地图范围
img_extent = [leftlon, rightlon, lowerlat, upperlat]
lon = u10_ana.longitude
lat = u10_ana.latitude

d = ax.quiver(lon[::20], lat[::20], u10_ana[::20, ::20], v10_ana[::20, ::20], windspeed_ana[::20, ::20], cmap=newcmap_2)
ax.quiverkey(d,0.875, 1.025, 10, '10 m/s', labelpos='E', coordinates='axes', color="k") # 设置箭头示例颜色
ax.add_feature(cfeature.BORDERS.with_scale('10m'))
ax.add_feature(cfeature.COASTLINE.with_scale('10m'))
ax.set_extent(img_extent, crs=ccrs.PlateCarree())  # 设置地图显示范围为全球

ax.set_xticks([-180, -150, -120, -90, -60, -30, 0, 30, 60, 90, 120, 150, 180], crs=ccrs.PlateCarree())
ax.set_xticklabels(["180°W", "150°W", "120°W", "90°W", "60°W", "30°W", "0°", "30°E", "60°E", "90°E", "120°E", "150°E", "180°"],
                   rotation=0, fontsize=6)
ax.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree())
ax.set_yticklabels(["90°S", "60°S", "30°S", "0°", "30°N", "60°N", "90°N"], rotation=0, fontsize=6)

ax.minorticks_on()
ax.xaxis.set_minor_locator(ticker.MultipleLocator(10))
ax.yaxis.set_minor_locator(ticker.MultipleLocator(10))
ax.set_title("自定义风场颜色(示例二)")
plt.show()

在这里插入图片描述

三、绘制每个季节的平均风场

import xarray as xr
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from matplotlib.offsetbox import AnchoredText
from matplotlib.colors import ListedColormap
import cmaps
import matplotlib.ticker as ticker
from matplotlib.gridspec import GridSpec
from cartopy.mpl.geoaxes import GeoAxes
from mpl_toolkits.axes_grid1 import AxesGrid
import datetime as dt

fig = plt.figure(layout="constrained", figsize=(12, 7), dpi=200)
gs = GridSpec(2, 2, figure=fig)

proj = ccrs.PlateCarree(central_longitude=180)
leftlon, rightlon, lowerlat, upperlat = (-180, 180, -90, 90)
img_extent = [leftlon, rightlon, lowerlat, upperlat]

lon = u10.longitude
lat = u10.latitude

seasons = [(0, 3, "DJF"), (3, 6, "MAM"), (6, 9, "JJA"), (9, 12, "SON")]

for i, (start, end, title) in enumerate(seasons):
    ax = fig.add_subplot(gs[i // 2, i % 2], projection=ccrs.PlateCarree())
    u10_sea = u10[start:end, :, :].mean(axis=0)
    v10_sea = v10[start:end, :, :].mean(axis=0)
    windspeed_sea = np.sqrt(u10_sea**2+v10_sea**2)

    d = ax.quiver(lon[::20], lat[::20], u10_sea[::20, ::20], v10_sea[::20, ::20], windspeed_sea[::20, ::20], cmap=newcmap_1)
    ax.quiverkey(d, 0.875, 1.025, 10, '10 m/s', labelpos='E', coordinates='axes', color="k")
    ax.add_feature(cfeature.BORDERS.with_scale('10m'))
    ax.add_feature(cfeature.COASTLINE.with_scale('10m'))
    ax.set_extent(img_extent, crs=ccrs.PlateCarree())

    ax.set_xticks([-180, -150, -120, -90, -60, -30, 0, 30, 60, 90, 120, 150, 180], crs=ccrs.PlateCarree())
    ax.set_xticklabels(["180°W", "150°W", "120°W", "90°W", "60°W", "30°W", "0°", "30°E", "60°E", "90°E", "120°E", "150°E", "180°"],
                       rotation=0, fontsize=6)
    ax.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree())
    ax.set_yticklabels(["90°S", "60°S", "30°S", "0°", "30°N", "60°N", "90°N"], rotation=0, fontsize=6)

    ax.minorticks_on()
    ax.xaxis.set_minor_locator(ticker.MultipleLocator(10))
    ax.yaxis.set_minor_locator(ticker.MultipleLocator(10))
    ax.set_title(title)

plt.tight_layout()
plt.show()

在这里插入图片描述

四、绘制每个月的风场

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from matplotlib.gridspec import GridSpec

fig = plt.figure(figsize=(12, 12), dpi=200)
gs = GridSpec(4, 3, figure=fig)

proj = ccrs.PlateCarree(central_longitude=180)
leftlon, rightlon, lowerlat, upperlat = (-180, 180, -90, 90)
img_extent = [leftlon, rightlon, lowerlat, upperlat]

lon = u10.longitude
lat = u10.latitude

months = list(zip(np.arange(12), ['Dec','Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov']))


for i, (month, title) in enumerate(months):
    ax = fig.add_subplot(gs[i // 3, i % 3], projection=ccrs.PlateCarree())
    u10_mon = u10[month, :, :]
    v10_mon = v10[month, :, :]
    windspeed_mon = np.sqrt(u10_mon**2+v10_mon**2)

    d = ax.quiver(lon[::20], lat[::20], u10_mon[::20, ::20], v10_mon[::20, ::20], windspeed_mon[::20, ::20], cmap=newcmap_1)
    ax.quiverkey(d, 0.7, 1.1, 10, '10 m/s', labelpos='E', coordinates='axes', color="k", fontproperties={"size":7})
    ax.add_feature(cfeature.BORDERS.with_scale('10m'))
    ax.add_feature(cfeature.COASTLINE.with_scale('10m'))
    ax.set_extent(img_extent, crs=ccrs.PlateCarree())

    ax.set_xticks([-180, -150, -120, -90, -60, -30, 0, 30, 60, 90, 120, 150, 180], crs=ccrs.PlateCarree())
    ax.set_xticklabels(["180°W", "150°W", "120°W", "90°W", "60°W", "30°W", "0°", "30°E", "60°E", "90°E", "120°E", "150°E", "180°"],
                       rotation=0, fontsize=4)
    ax.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree())
    ax.set_yticklabels(["90°S", "60°S", "30°S", "0°", "30°N", "60°N", "90°N"], rotation=0, fontsize=3)

    ax.minorticks_on()
    ax.xaxis.set_minor_locator(ticker.MultipleLocator(10))
    ax.yaxis.set_minor_locator(ticker.MultipleLocator(10))
    ax.set_title(title, fontsize=7)
# plt.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9)
# plt.tight_layout(pad=1.5)
plt.show()

在这里插入图片描述
数据及代码下载链接➡️:如何绘制自定义颜色的风场图

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱转呼啦圈的小兔子

觉得文章不错?请小编喝杯咖啡吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值