#!/usr/bin/env python # coding: utf-8 #
# #
Unidata Logo
# #

Using Python to get the latest NEXRAD Composite

#

Unidata Python Workshop

# #
#
# #
# #
Example Radar Image
# # Objective: Visualize the latest available reflectivity data composited data # # Steps involved: # - Construct the appropriate URL to get the latest data file # - Open the URL using netCDF4-python # - Read the basic metadata # - Create the appropriate CartoPy projection and plot the Radar Reflectivity # In[1]: # Set-up for notebook get_ipython().run_line_magic('matplotlib', 'inline') # Some needed imports import datetime as dt import matplotlib.pyplot as plt import matplotlib as mpl import cartopy import numpy as np from netCDF4 import Dataset from siphon.catalog import TDSCatalog from metpy.plots import ctables # ## Get the latest data URL, grab the metadata, and request the data # In[2]: # Get today's date... today = dt.datetime.utcnow() # ...and use that to assemble the URL and grab the catalog url = "http://thredds.ucar.edu/thredds/catalog/nexrad/composite/gini/n0r/1km/{}/catalog.xml".format(today.strftime("%Y%m%d")) cat = TDSCatalog(url) # Get the list of names of datasets names = list(cat.datasets.keys()) print(names[:15]) # In[3]: # sort, so that the last dataset is the latest names.sort() latest = names[-1] print(latest) # In[4]: # Grab the dataset for the latest latestDs = cat.datasets[latest] # In[5]: # Construct a NetCDF dataset using the OPeNDAP access URL dataset = Dataset(latestDs.access_urls['OPENDAP']) print(list(dataset.variables.keys())) # In[6]: dataset.variables['LambertConformal'].ncattrs() # In[7]: ################## # Projection fun # ################## # get basic info from the file regarding projection attributes # see the following for more info on projections as described here: # http://www.nco.ncep.noaa.gov/pmb/docs/on388/tableb.html#GRID218 # http://www.wmo.int/pages/prog/www/WDM/Guides/Guide-binary-2.html # [see LAMBERT CONFORMAL SECANT OR TANGENT CONE GRIDS] # http://www.unidata.ucar.edu/mailing_lists/archives/netcdf-java/2006/msg00006.html # [standard parallels in CDM] proj = dataset.variables['LambertConformal'] rsphere = proj.earth_radius # lat_0 : center of desired map domain (in degrees) [Basemap] # CDM : 'latitude_of_projection_origin' lat_0 = proj.latitude_of_projection_origin # lon_0 : center of desired map domain (in degrees) [Basemap] # CDM : 'longitude_of_central_meridian' lon_0 = proj.longitude_of_central_meridian # lat_1, lat_2 : 1st and second parallels [Basemap] # CDM : 'standard_parallel' - this attr contains both 1st and 2nd lat_1 = proj.standard_parallel print(lat_0, lon_0, lat_1, rsphere) # ## Grab the data # In[8]: # Used to subset the data xstride = 10 ystride = 10 # download x and y coords and convert them from km to m x = dataset.variables['x'][::xstride] * 1000. y = dataset.variables['y'][::ystride] * 1000. # Grab the reflectivity data. Mask values less than -30 dBz data = dataset.variables["Reflectivity"][0, 0::ystride, 0::xstride] data = np.ma.array(data, mask=data<=-30) # ## Create the Plot # In[10]: # Set up the projection for the LambertConformal projection we know we have lcc = cartopy.crs.LambertConformal(central_longitude=lon_0, central_latitude=lat_0, standard_parallels=(lat_0, lat_1)) # Create a large figure and axes with this projection fig = plt.figure(figsize=(24, 12)) ax = fig.add_subplot(1, 1, 1, projection=lcc) # Limit to the bounds of the data we have ax.set_extent([-129., -63., 22., 49.], cartopy.crs.Geodetic()) # Add some map features ax.stock_img() ax.coastlines(resolution='50m') ax.add_feature(cartopy.feature.NaturalEarthFeature(category='cultural', name='admin_1_states_provinces_lakes', scale='50m', facecolor='none')) ax.add_feature(cartopy.feature.BORDERS, linewidth='2', edgecolor='black') ax.gridlines() # Convert the time to text and add as the title time = dataset.variables["time"][:][0] / 1000. title = dt.datetime.fromtimestamp(time).isoformat() ax.set_title(title) # Plot the data as an image, using the x and y values we have as the extents of the image # NOTE: This assumes equal-spaced points cmap = ctables.registry.get_colortable('NWSReflectivityExpanded') norm = mpl.colors.Normalize(vmin=-35, vmax=80) cax = ax.imshow(data, extent=(x.min(), x.max(), y.min(), y.max()), cmap=cmap, norm=norm, origin="upper", transform=lcc) plt.colorbar(cax); # ## Exercise # Using what was done above, plot the digital hybrid reflectivity (DHR): # - Look at http://thredds.ucar.edu/thredds/catalog/nexrad/composite/gini/catalog.html # - Instead of plotting over all of the U.S., limit to an area of interest # - DHR was chosen to keep the colormap from the NWS the same. Can also look at: # - Echo Tops (EET) # - Digital VIL (DVL) # - Others in catalog # - ***Bonus points***: Plot the data into a new coordinate system, like Orthographic # In[ ]: