Grid QC’d Dataset - Surface QUantitatIve pRecipitation Estimation (SQUIRE)#

Imports#

import pyart
import matplotlib.pyplot as plt
import numpy as np
import glob
from pathlib import Path
## You are using the Python ARM Radar Toolkit (Py-ART), an open source
## library for working with weather radar data. Py-ART is partly
## supported by the U.S. Department of Energy as part of the Atmospheric
## Radiation Measurement (ARM) Climate Research Facility, an Office of
## Science user facility.
##
## If you use this software to prepare a publication, please cite:
##
##     JJ Helmus and SM Collis, JORS 2016, doi: 10.5334/jors.119
ERROR 1: PROJ: proj_create_from_database: Open of /ccsopen/home/mgrover/mgrover/sail-radar-dev/share/proj failed

Retrieve List of Files (QC’d Data)#

files = sorted(glob.glob("/gpfs/wolf/atm124/proj-shared/gucxprecipradarcmacM1.c1/ppi/202203/gucxprecipradarcmacM1.c1.20220314-03*"))

Load Data into Py-ART and Plot#

radar = pyart.io.read(files[0])
display = pyart.graph.RadarDisplay(radar)
fig = plt.figure(figsize=[5, 5])
ax = fig.add_subplot(111)
display.plot('snow_rate_ws88diw',
             0,
             vmin=0,
             vmax=50,
             title="PPI",
             cmap='pyart_HomeyerRainbow')
plt.xlim(-20, 20)
plt.ylim(-20, 20)
(-20.0, 20.0)
../_images/40eb2fbdbabc232e7116fe13fb4b28cd259993b0b3dd0532011c3b259c3bb642.png

Grid Using Nearest Neighbor Interpolation#

Setup a Helper Function and Configure our Grid#

def compute_number_of_points(extent, resolution):
    """
    Create a helper function to determine number of points
    """
    return int((extent[1] - extent[0])/resolution)

# Grid extents in meters
z_grid_limits = (500.,5_000.)
y_grid_limits = (-20_000.,20_000.)
x_grid_limits = (-20_000.,20_000.)

# Grid resolution in meters
grid_resolution = 250

Once we setup our interpolation, we can compute the number of points for each extent

x_grid_points = compute_number_of_points(x_grid_limits, grid_resolution)
y_grid_points = compute_number_of_points(y_grid_limits, grid_resolution)
z_grid_points = compute_number_of_points(z_grid_limits, grid_resolution)

print(z_grid_points,
      y_grid_points,
      x_grid_points)
18 160 160

Create our Grid using grid_from_radars#

grid = pyart.map.grid_from_radars(radar,
                                  grid_shape=(z_grid_points,
                                              y_grid_points,
                                              x_grid_points),
                                  grid_limits=(z_grid_limits,
                                               y_grid_limits,
                                               x_grid_limits),
                                  method='nearest'
                                 )

Visualize our Grid#

We start by converting our grid to xarray

ds = grid.to_xarray()
ds.snow_rate_ws88diw.isel(z=0).plot(x='lon',
                                    y='lat',
                                    vmin=0, 
                                    vmax=50,
                                    cmap='pyart_HomeyerRainbow')
<matplotlib.collections.QuadMesh at 0x7f33c6f78eb0>
../_images/10a972f9aa3cf2294d399406417920b4be7dd42bd67646a7cf7cbb7af2244466.png

Determine the Lowest Height in Each Column#

We plotted the lowest level (500 m) in the plot above. It would be more helpful to have data from the lowest data point (lowest z) in each column (across time, latitude, and longitude)

We start first by creating a new field in our dataset, height_expanded, which is a four-dimensional (time, z, x, y) vertical coordinate, with nan values where we have missing snow rate values.

ds["height_expanded"] = (ds.z * (ds.snow_rate_ws2012/ds.snow_rate_ws2012)).fillna(10_000)

Next, we find the index of the lowest value in this column, using the .argmin method, looking over the column (z)

min_index = ds.height_expanded.argmin(dim='z',
                                      skipna=True)

Here is a plot of the lowest value height in the column for our domain:

**Notice how some values are the top of the column - 5000 m, whereas some of the values are close lowest vertical level, 500 m

ds.height_expanded.isel(z=min_index).plot(vmin=500,
                                          vmax=5000);
../_images/dae92e94f404a9598bda60bc231c41cfc6c359493c072ae3bba3ac5cbe90fc79.png

Apply this to our snow fields#

We first check for snow fields in our dataset, by using the following list comprehension line:

snow_fields = [var for var in list(ds.variables) if "snow" in var]
snow_fields
['snow_rate_ws88diw',
 'snow_rate_m2009_1',
 'snow_rate_m2009_2',
 'snow_rate_ws2012']

Next, we subset our dataset for only these fields and select our lowest z value (using the index we built before)

subset_ds = ds[snow_fields].isel(z=min_index)

Visualize our closest-to-ground snow value#

Now that we have the lowest vertical level in each column, let’s plot our revised maps, which only have dimensions:

  • time

  • latitude

  • longitude

for snow_field in snow_fields:
    subset_ds[snow_field].plot(x='lon',
                               y='lat',
                               cmap='pyart_HomeyerRainbow')
    plt.show()
    plt.close()
../_images/df34c8bdccb9b4cf34ad3caca510fcd49de3895b4feabcb9f9ab4de2175cf9d0.png ../_images/df34c8bdccb9b4cf34ad3caca510fcd49de3895b4feabcb9f9ab4de2175cf9d0.png ../_images/551e2edb7da7732d247edd1f65d403a46d250e0f2d4d888aedd9bc1391fa3321.png ../_images/c0a934f0b0ad860a55bc51c313b38d36bf32a039bd6af71dd5177307ea0bd251.png

Wrap this Up into a Function#

Now that we have the full pipeline, let’s wrap this into a function!

def grid_radar(file,
               x_grid_limits=(-20_000.,20_000.),
               y_grid_limits=(-20_000.,20_000.),
               z_grid_limits = (500.,5_000.),
               grid_resolution = 250,
               
               ):
    """
    Grid the radar using some provided parameters
    """
    
    radar = pyart.io.read(file)
    
    x_grid_points = compute_number_of_points(x_grid_limits, grid_resolution)
    y_grid_points = compute_number_of_points(y_grid_limits, grid_resolution)
    z_grid_points = compute_number_of_points(z_grid_limits, grid_resolution)
    
    grid = pyart.map.grid_from_radars(radar,
                                      grid_shape=(z_grid_points,
                                                  y_grid_points,
                                                  x_grid_points),
                                      grid_limits=(z_grid_limits,
                                                   y_grid_limits,
                                                   x_grid_limits),
                                      method='nearest'
                                     )
    return grid.to_xarray()

def subset_lowest_vertical_level(ds, additional_fields=["corrected_reflectivity"]):
    """
    Filter the dataset based on the lowest vertical level
    """
    snow_fields = [var for var in list(ds.variables) if "snow" in var] + additional_fields
    
    # Create a new 4-d height field
    ds["height_expanded"] = (ds.z * (ds[snow_fields[0]]/ds[snow_fields[0]])).fillna(5_000)
    
    # Find the minimum height index
    min_index = ds.height_expanded.argmin(dim='z',
                                          skipna=True)
    
    # Subset our snow fields based on this new index
    subset_ds = ds[snow_fields].isel(z=min_index)
    
    return subset_ds

Loop Through and Apply this Workflow#

Now that we have our helper functions, we can apply our workflow to each file.

for file in files:
    ds = grid_radar(file)
    out_ds = subset_lowest_vertical_level(ds)
    
    # Create an output path
    out_path = f"gridded-for-dan/{Path(file).stem}.gridded.nc"
    out_ds.to_netcdf(out_path)
    print("Finished writing:", out_path)
Finished writing: gridded-for-dan/gucxprecipradarcmacM1.c1.20220314-030920.gridded.nc
Finished writing: gridded-for-dan/gucxprecipradarcmacM1.c1.20220314-032520.gridded.nc
Finished writing: gridded-for-dan/gucxprecipradarcmacM1.c1.20220314-033040.gridded.nc
Finished writing: gridded-for-dan/gucxprecipradarcmacM1.c1.20220314-033600.gridded.nc
Finished writing: gridded-for-dan/gucxprecipradarcmacM1.c1.20220314-034120.gridded.nc
Finished writing: gridded-for-dan/gucxprecipradarcmacM1.c1.20220314-034640.gridded.nc
Finished writing: gridded-for-dan/gucxprecipradarcmacM1.c1.20220314-035720.gridded.nc