Skip to content

Commit 62e94a2

Browse files
committed
Cleanse examples/fcstmaps.py
1 parent 4824629 commit 62e94a2

File tree

1 file changed

+110
-87
lines changed

1 file changed

+110
-87
lines changed

examples/fcstmaps.py

Lines changed: 110 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,113 @@
1-
from __future__ import (absolute_import, division, print_function)
1+
"""Make a multi-panel plot from numerical weather forecast in NOAA OPeNDAP."""
2+
from __future__ import print_function
23

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

0 commit comments

Comments
 (0)