Visualizations with Py-ART

First we'll import needed packages


In [ ]:
import pyart
from matplotlib import pyplot as plt
import numpy as np
import os
from datetime import datetime as dt

%matplotlib inline
print(pyart.__version__)

import warnings
warnings.simplefilter("ignore", category=DeprecationWarning)
#warnings.simplefilter('ignore')

The following function will not work with the original VM for the Short course. To use, install s3fs package (via conda or pip). It is a file system interface for AWS S3 buckets and provides a nice interface similar to unix/ftp command line arguments.


In [ ]:
def open_nexrad_file(filename, io='radx'):
    """
    Open file using pyart nexrad archive method.

    Parameters
    ----------
    filename: str
        Radar filename to open.
    io: str
        Py-ART open method. If radx then file is opened via Radx
        otherwise via native Py-ART function.
        Using Radx will handle split-cut sweeps
    """
    filename, zipped = try_file_gunzip(filename)
    if io.lower() == 'radx':
        radar = pyart.aux_io.read_radx(filename)
    else:
        radar = pyart.io.read_nexrad_archive(filename)
    if zipped:
        os.system('gzip {}'.format(filename))
    return radar

def get_latest_file(radar_id, bucket='noaa-nexrad-level2', engine='s3fs', io='radx'):
    """Return latest NEXRAD data file name."""
    try:
        import s3fs
        import tempfile
    
        s3conn = s3fs.S3FileSystem(anon=True)
        latest_year = os.path.join(
            bucket, os.path.basename(s3conn.ls(bucket)[-1]))
        latest_month = os.path.join(
            latest_year, os.path.basename(s3conn.ls(latest_year)[-1]))
        latest_day = os.path.join(
            latest_month, os.path.basename(s3conn.ls(latest_month)[-1]))
        s3key = s3conn.ls(os.path.join(latest_day, radar_id))[-1]

        path, filename = os.path.split(s3key)
        with tempfile.TemporaryFile() as temp88d:
            s3fs.get(s3key, temp88d)
        return open_nexrad_file(temp88d, io=io)
    except:
        print("Missing s3fs package, please install via conda or pip.")

Py-ART Colormaps

Retrieve the names of colormaps and the colormap list dictionary.

The colormaps are registered with matplotlib and can be accessed by inserting 'pyart_' in front of any name.


In [ ]:
cm_names = pyart.graph.cm._cmapnames
cms = pyart.graph.cm.cmap_d

In [ ]:
nrows = len(cm_names)
gradient = np.linspace(0, 1, 256)
gradient = np.vstack((gradient, gradient))

# Create a figure and axes instance
fig, axes = plt.subplots(nrows=nrows, figsize=(5,10))
fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.99)
axes[0].set_title('Py-Art Colormaps', fontsize=14)

# Loop through the possibilities
for nn, pymap in enumerate(cm_names):
    axes[nn].imshow(gradient, aspect='auto', cmap=cms[pymap])
    pos = list(axes[nn].get_position().bounds)
    x_text = pos[0] - 0.01
    y_text = pos[1] + pos[3]/2.
    fig.text(x_text, y_text, pymap, va='center', ha='right', fontsize=8)

# Turn off *all* ticks & spines, not just the ones with colormaps.
for ax in axes:
    ax.set_axis_off()

The RadarDisplay

This is the most commonly used class designed for surface-based scanning radar

Plot a NEXRAD file


In [ ]:
nexf = "data/KILN20140429_231254_V06"
nexr = pyart.io.read(nexf)
nexd = pyart.graph.RadarDisplay(nexr)

In [ ]:
nexr.fields.keys()

In [ ]:
fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(16, 12))
nexd.plot('reflectivity', sweep=1, cmap='pyart_NWSRef', vmin=0., vmax=55., mask_outside=False, ax=ax[0, 0])
nexd.plot_range_rings([50, 100], ax=ax[0, 0])
nexd.set_limits((-150., 150.), (-150., 150.), ax=ax[0, 0])

nexd.plot('velocity', sweep=1, cmap='pyart_NWSVel', vmin=-30, vmax=30., mask_outside=False, ax=ax[0, 1])
nexd.plot_range_rings([50, 100], ax=ax[0, 1])
nexd.set_limits((-150., 150.), (-150., 150.), ax=ax[0, 1])

nexd.plot('cross_correlation_ratio', sweep=0, cmap='pyart_BrBu12', vmin=0.85, vmax=1., mask_outside=False, ax=ax[1, 0])
nexd.plot_range_rings([50, 100], ax=ax[0, 1])
nexd.set_limits((-150., 150.), (-150., 150.), ax=ax[0, 1])

nexd.plot('differential_reflectivity', sweep=0, cmap='pyart_BuDOr12', vmin=-2, vmax=2., mask_outside=False, ax=ax[1, 1])
nexd.plot_range_rings([50, 100], ax=ax[1, 1])
nexd.set_limits((-150., 150.), (-150., 150.), ax=ax[1, 1])

There are many keyword values we can employe to refine the plot

Keywords exist for title, labels, colorbar, along with others. In addition, there are many methods that can be employed. For example, pull out a constructed RHI at a given azimuth.


In [ ]:
nexd.plot_azimuth_to_rhi('reflectivity', 305., cmap='pyart_NWSRef', vmin=0., vmax=55.)
nexd.set_limits((0., 150.), (0., 15.))

Py-ART RHI

Not only can we construct an RHI from a PPI volume, but RHI scans may be plotted as well.


In [ ]:
rhif = "data/noxp_rhi_140610232635.RAWHJFH"
rhir = pyart.io.read(rhif)
rhid = pyart.graph.RadarDisplay(rhir)

In [ ]:
rhid.plot_rhi('reflectivity', 0, vmin=-5.0, vmax=70,)
rhid.set_limits(xlim=(0, 50), ylim=(0, 15))

Py-ART RadarMapDisplay or RadarMapDisplayCartopy

This converts the x-y coordinates to latitude and longitude overplotting on a map

Let us see what version we have. The first is works on Py-ART which uses a standard definition. For other packages that may not the second method should work


In [ ]:
pyart_ver = pyart.__version__

import pkg_resources
pyart_ver2 = pkg_resources.get_distribution("arm_pyart").version

In [ ]:
if int(pyart_ver.split('.')[1]) == 8:
    print("8")
    nexmap = pyart.graph.RadarMapDisplayCartopy(nexr)
else:
    print("7")
    nexmap = pyart.graph.RadarMapDisplay(nexr)

In [ ]:
limits = [-87., -82., 37., 42.]
fig, ax = plt.subplots(1, 1, figsize=(7, 7))

nexmap.plot_ppi_map('reflectivity', sweep=1, vmin=0., vmax=55., ax=ax,
                    min_lon=limits[0], max_lon=limits[1], min_lat=limits[2], max_lat=limits[3])

Use what you have learned!

Using all that you have learned, make a two panel plot of reflectivity and doppler velocity using the data file from an RHI of NOXP data/noxp_rhi_140610232635.RAWHJFH. Use Cartopy to overlay the plots on a map of Austrailia and play around with differing colormaps and axes limits!


In [ ]:

Solution

The following cell loads a solution to the above problem.


In [ ]:
# %load solution.py

In [ ]: