在此降水图上显示两个水平色条,导致较大的空白

2024-06-17 12:28:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用Metpy制作一张漂亮的降水图。我觉得这更像是一个问题,但是我被如何在这个图上添加两个水平色条难住了。总体的想法是在这张地图上显示雪和雨的速率,这是我通过在一个图上使用两个等高线填充完成的。我想显示两个色条,因为我有两个单独的雪和雨的速率。理想情况下,我希望两个色条水平并排。我得到的最接近的方法是在它们之间有一个很大的空间来堆放它们。这是我的草率代码

import metpy
from siphon.catalog import TDSCatalog
from datetime import datetime, timedelta
%matplotlib inline
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from metpy.units import units
import metpy.calc as mpcalc
import matplotlib.pyplot as plt
import matplotlib.colors as cls
from xarray.backends import NetCDF4DataStore
import xarray as xr
from scipy.ndimage import gaussian_filter
import numpy as np

# Set up access via NCSS
gfs_catalog = ('http://thredds.ucar.edu/thredds/catalog/grib/NCEP/GFS/'
              'Global_0p5deg/catalog.xml?dataset=grib/NCEP/GFS/Global_0p5deg/Best')
cat = TDSCatalog(gfs_catalog)
ncss = cat.datasets[0].subset()
query3 = ncss.query()
query3.accept('netcdf')
query3.variables('Pressure_reduced_to_MSL_msl', 'Precipitation_rate_surface', 'Snow_depth_surface', 'Categorical_Snow_surface')
now = datetime.utcnow()
query3.time_range(now, now + timedelta(days=4))
query3.lonlat_box(west=-140, east=-60, north=60, south=20)
data3 = ncss.get_data(query3)
ds3 = xr.open_dataset(NetCDF4DataStore(data3))

#parsing data
isSnow_var = ds3.metpy.parse_cf('Categorical_Snow_surface')
precip_var = ds3.metpy.parse_cf('Precipitation_rate_surface')
longitude = precip_var.metpy.x
latitude = precip_var.metpy.y
time_index = 11

#All the Precip Stuff
precip_inch_hour = precip_var[time_index].squeeze() *  141.73228346457 
precip2 = mpcalc.smooth_n_point(precip_inch_hour, 5, 1)

#Converting to 10:1 snow ratio
snow_precip = (precip_inch_hour * isSnow_var[time_index].squeeze()) * 10

# Plot using CartoPy and Matplotlib
mapproj = ccrs.LambertConformal(central_latitude=45., central_longitude=-100.)

# Set projection of data
data_projection = ccrs.PlateCarree()

# Grab data for plotting state boundaries
states_provinces = cfeature.NaturalEarthFeature(
       category='cultural',
       name='admin_1_states_provinces_lakes',
       scale='50m',
       facecolor='none')

# Set extent and plot map lines
fig = plt.figure(1, figsize=(25.,25.))
ax = plt.subplot(111, projection=mapproj)
ax.set_extent([-125., -70, 25., 50.], ccrs.PlateCarree())
ax.coastlines('50m', edgecolor='black', linewidth=0.75)
ax.add_feature(states_provinces, edgecolor='black', linewidth=0.5)

#colormap data
precip_colors = [
   "#bde9bf",  # 0.01 - 0.02 inches 1
   "#adddb0",  # 0.02 - 0.03 inches 2
   "#9ed0a0",  # 0.03 - 0.04 inches 3
   "#8ec491",  # 0.04 - 0.05 inches 4
   "#7fb882",  # 0.05 - 0.06 inches 5
   "#70ac74",  # 0.06 - 0.07 inches 6
   "#60a065",  # 0.07 - 0.08 inches 7
   "#519457",  # 0.08 - 0.09 inches 8
   "#418849",  # 0.09 - 0.10 inches 9
   "#307c3c",  # 0.10 - 0.12 inches 10
   "#1c712e",  # 0.12 - 0.14 inches 11
   "#f7f370",  # 0.14 - 0.16 inches 12
   "#fbdf65",  # 0.16 - 0.18 inches 13
   "#fecb5a",  # 0.18 - 0.2 inches 14
   "#ffb650",  # 0.2 - 0.3 inches 15
   "#ffa146",  # 0.3 - 0.4 inches 16
   "#ff8b3c",   # 0.4 - 0.5 inches 17
   "#ff8b3c"   # 0.5 - 0.6 inches 18
]

precip_colormap = cls.ListedColormap(precip_colors)

#Precip Rate
clev_precip =  np.concatenate((np.arange(0.01, 0.1, .01), np.arange(.1, .2, .02), np.arange(.2, .61, .1)))
norm = cls.BoundaryNorm(clev_precip, 18)
cf = ax.contourf(longitude, latitude, precip2, clev_precip, cmap=precip_colormap, norm=norm, transform=ccrs.PlateCarree())
cb = plt.colorbar(cf, ticks=clev_precip, aspect=65, orientation = 'horizontal', shrink=0.6, pad=0.01)

snow_colors = [
   "#63c9d5",  # 0.1 - 0.2 inches 1
   "#5fb4ca",  # 0.2 - 0.3 inches 2
   "#5a9fc0",  # 0.3 - 0.4 inches 3
   "#558ab5",  # 0.4 - 0.5 inches 4
   "#4e76aa",  # 0.5 - 0.6 inches 5
   "#4763a0",  # 0.6 - 0.7 inches 6
   "#3e4f95",  # 0.7 - 0.8 inches 7
   "#353c8b",  # 0.8 - 0.9 inches 8
   "#292980",  # 0.9 - 1.0 inches 9
   "#493387",  # 1.0 - 1.2 inches 10
   "#643e8e",  # 1.2 - 1.4 inches 11
   "#7c4995",  # 1.4 - 1.6 inches 12
   "#94559c",  # 1.6 - 0.18 inches 13
   "#ab61a3",  # 1.8 - 2 inches 14
   "#c36eaa",  # 2 - 3 inches 15
   "#da7bb0",  # 3 - 4 inches 16
   "#f288b7"   # 4 - 5 inches 17
]

snow_colormap = cls.ListedColormap(snow_colors)

#Snow Rate
clev_snow =  np.concatenate((np.arange(.1, 1, .1), np.arange(1, 2, .2), np.arange(2, 6, 1)))
norm2 = cls.BoundaryNorm(clev_snow, 17)
cf2 = ax.contourf(longitude, latitude, snow_precip, clev_snow, cmap=snow_colormap, norm=norm2, transform=ccrs.PlateCarree())
cb2 = plt.colorbar(cf2, ticks=clev_snow, orientation = 'horizontal', pad=0.01, shrink=0.6, aspect=65)

#Valid Time
vtime = isSnow_var.metpy.time[time_index].values

#Title Info
plt.title('MSLP (hPa) with Highs and Lows, 1000-500 hPa Thickness (m), Rain (in/hr), Snow 10:1 (in/hr)', loc='left')
plt.title(f'VALID: {vtime}', loc='right')

Example of Plot

我尝试过子地块和gridSpec,但我不断遇到不同的障碍,在尝试这些不同的方法时会出现不同的错误。我认为这主要与我对Metpy、Cartopy和Matplotlib的入门级知识有关。请告知对此问题的任何见解和可能的解决方案。谢谢


Tags: importdatatimevarasnppltax
1条回答
网友
1楼 · 发布于 2024-06-17 12:28:51

首先,感谢您以可复制的方式发布所有代码

这看起来像是subaxes的解决方案。使用fig.add_axes可以精确地在需要的地方创建子节点

我使用了以下两个块来代替cb语句:

cax1 = fig.add_axes([0.15, 0.25, 0.3, 0.02])
cb = fig.colorbar(cf, cax=cax1, orientation = 'horizontal')

cax2 = fig.add_axes([0.55, 0.25, 0.3, 0.02])
cb2 = fig.colorbar(cf2, cax=cax2, orientation = 'horizontal')

这将创建两个并排的水平色条。这四个数字是左下角在x和y中的位置,以及在x和y中的大小,所有这些都是数字大小的一部分。我没有metpy在这台机器上工作,所以必须使用随机数据,但这不会影响您的结果:

side by side colorbars1

注意:在创建新轴时,对plt.<function>的任何调用都将默认使用上次创建的轴,在本例中为cb2。出于这个原因,您可以选择使用mantplotlib首选的面向对象编程风格,因此使用ax.set_title而不是plt.title创建标题

相关问题 更多 >