|
|
@ -13,7 +13,7 @@ Matplotlib With Cartopy |
|
|
|
Cartopy is becoming the main tool for base mapping with matplotlib, but you should |
|
|
|
Cartopy is becoming the main tool for base mapping with matplotlib, but you should |
|
|
|
be aware of a few shortcomings when working with WRF data. |
|
|
|
be aware of a few shortcomings when working with WRF data. |
|
|
|
|
|
|
|
|
|
|
|
- The builtin tranformations of coordinates when calling the contouring functions |
|
|
|
- The builtin transformations of coordinates when calling the contouring functions |
|
|
|
do not work correctly with the rotated pole projection. The |
|
|
|
do not work correctly with the rotated pole projection. The |
|
|
|
transform_points method needs to be called manually on the latitude and |
|
|
|
transform_points method needs to be called manually on the latitude and |
|
|
|
longitude arrays. |
|
|
|
longitude arrays. |
|
|
@ -33,8 +33,6 @@ Plotting a Two-dimensional Field |
|
|
|
:align: center |
|
|
|
:align: center |
|
|
|
|
|
|
|
|
|
|
|
.. code-block:: python |
|
|
|
.. code-block:: python |
|
|
|
|
|
|
|
|
|
|
|
from __future__ import (absolute_import, division, print_function, unicode_literals) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from netCDF4 import Dataset |
|
|
|
from netCDF4 import Dataset |
|
|
|
import matplotlib.pyplot as plt |
|
|
|
import matplotlib.pyplot as plt |
|
|
@ -42,7 +40,8 @@ Plotting a Two-dimensional Field |
|
|
|
import cartopy.crs as crs |
|
|
|
import cartopy.crs as crs |
|
|
|
from cartopy.feature import NaturalEarthFeature |
|
|
|
from cartopy.feature import NaturalEarthFeature |
|
|
|
|
|
|
|
|
|
|
|
from wrf import npvalues, getvar, smooth2d |
|
|
|
from wrf import (to_np, getvar, smooth2d, get_cartopy, latlon_coords, |
|
|
|
|
|
|
|
cartopy_xlim, cartopy_ylim) |
|
|
|
|
|
|
|
|
|
|
|
ncfile = Dataset("wrfout_d01_2016-10-07_00_00_00") |
|
|
|
ncfile = Dataset("wrfout_d01_2016-10-07_00_00_00") |
|
|
|
|
|
|
|
|
|
|
@ -52,15 +51,11 @@ Plotting a Two-dimensional Field |
|
|
|
# Smooth the sea level pressure since it tends to be noisy near the mountains |
|
|
|
# Smooth the sea level pressure since it tends to be noisy near the mountains |
|
|
|
smooth_slp = smooth2d(slp, 3) |
|
|
|
smooth_slp = smooth2d(slp, 3) |
|
|
|
|
|
|
|
|
|
|
|
# Get the numpy array from the XLAT and XLONG coordinates |
|
|
|
# Get the latitude and longitude coordinate arrays |
|
|
|
lats = npvalues(slp.coords["XLAT"]) |
|
|
|
lats, lons = latlon_coords(smooth_slp) |
|
|
|
lons = npvalues(slp.coords["XLONG"]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the wrf.WrfProj object |
|
|
|
|
|
|
|
wrf_proj = slp.attrs["projection"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# The WrfProj.cartopy() method returns a cartopy.crs projection object |
|
|
|
# The WrfProj.cartopy() method returns a cartopy.crs projection object |
|
|
|
cart_proj = wrf_proj.cartopy() |
|
|
|
cart_proj = get_cartopy(smooth_slp) |
|
|
|
|
|
|
|
|
|
|
|
# Create a figure that's 10x10 |
|
|
|
# Create a figure that's 10x10 |
|
|
|
fig = plt.figure(figsize=(10,10)) |
|
|
|
fig = plt.figure(figsize=(10,10)) |
|
|
@ -75,17 +70,583 @@ Plotting a Two-dimensional Field |
|
|
|
ax.coastlines('50m', linewidth=0.8) |
|
|
|
ax.coastlines('50m', linewidth=0.8) |
|
|
|
|
|
|
|
|
|
|
|
# Make the contour outlines and filled contours for the smoothed sea level pressure. |
|
|
|
# Make the contour outlines and filled contours for the smoothed sea level pressure. |
|
|
|
# The transform keyword indicates that the lats and lons arrays are lat/lon coordinates and tells |
|
|
|
plt.contour(to_np(lons), to_np(lats), to_np(smooth_slp), 10, colors="black", |
|
|
|
# cartopy to transform the points in to the WRF projection set for the GeoAxes. |
|
|
|
transform=crs.PlateCarree()) |
|
|
|
plt.contour(lons, lats, npvalues(smooth_slp), 10, colors="black", transform=crs.PlateCarree()) |
|
|
|
plt.contourf(to_np(lons), to_np(lats), to_np(smooth_slp), 10, transform=crs.PlateCarree()) |
|
|
|
plt.contourf(lons, lats, npvalues(smooth_slp), 10, transform=crs.PlateCarree()) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Add a color bar |
|
|
|
# Add a color bar |
|
|
|
plt.colorbar(ax=ax, shrink=.47) |
|
|
|
plt.colorbar(ax=ax, shrink=.47) |
|
|
|
|
|
|
|
|
|
|
|
# Set the map limits |
|
|
|
# Set the map limits |
|
|
|
ax.set_xlim(wrf_proj.cartopy_xlim()) |
|
|
|
ax.set_xlim(cartopy_xlim(smooth_slp)) |
|
|
|
ax.set_ylim(wrf_proj.cartopy_ylim()) |
|
|
|
ax.set_ylim(cartopy_ylim(smooth_slp)) |
|
|
|
|
|
|
|
|
|
|
|
# Add the gridlines |
|
|
|
# Add the gridlines |
|
|
|
ax.gridlines() |
|
|
|
ax.gridlines() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plt.title("Sea Level Pressure (hPa)") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plt.show() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Horizontal Interpolation to a Pressure Level |
|
|
|
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. image:: _static/images/cartopy_500.png |
|
|
|
|
|
|
|
:scale: 100% |
|
|
|
|
|
|
|
:align: center |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. code-block:: python |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from netCDF4 import Dataset |
|
|
|
|
|
|
|
import numpy as np |
|
|
|
|
|
|
|
import matplotlib.pyplot as plt |
|
|
|
|
|
|
|
from matplotlib.cm import get_cmap |
|
|
|
|
|
|
|
import cartopy.crs as crs |
|
|
|
|
|
|
|
from cartopy.feature import NaturalEarthFeature |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from wrf import (getvar, interplevel, to_np, get_cartopy, |
|
|
|
|
|
|
|
latlon_coords, cartopy_xlim, cartopy_ylim) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ncfile = Dataset("wrfout_d01_2016-10-07_00_00_00") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Extract the pressure, geopotential height, and wind variables |
|
|
|
|
|
|
|
p = getvar(ncfile, "pressure") |
|
|
|
|
|
|
|
z = getvar(ncfile, "z", units="dm") |
|
|
|
|
|
|
|
ua = getvar(ncfile, "ua", units="kt") |
|
|
|
|
|
|
|
va = getvar(ncfile, "va", units="kt") |
|
|
|
|
|
|
|
wspd = getvar(ncfile, "wspd_wdir", units="kts")[0,:] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Interpolate geopotential height, u, and v winds to 500 hPa |
|
|
|
|
|
|
|
ht_500 = interplevel(z, p, 500) |
|
|
|
|
|
|
|
u_500 = interplevel(ua, p, 500) |
|
|
|
|
|
|
|
v_500 = interplevel(va, p, 500) |
|
|
|
|
|
|
|
wspd_500 = interplevel(wspd, p, 500) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the lat/lon coordinates |
|
|
|
|
|
|
|
lats, lons = latlon_coords(ht_500) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the cartopy map projection information |
|
|
|
|
|
|
|
cart_proj = get_cartopy(ht_500) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create the figure |
|
|
|
|
|
|
|
fig = plt.figure(figsize=(10,10)) |
|
|
|
|
|
|
|
ax = plt.axes([0.1,0.1,0.8,0.8], projection=cart_proj) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Download and add the states and coastlines |
|
|
|
|
|
|
|
states = NaturalEarthFeature(category='cultural', scale='50m', facecolor='none', |
|
|
|
|
|
|
|
name='admin_1_states_provinces_shp') |
|
|
|
|
|
|
|
ax.add_feature(states, linewidth=0.5) |
|
|
|
|
|
|
|
ax.coastlines('50m', linewidth=0.8) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create the 500 hPa geopotential height contours |
|
|
|
|
|
|
|
levels = np.arange(520., 580., 6.) |
|
|
|
|
|
|
|
contours = plt.contour(to_np(lons), to_np(lats), to_np(ht_500), levels=levels, colors="black", |
|
|
|
|
|
|
|
transform=crs.PlateCarree()) |
|
|
|
|
|
|
|
plt.clabel(contours, inline=1, fontsize=10, fmt="%i") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Wind Speed contours |
|
|
|
|
|
|
|
levels = [25, 30, 35, 40, 50, 60, 70, 80, 90, 100, 110, 120] |
|
|
|
|
|
|
|
wspd_contours = plt.contourf(to_np(lons), to_np(lats), to_np(wspd_500), levels=levels, |
|
|
|
|
|
|
|
cmap=get_cmap("rainbow"), |
|
|
|
|
|
|
|
transform=crs.PlateCarree()) |
|
|
|
|
|
|
|
plt.colorbar(wspd_contours, ax=ax, orientation="horizontal", pad=.05) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Add the 500 hPa wind barbs, only plotting every 125th data point. |
|
|
|
|
|
|
|
plt.barbs(to_np(lons[::125,::125]), to_np(lats[::125,::125]), to_np(u_500[::125, ::125]), |
|
|
|
|
|
|
|
to_np(v_500[::125, ::125]), transform=crs.PlateCarree(), length=6) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the map bounds |
|
|
|
|
|
|
|
ax.set_xlim(cartopy_xlim(ht_500)) |
|
|
|
|
|
|
|
ax.set_ylim(cartopy_ylim(ht_500)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ax.gridlines() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plt.title("500 MB Height (dm), Wind Speed (kt), Barbs (kt)") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plt.show() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Panel Plots From Front Page |
|
|
|
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This lengthy example shows how to make the panel plots on the first page |
|
|
|
|
|
|
|
of the documentation. For a simpler example of how to make a cross section |
|
|
|
|
|
|
|
plot, see :ref:`cross_example`. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. image:: _static/images/matthew.png |
|
|
|
|
|
|
|
:scale: 100% |
|
|
|
|
|
|
|
:align: center |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. code-block:: python |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import numpy as np |
|
|
|
|
|
|
|
import matplotlib.pyplot as plt |
|
|
|
|
|
|
|
from matplotlib.cm import get_cmap |
|
|
|
|
|
|
|
import cartopy.crs as crs |
|
|
|
|
|
|
|
import cartopy.feature as cfeature |
|
|
|
|
|
|
|
from netCDF4 import Dataset |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from wrf import (getvar, to_np, vertcross, smooth2d, CoordPair, GeoBounds, |
|
|
|
|
|
|
|
latlon_coords, get_cartopy, cartopy_xlim, cartopy_ylim) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Open the output NetCDF file |
|
|
|
|
|
|
|
filename = "wrfout_d01_2016-10-07_00_00_00" |
|
|
|
|
|
|
|
ncfile = DataSet(filename) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the WRF variables |
|
|
|
|
|
|
|
slp = getvar(ncfile, "slp") |
|
|
|
|
|
|
|
smooth_slp = smooth2d(slp, 3) |
|
|
|
|
|
|
|
ctt = getvar(ncfile, "ctt") |
|
|
|
|
|
|
|
height = getvar(ncfile, "z") |
|
|
|
|
|
|
|
dbz = getvar(ncfile, "dbz") |
|
|
|
|
|
|
|
Z = 10**(dbz/10.) |
|
|
|
|
|
|
|
wspd = getvar(ncfile, "wspd_wdir", units="kt")[0,:] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the start point and end point for the cross section |
|
|
|
|
|
|
|
start_point = CoordPair(lat=26.76, lon=-80.0) |
|
|
|
|
|
|
|
end_point = CoordPair(lat=26.76, lon=-77.8) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Compute the vertical cross-section interpolation. Also, include the |
|
|
|
|
|
|
|
# lat/lon points along the cross-section in the metadata by setting |
|
|
|
|
|
|
|
# latlon to True. |
|
|
|
|
|
|
|
z_cross = vertcross(Z, height, wrfin=ncfile, start_point=start_point, |
|
|
|
|
|
|
|
end_point=end_point, latlon=True, meta=True) |
|
|
|
|
|
|
|
wspd_cross = vertcross(wspd, height, wrfin=ncfile, start_point=start_point, |
|
|
|
|
|
|
|
end_point=end_point, latlon=True, meta=True) |
|
|
|
|
|
|
|
dbz_cross = 10.0 * np.log10(z_cross) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the latitude and longitude coordinate arrays |
|
|
|
|
|
|
|
lats, lons = latlon_coords(slp) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the cartopy projection object |
|
|
|
|
|
|
|
cart_proj = get_cartopy(slp) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create the figure which will have 3 subplots, one on the left, and |
|
|
|
|
|
|
|
# two vertically stacked on the right. |
|
|
|
|
|
|
|
fig = plt.figure(figsize=(7,5)) |
|
|
|
|
|
|
|
ax_ctt = fig.add_subplot(1,2,1,projection=cart_proj) |
|
|
|
|
|
|
|
ax_wspd = fig.add_subplot(2,2,2) |
|
|
|
|
|
|
|
ax_dbz = fig.add_subplot(2,2,4) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Download and create the states, land, and oceans using cartopy features |
|
|
|
|
|
|
|
states = cfeature.NaturalEarthFeature(category='cultural', scale='50m', facecolor='none', |
|
|
|
|
|
|
|
name='admin_1_states_provinces_shp') |
|
|
|
|
|
|
|
land = cfeature.NaturalEarthFeature(category='physical', name='land', scale='50m', |
|
|
|
|
|
|
|
facecolor=cfeature.COLORS['land']) |
|
|
|
|
|
|
|
ocean = cfeature.NaturalEarthFeature(category='physical', name='ocean', scale='50m', |
|
|
|
|
|
|
|
facecolor=cfeature.COLORS['water']) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Make the ctt contours. |
|
|
|
|
|
|
|
contour_levels = [960, 965, 970, 975, 980, 990] |
|
|
|
|
|
|
|
c1 = ax_ctt.contour(to_np(lons), to_np(lats), to_np(smooth_slp), levels=contour_levels, |
|
|
|
|
|
|
|
colors="white", transform=crs.PlateCarree(), zorder=3, linewidths=1.0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create the filled cloud top temperature contours |
|
|
|
|
|
|
|
contour_levels = [-80.0, -70.0, -60, -50, -40, -30, -20, -10, 0, 10] |
|
|
|
|
|
|
|
ctt_contours = ax_ctt.contourf(lons, lats, to_np(ctt), contour_levels, |
|
|
|
|
|
|
|
cmap=get_cmap("Greys"), transform=crs.PlateCarree(), |
|
|
|
|
|
|
|
zorder=2) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Draw the yellow cross section line |
|
|
|
|
|
|
|
ax_ctt.plot([start_point.lon, end_point.lon], [start_point.lat, end_point.lat], |
|
|
|
|
|
|
|
color="yellow", marker="o", transform=crs.PlateCarree(), zorder=3) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create the label bar for cloud top temperature |
|
|
|
|
|
|
|
cb_ctt = fig.colorbar(ctt_contours, ax=ax_ctt, shrink=.5) |
|
|
|
|
|
|
|
cb_ctt.ax.tick_params(labelsize=5) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Draw the oceans, land, and states |
|
|
|
|
|
|
|
ax_ctt.add_feature(ocean) |
|
|
|
|
|
|
|
ax_ctt.add_feature(land) |
|
|
|
|
|
|
|
ax_ctt.add_feature(states, linewidth=.5, edgecolor="black") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Crop the domain to the region around the hurricane |
|
|
|
|
|
|
|
hur_bounds = GeoBounds(CoordPair(lat=np.amin(to_np(lats)), lon=-85.0), |
|
|
|
|
|
|
|
CoordPair(lat=30.0, lon=-72.0)) |
|
|
|
|
|
|
|
ax_ctt.set_xlim(cartopy_xlim(ctt, geobounds=hur_bounds)) |
|
|
|
|
|
|
|
ax_ctt.set_ylim(cartopy_ylim(ctt, geobounds=hur_bounds)) |
|
|
|
|
|
|
|
ax_ctt.gridlines() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Make the contour plot for wspd |
|
|
|
|
|
|
|
wspd_contours = ax_wspd.contourf(to_np(wspd_cross)) |
|
|
|
|
|
|
|
# Add the color bar |
|
|
|
|
|
|
|
cb_wspd = fig.colorbar(wspd_contours, ax=ax_wspd) |
|
|
|
|
|
|
|
cb_wspd.ax.tick_params(labelsize=5) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Make the contour plot for dbz |
|
|
|
|
|
|
|
levels = [5 + 5*n for n in range(15)] |
|
|
|
|
|
|
|
dbz_contours = ax_dbz.contourf(to_np(dbz_cross), levels=levels) |
|
|
|
|
|
|
|
cb_dbz = fig.colorbar(dbz_contours, ax=ax_dbz) |
|
|
|
|
|
|
|
cb_dbz.ax.tick_params(labelsize=5) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the x-ticks to use latitude and longitude labels. |
|
|
|
|
|
|
|
coord_pairs = to_np(dbz_cross.coords["xy_loc"]) |
|
|
|
|
|
|
|
x_ticks = np.arange(coord_pairs.shape[0]) |
|
|
|
|
|
|
|
x_labels = [pair.latlon_str() for pair in to_np(coord_pairs)] |
|
|
|
|
|
|
|
ax_wspd.set_xticks(x_ticks[::20]) |
|
|
|
|
|
|
|
ax_wspd.set_xticklabels([], rotation=45) |
|
|
|
|
|
|
|
ax_dbz.set_xticks(x_ticks[::20]) |
|
|
|
|
|
|
|
ax_dbz.set_xticklabels(x_labels[::20], rotation=45, fontsize=4) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the y-ticks to be height. |
|
|
|
|
|
|
|
vert_vals = to_np(dbz_cross.coords["vertical"]) |
|
|
|
|
|
|
|
v_ticks = np.arange(vert_vals.shape[0]) |
|
|
|
|
|
|
|
ax_wspd.set_yticks(v_ticks[::20]) |
|
|
|
|
|
|
|
ax_wspd.set_yticklabels(vert_vals[::20], fontsize=4) |
|
|
|
|
|
|
|
ax_dbz.set_yticks(v_ticks[::20]) |
|
|
|
|
|
|
|
ax_dbz.set_yticklabels(vert_vals[::20], fontsize=4) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the x-axis and y-axis labels |
|
|
|
|
|
|
|
ax_dbz.set_xlabel("Latitude, Longitude", fontsize=5) |
|
|
|
|
|
|
|
ax_wspd.set_ylabel("Height (m)", fontsize=5) |
|
|
|
|
|
|
|
ax_dbz.set_ylabel("Height (m)", fontsize=5) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Add titles |
|
|
|
|
|
|
|
ax_ctt.set_title("Cloud Top Temperature (degC)", {"fontsize" : 7}) |
|
|
|
|
|
|
|
ax_wspd.set_title("Cross-Section of Wind Speed (kt)", {"fontsize" : 7}) |
|
|
|
|
|
|
|
ax_dbz.set_title("Cross-Section of Reflectivity (dBZ)", {"fontsize" : 7}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plt.show() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Matplotlib with Basemap |
|
|
|
|
|
|
|
----------------------- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Although basemap is in maintenance mode only and becoming deprecated, it is still |
|
|
|
|
|
|
|
widely used by many programmers. Cartopy is becoming the preferred package for |
|
|
|
|
|
|
|
mapping, however it suffers from growing pains in some areas |
|
|
|
|
|
|
|
(can't use latitude/longitude labels for many map projections). If you |
|
|
|
|
|
|
|
run in to these issues, basemap is likely to accomplish what you need, despite |
|
|
|
|
|
|
|
slower performance. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Plotting a Two-Dimensional Field |
|
|
|
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. image:: _static/images/basemap_slp.png |
|
|
|
|
|
|
|
:scale: 100% |
|
|
|
|
|
|
|
:align: center |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. code-block:: python |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from netCDF4 import Dataset |
|
|
|
|
|
|
|
import matplotlib.pyplot as plt |
|
|
|
|
|
|
|
from matplotlib.cm import get_cmap |
|
|
|
|
|
|
|
from mpl_toolkits.basemap import Basemap |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from wrf import to_np, getvar, smooth2d, latlon_coords, get_basemap |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ncfile = Dataset("wrfout_d01_2016-10-07_00_00_00") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the sea level pressure |
|
|
|
|
|
|
|
slp = getvar(ncfile, "slp") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Smooth the sea level pressure since it tends to be noisey near the mountains |
|
|
|
|
|
|
|
smooth_slp = smooth2d(slp, 3) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the latitude and longitude coordinates |
|
|
|
|
|
|
|
lats, lons = latlon_coords(slp) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the basemap projection object |
|
|
|
|
|
|
|
bm = get_basemap(slp) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create a figure that's 10x10 |
|
|
|
|
|
|
|
fig = plt.figure(figsize=(10,10)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bm.drawcoastlines(linewidth=0.25) |
|
|
|
|
|
|
|
bm.drawstates(linewidth=0.25) |
|
|
|
|
|
|
|
bm.drawcountries(linewidth=0.25) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Convert the lats and lons to x and y. Make sure you convert the lats and lons to |
|
|
|
|
|
|
|
# numpy arrays via to_np, or basemap crashes with an undefined RuntimeError. |
|
|
|
|
|
|
|
x, y = bm(to_np(lons), to_np(lats)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Draw the contours and filled contours |
|
|
|
|
|
|
|
bm.contour(x, y, to_np(smooth_slp), 10, colors="black") |
|
|
|
|
|
|
|
bm.contourf(x, y, to_np(smooth_slp), 10) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Add a color bar |
|
|
|
|
|
|
|
plt.colorbar(shrink=.47) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plt.title("Sea Level Pressure (hPa)") |
|
|
|
|
|
|
|
plt.show() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Horizontal Interpolation to a Pressure Level |
|
|
|
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. image:: _static/images/basemap_500.png |
|
|
|
|
|
|
|
:scale: 100% |
|
|
|
|
|
|
|
:align: center |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. code-block:: python |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from netCDF4 import Dataset |
|
|
|
|
|
|
|
import numpy as np |
|
|
|
|
|
|
|
import matplotlib.pyplot as plt |
|
|
|
|
|
|
|
from matplotlib.cm import get_cmap |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from wrf import getvar, interplevel, to_np, get_basemap, latlon_coords |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ncfile = Dataset("wrfout_d01_2016-10-07_00_00_00") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Extract the pressure, geopotential height, and wind variables |
|
|
|
|
|
|
|
p = getvar(ncfile, "pressure") |
|
|
|
|
|
|
|
z = getvar(ncfile, "z", units="dm") |
|
|
|
|
|
|
|
ua = getvar(ncfile, "ua", units="kt") |
|
|
|
|
|
|
|
va = getvar(ncfile, "va", units="kt") |
|
|
|
|
|
|
|
wspd = getvar(ncfile, "wspd_wdir", units="kts")[0,:] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Interpolate geopotential height, u, and v winds to 500 hPa |
|
|
|
|
|
|
|
ht_500 = interplevel(z, p, 500) |
|
|
|
|
|
|
|
u_500 = interplevel(ua, p, 500) |
|
|
|
|
|
|
|
v_500 = interplevel(va, p, 500) |
|
|
|
|
|
|
|
wspd_500 = interplevel(wspd, p, 500) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the lat/lon coordinates |
|
|
|
|
|
|
|
lats, lons = latlon_coords(ht_500) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the basemap projection object |
|
|
|
|
|
|
|
bm = get_basemap(ht_500) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create the figure |
|
|
|
|
|
|
|
fig = plt.figure(figsize=(8,8)) |
|
|
|
|
|
|
|
ax = plt.axes([0.1,0.1,0.8,0.8]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the x and y coordinates |
|
|
|
|
|
|
|
x, y = bm(to_np(lons), to_np(lats)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create the 500 hPa geopotential height contours |
|
|
|
|
|
|
|
levels = np.arange(520., 580., 6.) |
|
|
|
|
|
|
|
contours = bm.contour(x, y, to_np(ht_500), levels=levels, colors="black") |
|
|
|
|
|
|
|
plt.clabel(contours, inline=1, fontsize=10, fmt="%i") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Wind Speed contours |
|
|
|
|
|
|
|
levels = [25, 30, 35, 40, 50, 60, 70, 80, 90, 100, 110, 120] |
|
|
|
|
|
|
|
wspd_contours = bm.contourf(x, y, to_np(wspd_500), levels=levels, |
|
|
|
|
|
|
|
cmap=get_cmap("rainbow")) |
|
|
|
|
|
|
|
plt.colorbar(wspd_contours, ax=ax, orientation="horizontal", pad=.05) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bm.drawcoastlines(linewidth=0.25) |
|
|
|
|
|
|
|
bm.drawstates(linewidth=0.25) |
|
|
|
|
|
|
|
bm.drawcountries(linewidth=0.25) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Add the 500 hPa wind barbs, only plotting every 125th data point. |
|
|
|
|
|
|
|
bm.barbs(x[::125,::125], y[::125,::125], to_np(u_500[::125, ::125]), |
|
|
|
|
|
|
|
to_np(v_500[::125, ::125]), length=6) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plt.title("500 MB Height (dm), Wind Speed (kt), Barbs (kt)") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plt.show() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Panel Plots from the Front Page |
|
|
|
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This lengthy example shows how to make the panel plots on the first page |
|
|
|
|
|
|
|
of the documentation. For a simpler example of how to make a cross section |
|
|
|
|
|
|
|
plot, see :ref:`cross_example`. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. image:: _static/images/basemap_front.png |
|
|
|
|
|
|
|
:scale: 100% |
|
|
|
|
|
|
|
:align: center |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. code-block:: python |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import numpy as np |
|
|
|
|
|
|
|
import matplotlib.pyplot as plt |
|
|
|
|
|
|
|
from matplotlib.cm import get_cmap |
|
|
|
|
|
|
|
from netCDF4 import Dataset |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from wrf import getvar, to_np, vertcross, smooth2d, CoordPair, get_basemap, latlon_coords |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Open the output NetCDF file |
|
|
|
|
|
|
|
filename = "/Users/ladwig/Documents/wrf_files/wrfout_d01_2016-10-07_00_00_00" |
|
|
|
|
|
|
|
ncfile = Dataset(filename) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the WRF variables |
|
|
|
|
|
|
|
slp = getvar(ncfile, "slp") |
|
|
|
|
|
|
|
smooth_slp = smooth2d(slp, 3) |
|
|
|
|
|
|
|
ctt = getvar(ncfile, "ctt") |
|
|
|
|
|
|
|
z = getvar(ncfile, "z", timeidx=0) |
|
|
|
|
|
|
|
dbz = getvar(ncfile, "dbz", timeidx=0) |
|
|
|
|
|
|
|
Z = 10**(dbz/10.) |
|
|
|
|
|
|
|
wspd = getvar(ncfile, "wspd_wdir", units="kt")[0,:] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the start point and end point for the cross section |
|
|
|
|
|
|
|
start_point = CoordPair(lat=26.76, lon=-80.0) |
|
|
|
|
|
|
|
end_point = CoordPair(lat=26.76, lon=-77.8) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Compute the vertical cross-section interpolations. Also, include the lat/lon points along the cross-section |
|
|
|
|
|
|
|
# in the metadata by setting latlon to True. |
|
|
|
|
|
|
|
z_cross = vertcross(Z, z, wrfin=ncfile, start_point=start_point, end_point=end_point, latlon=True, meta=True) |
|
|
|
|
|
|
|
wspd_cross = vertcross(wspd, z, wrfin=ncfile, start_point=start_point, end_point=end_point, latlon=True, meta=True) |
|
|
|
|
|
|
|
dbz_cross = 10.0 * np.log10(z_cross) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Extract the latitude and longitude coordinate arrays |
|
|
|
|
|
|
|
lats, lons = latlon_coords(slp) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create a figure that will have 3 subplots. One on the left, |
|
|
|
|
|
|
|
# two vertically stacked on the right. |
|
|
|
|
|
|
|
fig = plt.figure(figsize=(8,5)) |
|
|
|
|
|
|
|
ax_ctt = fig.add_subplot(1,2,1) |
|
|
|
|
|
|
|
ax_wspd = fig.add_subplot(2,2,2) |
|
|
|
|
|
|
|
ax_dbz = fig.add_subplot(2,2,4) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the basemap projection class |
|
|
|
|
|
|
|
bm = get_basemap(slp) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the x, y values |
|
|
|
|
|
|
|
x, y = bm(to_np(lons), to_np(lats)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Make the pressure contours. |
|
|
|
|
|
|
|
contour_levels = [960, 965, 970, 975, 980, 990] |
|
|
|
|
|
|
|
c1 = bm.contour(x, y, to_np(smooth_slp), levels=contour_levels, colors="white", |
|
|
|
|
|
|
|
zorder=3, linewidths=1.0, ax=ax_ctt) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create the filled cloud top temperature contours |
|
|
|
|
|
|
|
contour_levels = [-80.0, -70.0, -60, -50, -40, -30, -20, -10, 0, 10] |
|
|
|
|
|
|
|
ctt_contours = bm.contourf(x, y, to_np(ctt), contour_levels, cmap=get_cmap("Greys"), |
|
|
|
|
|
|
|
zorder=2, ax=ax_ctt) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
point_x, point_y = bm([start_point.lon, end_point.lon], [start_point.lat, end_point.lat]) |
|
|
|
|
|
|
|
bm.plot([point_x[0], point_x[1]], [point_y[0], point_y[1]], color="yellow", |
|
|
|
|
|
|
|
marker="o", zorder=3, ax=ax_ctt) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create the label bar for cloud top temperature |
|
|
|
|
|
|
|
cb_ctt = fig.colorbar(ctt_contours, ax=ax_ctt, shrink=.68) |
|
|
|
|
|
|
|
cb_ctt.ax.tick_params(labelsize=5) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Draw the oceans, land, and states. Use the same colors as the cartopy |
|
|
|
|
|
|
|
# example |
|
|
|
|
|
|
|
bm.drawcoastlines(linewidth=0.25, ax=ax_ctt) |
|
|
|
|
|
|
|
bm.drawstates(linewidth=0.25, ax=ax_ctt) |
|
|
|
|
|
|
|
bm.drawcountries(linewidth=0.25, ax=ax_ctt) |
|
|
|
|
|
|
|
bm.fillcontinents(color=np.array([ 0.9375 , 0.9375 , 0.859375]), |
|
|
|
|
|
|
|
ax=ax_ctt, lake_color=np.array([ 0.59375 , 0.71484375, 0.8828125 ])) |
|
|
|
|
|
|
|
bm.drawmapboundary(fill_color=np.array([ 0.59375 , 0.71484375, 0.8828125 ]), ax=ax_ctt) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Draw Parallels |
|
|
|
|
|
|
|
parallels = np.arange(np.amin(lats), 30., 2.5) |
|
|
|
|
|
|
|
bm.drawparallels(parallels, ax=ax_ctt) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
merids = np.arange(-85.0, -72.0, 2.5) |
|
|
|
|
|
|
|
bm.drawmeridians(merids, ax=ax_ctt) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get the x and y coordinate ranges for the cropped region around the |
|
|
|
|
|
|
|
# hurricane |
|
|
|
|
|
|
|
x_start, y_start = bm(-85.0, np.amin(lats)) |
|
|
|
|
|
|
|
x_end, y_end = bm(-72.0, 30.0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ax_ctt.set_xlim([x_start, x_end]) |
|
|
|
|
|
|
|
ax_ctt.set_ylim([y_start, y_end]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Make the contour plot for wspd |
|
|
|
|
|
|
|
wspd_contours = ax_wspd.contourf(to_np(wspd_cross)) |
|
|
|
|
|
|
|
# Add the color bar |
|
|
|
|
|
|
|
cb_wspd = fig.colorbar(wspd_contours, ax=ax_wspd) |
|
|
|
|
|
|
|
cb_wspd.ax.tick_params(labelsize=5) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Make the contour plot for dbz |
|
|
|
|
|
|
|
levels = [5 + 5*n for n in range(15)] |
|
|
|
|
|
|
|
dbz_contours = ax_dbz.contourf(to_np(dbz_cross), levels=levels) |
|
|
|
|
|
|
|
cb_dbz = fig.colorbar(dbz_contours, ax=ax_dbz) |
|
|
|
|
|
|
|
cb_dbz.ax.tick_params(labelsize=5) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the x-ticks to use latitude and longitude labels. |
|
|
|
|
|
|
|
coord_pairs = to_np(dbz_cross.coords["xy_loc"]) |
|
|
|
|
|
|
|
x_ticks = np.arange(coord_pairs.shape[0]) |
|
|
|
|
|
|
|
x_labels = [pair.latlon_str() for pair in to_np(coord_pairs)] |
|
|
|
|
|
|
|
ax_wspd.set_xticks(x_ticks[::20]) |
|
|
|
|
|
|
|
ax_wspd.set_xticklabels([], rotation=45) |
|
|
|
|
|
|
|
ax_dbz.set_xticks(x_ticks[::20]) |
|
|
|
|
|
|
|
ax_dbz.set_xticklabels(x_labels[::20], rotation=45, fontsize=4) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the y-ticks to be height. |
|
|
|
|
|
|
|
vert_vals = to_np(dbz_cross.coords["vertical"]) |
|
|
|
|
|
|
|
v_ticks = np.arange(vert_vals.shape[0]) |
|
|
|
|
|
|
|
ax_wspd.set_yticks(v_ticks[::20]) |
|
|
|
|
|
|
|
ax_wspd.set_yticklabels(vert_vals[::20], fontsize=4) |
|
|
|
|
|
|
|
ax_dbz.set_yticks(v_ticks[::20]) |
|
|
|
|
|
|
|
ax_dbz.set_yticklabels(vert_vals[::20], fontsize=4) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the x-axis and y-axis labels |
|
|
|
|
|
|
|
ax_dbz.set_xlabel("Latitude, Longitude", fontsize=5) |
|
|
|
|
|
|
|
ax_wspd.set_ylabel("Height (m)", fontsize=5) |
|
|
|
|
|
|
|
ax_dbz.set_ylabel("Height (m)", fontsize=5) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Add a title |
|
|
|
|
|
|
|
ax_ctt.set_title("Cloud Top Temperature (degC)", {"fontsize" : 7}) |
|
|
|
|
|
|
|
ax_wspd.set_title("Cross-Section of Wind Speed (kt)", {"fontsize" : 7}) |
|
|
|
|
|
|
|
ax_dbz.set_title("Cross-Section of Reflectivity (dBZ)", {"fontsize" : 7}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plt.show() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. _cross_example: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Vertical Cross Section |
|
|
|
|
|
|
|
------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Vertical cross sections require no mapping software package and can be |
|
|
|
|
|
|
|
plotted using the standard matplotlib API. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. image:: _static/images/cartopy_cross.png |
|
|
|
|
|
|
|
:scale: 100% |
|
|
|
|
|
|
|
:align: center |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. code-block:: python |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import numpy as np |
|
|
|
|
|
|
|
import matplotlib.pyplot as plt |
|
|
|
|
|
|
|
from matplotlib.cm import get_cmap |
|
|
|
|
|
|
|
from netCDF4 import Dataset |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from wrf import to_np, getvar, CoordPair, vertcross |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Open the output NetCDF file with PyNIO |
|
|
|
|
|
|
|
filename = "wrfout_d01_2016-10-07_00_00_00" |
|
|
|
|
|
|
|
ncfile = Dataset(filename) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Extract pressure and model height |
|
|
|
|
|
|
|
z = getvar(ncfile, "z") |
|
|
|
|
|
|
|
wspd = getvar(ncfile, "uvmet_wspd_wdir", units="kt")[0,:] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Define the start point and end point for the cross section using |
|
|
|
|
|
|
|
# latitude and longitude coordinates. |
|
|
|
|
|
|
|
start_point = CoordPair(lat=26.76, lon=-80.0) |
|
|
|
|
|
|
|
end_point = CoordPair(lat=26.76, lon=-77.8) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Compute the vertical cross-section interpolation. Also, include the lat/lon |
|
|
|
|
|
|
|
# points along the cross-section in the metadata by setting latlon to True. |
|
|
|
|
|
|
|
wspd_cross = vertcross(wspd, z, wrfin=ncfile, start_point=start_point, |
|
|
|
|
|
|
|
end_point=end_point, latlon=True, meta=True) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create the figure |
|
|
|
|
|
|
|
fig = plt.figure(figsize=(10,5)) |
|
|
|
|
|
|
|
ax = plt.axes([0.1,0.1,0.8,0.8]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Make the contour plot |
|
|
|
|
|
|
|
wspd_contours = ax.contourf(to_np(wspd_cross)) |
|
|
|
|
|
|
|
# Add the color bar |
|
|
|
|
|
|
|
plt.colorbar(wspd_contours, ax=ax) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the x-ticks to use latitude and longitude labels. |
|
|
|
|
|
|
|
coord_pairs = to_np(wspd_cross.coords["xy_loc"]) |
|
|
|
|
|
|
|
x_ticks = np.arange(coord_pairs.shape[0]) |
|
|
|
|
|
|
|
x_labels = [pair.latlon_str(fmt="{:.2f}, {:.2f}") for pair in to_np(coord_pairs)] |
|
|
|
|
|
|
|
ax.set_xticks(x_ticks[::20]) |
|
|
|
|
|
|
|
ax.set_xticklabels(x_labels[::20], rotation=45, fontsize=8) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the y-ticks to be height. |
|
|
|
|
|
|
|
vert_vals = to_np(wspd_cross.coords["vertical"]) |
|
|
|
|
|
|
|
v_ticks = np.arange(vert_vals.shape[0]) |
|
|
|
|
|
|
|
ax.set_yticks(v_ticks[::20]) |
|
|
|
|
|
|
|
ax.set_yticklabels(vert_vals[::20], fontsize=8) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the x-axis and y-axis labels |
|
|
|
|
|
|
|
ax.set_xlabel("Latitude, Longitude", fontsize=12) |
|
|
|
|
|
|
|
ax.set_ylabel("Height (m)", fontsize=12) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plt.title("Vertical Cross Section of Wind Speed (kt)") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
plt.show() |
|
|
|
|
|
|
|
|
|
|
|