Skip to content

Commit 34d83ce

Browse files
committed
Cleanse examples/fcstmaps_axesgrid.py
1 parent 62e94a2 commit 34d83ce

File tree

1 file changed

+123
-98
lines changed

1 file changed

+123
-98
lines changed

examples/fcstmaps_axesgrid.py

Lines changed: 123 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,127 @@
1-
from __future__ import (absolute_import, division, print_function)
1+
"""Make a multi-panel plot from numerical weather forecast in NOAA OPeNDAP.
22
3-
from __future__ import unicode_literals
4-
# this example reads today's numerical weather forecasts
5-
# from the NOAA OpenDAP servers and makes a multi-panel plot.
6-
# This version demonstrates the use of the AxesGrid toolkit.
7-
import datetime as dt
3+
This version demonstrates the use of the AxesGrid toolkit.
4+
"""
5+
from __future__ import print_function
6+
7+
import netCDF4
88
import numpy as np
99
import matplotlib.pyplot as plt
10-
import sys
11-
import numpy.ma as ma
12-
from mpl_toolkits.basemap import Basemap, addcyclic
10+
from mpl_toolkits.basemap import Basemap
11+
from mpl_toolkits.basemap import addcyclic
1312
from mpl_toolkits.axes_grid1 import AxesGrid
14-
from netCDF4 import Dataset as NetCDFFile, num2date
15-
16-
17-
# today's date is default.
18-
if len(sys.argv) > 1:
19-
date = dt.datetime.strptime(sys.argv[1], "%Y%m%d")
20-
else:
21-
date = dt.datetime.today()
22-
23-
# set OpenDAP server URL.
24-
try:
25-
urlbase = "http://nomads.ncep.noaa.gov/dods/gfs_0p25/gfs%Y%m%d/gfs_0p25_00z"
26-
data = NetCDFFile(date.strftime(urlbase))
27-
except:
28-
msg = """
29-
opendap server not providing the requested data.
30-
Try another date by providing YYYYMMDD on command line."""
31-
raise IOError(msg)
32-
33-
# read lats,lons,times.
34-
35-
print(data.variables.keys())
36-
latitudes = data.variables['lat']
37-
longitudes = data.variables['lon']
38-
fcsttimes = data.variables['time']
39-
times = fcsttimes[0:6] # first 6 forecast times.
40-
ntimes = len(times)
41-
# convert times for datetime instances.
42-
fdates = num2date(times,units=fcsttimes.units,calendar='standard')
43-
# make a list of YYYYMMDDHH strings.
44-
verifdates = [fdate.strftime('%Y%m%d%H') for fdate in fdates]
45-
# convert times to forecast hours.
46-
fcsthrs = []
47-
for fdate in fdates:
48-
fdiff = fdate-fdates[0]
49-
fcsthrs.append(fdiff.days*24. + fdiff.seconds/3600.)
50-
print(fcsthrs)
51-
print(verifdates)
52-
lats = latitudes[:]
53-
nlats = len(lats)
54-
lons1 = longitudes[:]
55-
nlons = len(lons1)
56-
57-
# unpack 2-meter temp forecast data.
58-
59-
t2mvar = data.variables['tmp2m']
60-
61-
# create figure, set up AxesGrid.
62-
fig=plt.figure(figsize=(6,8))
63-
grid = AxesGrid(fig, [0.05,0.01,0.9,0.9],
64-
nrows_ncols=(3, 2),
65-
axes_pad=0.25,
66-
cbar_mode='single',
67-
cbar_pad=0.3,
68-
cbar_size=0.1,
69-
cbar_location='top',
70-
share_all=True,
71-
)
72-
73-
# create Basemap instance for Orthographic projection.
74-
m = Basemap(lon_0=-90,lat_0=60,projection='ortho')
75-
# add wrap-around point in longitude.
76-
t2m = np.zeros((ntimes,nlats,nlons+1),np.float32)
77-
for nt in range(ntimes):
78-
t2m[nt,:,:], lons = addcyclic(t2mvar[nt,:,:], lons1)
79-
# convert to celsius.
80-
t2m = t2m-273.15
81-
# contour levels
82-
clevs = np.arange(-30,30.1,2.)
83-
lons, lats = np.meshgrid(lons, lats)
84-
x, y = m(lons, lats)
85-
# make subplots.
86-
for nt,fcsthr in enumerate(fcsthrs):
87-
ax = grid[nt]
88-
m.ax = ax
89-
cs = m.contourf(x,y,t2m[nt,:,:],clevs,cmap=plt.cm.jet,extend='both')
90-
m.drawcoastlines(linewidth=0.5)
91-
m.drawcountries()
92-
m.drawparallels(np.arange(-80,81,20))
93-
m.drawmeridians(np.arange(0,360,20))
94-
# panel title
95-
ax.set_title('%d-h forecast valid '%fcsthr+verifdates[nt],fontsize=9)
96-
# figure title
97-
plt.figtext(0.5,0.95,
98-
"2-m temp (\N{DEGREE SIGN}C) forecasts from %s"%verifdates[0],
99-
horizontalalignment='center',fontsize=14)
100-
# a single colorbar.
101-
cbar = fig.colorbar(cs, cax=grid.cbar_axes[0], orientation='horizontal')
102-
plt.show()
13+
14+
15+
def main(date, verbose=True):
16+
"""Main function."""
17+
18+
# Open dataset from OPeNDAP URL.
19+
url = "http://nomads.ncep.noaa.gov/dods/gfs_0p25/gfs%Y%m%d/gfs_0p25_00z"
20+
try:
21+
data = netCDF4.Dataset(date.strftime(url), "r")
22+
if verbose:
23+
print("Data variables:")
24+
print(sorted(data.variables))
25+
except OSError as err:
26+
err.args = (err.args[0], "date not found in OPeNDAP server")
27+
raise
28+
29+
# Read lats, lons, and times.
30+
latitudes = data.variables["lat"]
31+
longitudes = data.variables["lon"]
32+
fcsttimes = data.variables["time"]
33+
times = fcsttimes[0:6] # First 6 forecast times.
34+
ntimes = len(times)
35+
36+
# Convert times for datetime instances.
37+
fdates = netCDF4.num2date(
38+
times, units=fcsttimes.units, calendar="standard")
39+
40+
# Make a list of YYYYMMDDHH strings.
41+
verifdates = [fdate.strftime("%Y%m%d%H") for fdate in fdates]
42+
if verbose:
43+
print("Forecast datetime strings:")
44+
print(verifdates)
45+
46+
# Convert times to forecast hours.
47+
fcsthrs = []
48+
for fdate in fdates:
49+
fdiff = fdate - fdates[0]
50+
fcsthrs.append(fdiff.days * 24. + fdiff.seconds / 3600.)
51+
if verbose:
52+
print("Forecast datetime hours:")
53+
print(fcsthrs)
54+
55+
# Unpack 2-meter temp forecast data.
56+
lats = latitudes[:]
57+
nlats = len(lats)
58+
lons1 = longitudes[:]
59+
nlons = len(lons1)
60+
t2mvar = data.variables["tmp2m"]
61+
62+
# Create Basemap instance for orthographic projection.
63+
bmap = Basemap(lon_0=-90, lat_0=60, projection="ortho")
64+
65+
# Add wrap-around point in longitude.
66+
t2m = np.zeros((ntimes, nlats, nlons + 1), np.float32)
67+
for nt in range(ntimes):
68+
t2m[nt, :, :], lons = addcyclic(t2mvar[nt, :, :], lons1)
69+
70+
# Convert to Celsius.
71+
t2m = t2m - 273.15
72+
73+
# Define contour levels.
74+
clevs = np.arange(-30, 30.1, 2.0)
75+
lons, lats = np.meshgrid(lons, lats)
76+
x, y = bmap(lons, lats)
77+
78+
# Create figure and AxesGrid instance.
79+
fig = plt.figure(figsize=(6, 8))
80+
grid = AxesGrid(
81+
fig,
82+
[0.05, 0.01, 0.9, 0.9],
83+
nrows_ncols=(3, 2),
84+
axes_pad=0.5,
85+
cbar_mode="single",
86+
cbar_pad=0.75,
87+
cbar_size=0.1,
88+
cbar_location="top",
89+
share_all=True)
90+
91+
# Make subplots.
92+
for nt, fcsthr in enumerate(fcsthrs):
93+
bmap.ax = grid[nt]
94+
cs = bmap.contourf(x, y, t2m[nt, :, :], clevs,
95+
cmap=plt.cm.jet, extend="both")
96+
bmap.drawcoastlines(linewidth=0.5)
97+
bmap.drawcountries()
98+
bmap.drawparallels(np.arange(-80, 81, 20))
99+
bmap.drawmeridians(np.arange(0, 360, 20))
100+
# Set panel title.
101+
bmap.ax.set_title(
102+
"%d-h forecast valid " % fcsthr + verifdates[nt], fontsize=9)
103+
104+
# Set figure title.
105+
plt.figtext(
106+
0.5, 0.95,
107+
"2-m temp (\N{DEGREE SIGN}C) forecasts from %s" % verifdates[0],
108+
horizontalalignment="center", fontsize=14)
109+
110+
# Draw a single colorbar.
111+
cax = grid.cbar_axes[0]
112+
fig.colorbar(cs, cax=cax, orientation="horizontal")
113+
plt.show()
114+
115+
116+
if __name__ == "__main__":
117+
118+
import sys
119+
import datetime as dt
120+
121+
# Parse input date (default: today).
122+
if len(sys.argv) > 1:
123+
dateobj = dt.datetime.strptime(sys.argv[1], "%Y%m%d")
124+
else:
125+
dateobj = dt.datetime.today()
126+
127+
sys.exit(main(dateobj, verbose=True))

0 commit comments

Comments
 (0)