Completed
Pull Request — master (#333)
by
unknown
01:19
created

plot_background()   A

Complexity

Conditions 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
1
# Copyright (c) 2008-2016 MetPy Developers.
2
# Distributed under the terms of the BSD 3-Clause License.
3
# SPDX-License-Identifier: BSD-3-Clause
4
"""
5
Four Panel Map
6
===============
7
8
By reading model output data from a netCDF file, we can create a four panel plot showing:
9
10
* 300 hPa heights and winds
11
* 500 hPa heights and absolute vorticity
12
* Surface temperatures
13
* Precipitable water
14
"""
15
16
###########################################
17
18
import netCDF4
19
import numpy as np
20
import scipy.ndimage as ndimage
21
import matplotlib.pyplot as plt
22
import matplotlib.gridspec as gridspec
23
import cartopy.crs as ccrs
24
import cartopy.feature as cfeature
25
from metpy.cbook import get_test_data
26
27
###########################################
28
29
30
# Function used to create the map subplots
31
def plot_background(ax):
32
    ax.set_extent([235., 290., 20., 55.])
33
    ax.coastlines('50m', edgecolor='black', linewidth=0.5)
34
    ax.add_feature(states_provinces, edgecolor='black', linewidth=0.5)
35
    ax.add_feature(country_borders, edgecolor='black', linewidth=0.5)
36
    return ax
37
38
###########################################
39
40
# Open the example netCDF data
41
ds = netCDF4.Dataset(get_test_data('gfs_output.nc', False))
42
print(ds)
43
44
###########################################
45
46
# Convert number of hours since the reference time into an actual date
47
time_vals = netCDF4.num2date(ds.variables['time'][:].squeeze(), ds.variables['time'].units)
48
49
###########################################
50
51
# Combine 1D latitude and longitudes into a 2D grid of locations
52
lon_2d, lat_2d = np.meshgrid(ds.variables['lon'][:], ds.variables['lat'][:])
53
54
###########################################
55
56
# Convert data to common formats
57
vort_500 = ds.variables['vort_500'][0] * 10**5  # To plot a e-5 s^-1
58
surface_temp = ds.variables['temp'][0] * 1.8 - 459.67
59
precip_water = ds.variables['precip_water'][0] * 0.0393700787
60
winds_300 = ds.variables['winds_300'][0] * 1.94384
61
62
###########################################
63
64
# Smooth the height data
65
heights_300 = ndimage.gaussian_filter(ds.variables['heights_300'][0], sigma=1.5, order=0)
66
heights_500 = ndimage.gaussian_filter(ds.variables['heights_500'][0], sigma=1.5, order=0)
67
68
###########################################
69
70
# Add state boundaries to plot
71
states_provinces = cfeature.NaturalEarthFeature(category='cultural',
72
                                                name='admin_1_states_provinces_lines',
73
                                                scale='50m', facecolor='none')
74
75
# Add country borders to plot
76
country_borders = cfeature.NaturalEarthFeature(category='cultural',
77
                                               name='admin_0_countries',
78
                                               scale='50m', facecolor='none')
79
80
crs = ccrs.LambertConformal(central_longitude=-100.0, central_latitude=45.0)
81
82
###########################################
83
84
# Create the figure
85
fig = plt.figure(figsize=(20, 15))
86
gs = gridspec.GridSpec(5, 2, height_ratios=[1, .05, 1, .05, 0], bottom=.05, top=.95, wspace=.1)
87
88
89
# Upper left plot - 300-hPa winds and geopotential heights
90
ax1 = plt.subplot(gs[0, 0], projection=crs)
91
plot_background(ax1)
92
cf1 = ax1.contourf(lon_2d, lat_2d, winds_300, cmap='cool', transform=ccrs.PlateCarree())
93
c1 = ax1.contour(lon_2d, lat_2d, heights_300, colors='black', linewidth=2,
94
                 transform=ccrs.PlateCarree())
95
plt.clabel(c1, fontsize=10, inline=1, inline_spacing=1, fmt='%i', rightside_up=True)
96
97
ax2 = plt.subplot(gs[1, 0])
98
cb1 = plt.colorbar(cf1, cax=ax2, orientation='horizontal')
99
cb1.set_label(r'kts', size='x-large')
100
ax1.set_title('300-hPa Wind Speeds and Heights \nfor {0:%d %B %Y %H:%MZ}'.format(time_vals),
101
              fontsize=16)
102
103
# Upper right plot - 500mb absolute vorticity and geopotential heights
104
ax3 = plt.subplot(gs[0, 1], projection=crs)
105
plot_background(ax3)
106
cf2 = ax3.contourf(lon_2d, lat_2d, vort_500, cmap='BrBG', transform=ccrs.PlateCarree(),
107
                   zorder=0, norm=plt.Normalize(-32, 32), latlon=True)
108
c2 = ax3.contour(lon_2d, lat_2d, heights_500, colors='k', lw=2, transform=ccrs.PlateCarree())
109
plt.clabel(c2, fontsize=10, inline=1, inline_spacing=1, fmt='%i', rightside_up=True)
110
111
ax4 = plt.subplot(gs[1, 1])
112
cb2 = plt.colorbar(cf2, cax=ax4, orientation='horizontal')
113
cb2.set_label(r'$10^{-5}$ s$^{-1}$', size='x-large')
114
ax3.set_title('500-hPa Absolute Vorticity and Heights \n'
115
              'for {0:%d %B %Y %H:%MZ}'.format(time_vals), fontsize=16)
116
117
# Lower left plot - surface temperatures
118
ax5 = plt.subplot(gs[2, 0], projection=crs)
119
plot_background(ax5)
120
cf3 = ax5.contourf(lon_2d, lat_2d, surface_temp, cmap='YlOrRd',
121
                   transform=ccrs.PlateCarree(), zorder=0)
122
123
ax6 = plt.subplot(gs[3, 0])
124
cb3 = plt.colorbar(cf3, cax=ax6, orientation='horizontal')
125
cb3.set_label(r'$^o$F', size='x-large')
126
ax5.set_title('Surface Temperatures for {0:%d %B %Y %H:%MZ}'.format(time_vals), fontsize=16)
127
128
# Lower right plot - precipitable water entire atmosphere
129
ax7 = plt.subplot(gs[2, 1], projection=crs)
130
plot_background(ax7)
131
cf4 = plt.contourf(lon_2d, lat_2d, precip_water, cmap='Greens',
132
                   transform=ccrs.PlateCarree(), zorder=0)
133
134
ax8 = plt.subplot(gs[3, 1])
135
cb4 = plt.colorbar(cf4, cax=ax8, orientation='horizontal')
136
cb4.set_label(r'in.', size='x-large')
137
ax7.set_title('Precipitable Water for {0:%d %B %Y %H:%MZ}'.format(time_vals), fontsize=16)
138
139
# Display the plot
140
plt.show()
141