Beam Block

Creating beamblock functions that use wradlib to retrieve PBB and CBB. beamblock flags are then created and the PBB, CBB and flags are converted into fields in an empty radar object.


In [839]:
import gdal
import osr
import numpy as np
import netCDF4
import re
import pyart
import wradlib as wrl

import matplotlib
import matplotlib.pyplot as plt
from matplotlib import animation
from mpl_toolkits.basemap import Basemap
from matplotlib import cm
from mpl_toolkits.basemap import Basemap

from IPython.display import Image, display
get_ipython().magic(
    'install_ext https://raw.github.com/cpcloud/ipython-\
autotime/master/autotime.py')
get_ipython().magic('load_ext autotime')


ERROR:root:Line magic function `%install_ext` not found.
The autotime extension is already loaded. To reload it, use:
  %reload_ext autotime
time: 8.48 ms

In [840]:
"""
pyart.retrieve.beam_block_calc
=======================================

Calculates partial beam block(PBB) and cumulative beam block(CBB)
by using wradlib's beamblock and geotiff functions. PBB and CBB
are then used to created flags when a certain beam block fraction
is passed. Empty radar object is created using Py-ART and then
is filled with beam block data.

.. autosummary::
    :toctreeL generated/
    :template: dev_template.rst

    beam_block
    empty_radar_beam_block_ppi
    beam_block_flag
    _arrays_to_dict
    _flags_to_dict

"""

import pyart
import numpy as np
import wradlib as wrl


def beam_block(radar, tif_name,
               beam_width=1.0):
    """
    Beam Block Calculation

    Parameters
    ----------
    radar : Radar
        Radar object used.
    tif_name : string
        Name of geotiff file to use for the
        calculation

    Other Parameters
    ----------------
    beam_width : float
        Radar's beam width for calculation.
        Default value is 1.0.

    Returns
    -------
    pbb : array
        Array of partial beam block fractions for each
        gate in each ray.
    cbb: array
        Array of cumulative beam block fractions for
        each gate in each ray.

    References
    ----------
    Bech, J., B. Codina, J. Lorente, and D. Bebbington,
    2003: The sensitivity of single polarization weather
    radar beam blockage correction to variability in the
    vertical refractivity gradient. J. Atmos. Oceanic
    Technol., 20, 845–855

    Heistermann, M., Jacobi, S., and Pfaff, T., 2013:
    Technical Note: An open source library for processing
    weather radar data (wradlib), Hydrol. Earth Syst.
    Sci., 17, 863-871, doi:10.5194/hess-17-863-2013
    
    Helmus, J.J. & Collis, S.M., (2016). The Python ARM
    Radar Toolkit (Py-ART), a Library for Working with
    Weather Radar Data in the Python Programming Language.
    Journal of Open Research Software. 4(1), p.e25.
    DOI: http://doi.org/10.5334/jors.119

    """

    radar.fields.clear()
    _range = radar.range['data']
    beamradius = wrl.util.half_power_radius(_range, beam_width)

    rasterfile = tif_name
    data_raster = wrl.io.open_raster(rasterfile)
    rastervalues, rastercoords, proj = wrl.georef.extract_raster_dataset(
        data_raster, nodata=None)
    sitecoords = (np.float(radar.longitude['data']),
                  np.float(radar.latitude['data']),
                  np.float(radar.altitude['data']))

    pbb_arrays = []
    cbb_arrays = []

    for i in range(len(radar.sweep_start_ray_index['data'])):
        index_start = radar.sweep_start_ray_index['data'][i]
        index_end = radar.sweep_end_ray_index['data'][i] + 1

        #nrays = index_end - index_start + 1
        #nbins = radar.ngates
        #range_res = (np.max(_range) - np.min(_range)) / (nbins - 1)
        #range_res = _range[1] - _range[0]
        #range_res = wrl.georef._get_range_resolution(_range)
        #elev = radar.fixed_angle['data'][i]
        elevs = radar.elevation['data'][index_start:index_end]
        azimuths = radar.azimuth['data'][index_start:index_end]
        rg, azg = np.meshgrid(_range, azimuths)
        rg, eleg = np.meshgrid(_range, elevs)
        lon, lat, alt = wrl.georef.polar2lonlatalt_n(
            rg, azg, eleg, sitecoords)

        #lon = radar.gate_longitude['data'][index_start:index_end +1]
        #lat = radar.gate_latitude['data'][index_start:index_end + 1]
        #alt = radar.gate_altitude['data'][index_start:index_end + 1]
        x_pol, y_pol = wrl.georef.reproject(
            lon, lat, projection_target=proj)
        polcoords = np.dstack((x_pol, y_pol))

        rlimits = (x_pol.min(), y_pol.min(), x_pol.max(), y_pol.max())
        ind = wrl.util.find_bbox_indices(rastercoords, rlimits)
        rastercoords = rastercoords[0:ind[3], ind[0]:ind[2], ...]
        rastervalues = rastervalues[0:ind[3], ind[0]:ind[2]]

        # Map rastervalues to polar grid points
        
    
        polarvalues = wrl.ipol.cart2irregular_spline(
            rastercoords, rastervalues, polcoords)

        pbb = wrl.qual.beam_block_frac(polarvalues, alt, beamradius)
        pbb = np.ma.masked_invalid(pbb)
        pbb_arrays.append(pbb)

        cbb = wrl.qual.cum_beam_block_frac(pbb)
        cbb_arrays.append(cbb)

    pbb_all = np.ma.concatenate(pbb_arrays)
    cbb_all = np.ma.concatenate(cbb_arrays)
    return pbb_all, cbb_all

def beam_block_flag(pbb_all, cbb_all, no_block_thresh=0.01,
                    complete_block_thresh=0.95):
    """ Takes PBB and CBB arrays created from the
    beam_block function and user chosen thresholds
    to create and array of 1s and 0s, 1 is a flagged gate
    where the fraction value is past the threshold. """
    pbb_flags = np.empty_like(pbb_all)
    pbb_flags[pbb_all > complete_block_thresh] = 2
    pbb_flags[(pbb_all > no_block_thresh) & (pbb_all < complete_block_thresh)] = 1
    pbb_flags[pbb_all < no_block_thresh] = 0
    
    cbb_flags = np.empty_like(cbb_all)
    cbb_flags[cbb_all > complete_block_thresh] = 2
    cbb_flags[(cbb_all > no_block_thresh) & (cbb_all < complete_block_thresh)] = 1
    cbb_flags[cbb_all < no_block_thresh] = 0
    return pbb_flags, cbb_flags

def empty_radar_beam_block_ppi(ngates, rays_per_sweep, nsweeps,
                               lon, lat, alt, range_start,
                               gate_space, elevations):
    """ Creates a radar object with no fields based on
    user inputed dimensions. The empty radar is to then
    be used to add PBB, CBB and the flags for both. """
    radar = pyart.testing.make_empty_ppi_radar(
        ngates, rays_per_sweep, nsweeps)
    radar.longitude['data'] = np.array([lon])
    radar.latitude['data'] = np.array([lat])
    radar.altitude['data'] = np.array([alt])
    radar.azimuth['data'] = np.linspace(0, 360, rays_per_sweep)
    radar.range['data'] = np.linspace(
        range_start, (ngates - 1)*gate_space + range_start, ngates)
    radar.fixed_angle['data'] = elevations
    radar.elevation['data'] = np.array([elevations] * rays_per_sweep)
    radar.metadata['instrument_name'] = 'beam_block_radar_object'
    return radar

def _arrays_to_dict(pbb_all, cbb_all):
    """ Function that takes the PBB and CBB arrays
    and turns them into dictionaries to be used and added
    to the pyart radar object. """
    pbb_dict = {}
    pbb_dict['coordinates'] = 'elevation, azimuth, range'
    pbb_dict['units'] = 'unitless'
    pbb_dict['data'] = pbb_all
    pbb_dict['standard_name'] = 'partial_beam_block'
    pbb_dict['long_name'] = 'Partial Beam Block Fraction'
    pbb_dict['comment'] = 'Partial beam block fraction due to terrain'

    cbb_dict = {}
    cbb_dict['coordinates'] = 'elevation, azimuth, range'
    cbb_dict['units'] = 'unitless'
    cbb_dict['data'] = cbb_all
    cbb_dict['standard_name'] = 'cumulative_beam_block'
    cbb_dict['long_name'] = 'Cumulative Beam Block Fraction'
    cbb_dict['comment'] = 'Cumulative beam block fraction due to terrain'
    return pbb_dict, cbb_dict

def _flags_to_dict(pbb_flags, cbb_flags):
    """ Function that takes the PBB_flag and CBB_flag
    arrays and turns them into dictionaries to be used
    and added to the pyart radar object. """
    pbb_flag_dict = {}
    pbb_flag_dict['units'] = 'unitless'
    pbb_flag_dict['data'] = pbb_flags
    pbb_flag_dict['standard_name'] = 'partial_beam_block_flags'
    pbb_flag_dict['long_name'] = 'Partial Beam Block Flags'
    pbb_flag_dict['notes'] = '0: No Blockage, 1: Partial Blockage,' \
                             ' 2: Complete Blockage'
    
    cbb_flag_dict = {}
    cbb_flag_dict['units'] = 'unitless'
    cbb_flag_dict['data'] = cbb_flags
    cbb_flag_dict['standard_name'] = 'cumulative_beam_block_flags'
    cbb_flag_dict['long_name'] = 'Cumulative Beam Block Flags'
    cbb_flag_dict['notes'] = '0: No Blockage, 1: Partial Blockage,' \
                             ' 2: Complete Blockage'
    return pbb_flag_dict, cbb_flag_dict


time: 168 ms

In [363]:
# Examples
# --------
# >>> import pyart
# >>> radar = pyart.io.read('radar_file.nc')
# >>> gatefilter = pyart.correct.GateFilter(radar)
# >>> beam_block = radar.fields['partial_beam_block_flag']['data']
# >>> gatefilter.exclude_beam_block(beam_block)

def exclude_beam_block(self, beam_block, exclude_masked=True, op='or'):
    """
    Exclude gates where a beam block is equal to True.

    Parameters
    ----------
    beam_block : numpy array
        Boolean numpy array with same shape as a field array.
    exclude_masked : bool, optional
        True to filter masked values in the specified mask if it is
        a masked array, False to include any masked values.
    op : {'and', 'or', 'new'}
        Operation to perform when merging the existing set of excluded
        gates with the excluded gates from the current operation.
        'and' will perform a logical AND operation, 'or' a logical OR,
        and 'new' will replace the existing excluded gates with the one
        generated here. 'or', the default for exclude methods, is
        typically desired when building up a set of conditions for
        excluding gates where the desired effect is to exclude gates which
        meet any of the conditions. 'and', the default for include
        methods, is typically desired when building up a set of conditions
        where the desired effect is to include gates which meet any of the
        conditions.  Note that the 'and' method MAY results in including
        gates which have previously been excluded because they were masked
        or invalid.

    """

    fdata = next(iter(self._radar.fields.values()))['data']
    if beam_block.shape != fdata.shape:
        raise ValueError("beam_block array must be the same size as a field.")
    marked = np.array(beam_block, dtype='bool')
    return self._merge(marked, op, exclude_masked)


time: 18.6 ms

In [859]:
# sitecoords = (-28.0257, 39.0916, 40.0)
elevations = np.array([0.5, 1.0, 2.0, 3.0, 4.0, 10.0, 11.0, 15.0,
                          20.0, 30.0, 40.0])
radar = empty_radar_beam_block_ppi(1800, 1090, 1, -28.0257,
                                39.0916, 40.0, 0, 10,
                                elevations=2.0)
tif_name = '/home/zsherman/beam_block/data/dtm_gra.tif'


time: 4.65 ms

In [84]:
elevations = np.array([0.5, 1.0, 2.0, 3.0, 4.0, 10.0, 11.0, 15.0,
                       20.0, 30.0, 40.0])
radar = empty_radar_beam_block_ppi(1832, 720, 1, -122.4959,
                                   48.1946, 195.0, 2125, 250,
                                   elevations=0.4833)
tif_name = '/home/zsherman/seattle.tif'


time: 5.02 ms

In [741]:
#pyart.io.write_cfradial(
#    '/home/zsherman/sample_radar.nc', radar)


time: 2.22 ms

In [860]:
pbb_all, cbb_all = beam_block(
    radar, tif_name, 1.0)


/home/zsherman/anaconda3/envs/gdal_jupyter/lib/python3.5/site-packages/wradlib/qual.py:205: RuntimeWarning: invalid value encountered in sqrt
  (a ** 2 * np.arcsin(y / a)) + (np.pi * a ** 2 / 2.)
/home/zsherman/anaconda3/envs/gdal_jupyter/lib/python3.5/site-packages/wradlib/qual.py:205: RuntimeWarning: divide by zero encountered in true_divide
  (a ** 2 * np.arcsin(y / a)) + (np.pi * a ** 2 / 2.)
/home/zsherman/anaconda3/envs/gdal_jupyter/lib/python3.5/site-packages/wradlib/qual.py:205: RuntimeWarning: invalid value encountered in arcsin
  (a ** 2 * np.arcsin(y / a)) + (np.pi * a ** 2 / 2.)
time: 4.42 s

In [861]:
print(pbb_all.max())
print(cbb_all.max())


0.999999974922
0.999999974922
time: 7.6 ms

In [744]:
pbb_all.shape


Out[744]:
(1090, 1800)
time: 1.69 ms

In [706]:
wrl.util.get_raster_origin(rastercoords)


Out[706]:
'upper'
time: 2.33 ms

In [698]:
pract = {}
pract['notes'] = '0: No Blockage, 1: Partial Blockage, 2: Complete Blockage'


time: 3.36 ms

In [699]:
for pair_str in pract['notes'].split(','):
    print(pair_str)
    pract.update({pair_str.split(':')[1]:int(pair_str.split(':')[0])})


0: No Blockage
 1: Partial Blockage
 2: Complete Blockage
time: 1.69 ms

In [700]:
pract


Out[700]:
{' Complete Blockage': 2,
 ' No Blockage': 0,
 ' Partial Blockage': 1,
 'notes': '0: No Blockage, 1: Partial Blockage, 2: Complete Blockage'}
time: 1.91 ms

In [511]:
tif_name = '/home/zsherman/beam_block/data/dtm_gra.tif'
sitecoords = (-28.0257, 39.0916, 40.0)
nrays = 1200
nbins = 1000
el = 2.0
bw = 1.0
range_res = 100.0

r = np.arange(nbins) * range_res
beamradius = wrl.util.half_power_radius(r, bw)

rasterfile = tif_name
data_raster = wrl.io.open_raster(rasterfile)
rastervalues, rastercoords, proj = wrl.georef.extract_raster_dataset(
    data_raster)
print('rastercoords.shape = ' ,rastercoords.shape)
print('rastervalues.shape = ', rastervalues.shape)
coord = wrl.georef.sweep_centroids(nrays, range_res, nbins, el)
lon, lat, alt = wrl.georef.polar2lonlatalt_n(
    coord[..., 0], np.degrees(coord[..., 1]),
    coord[..., 2], sitecoords)

x_pol, y_pol = wrl.georef.reproject(
    lon, lat, projection_target=proj)
polcoords = np.dstack((x_pol, y_pol))
    
rlimits = (x_pol.min(), y_pol.min(), x_pol.max(), y_pol.max())

# Clip the region inside our bounding box
ind = wrl.util.find_bbox_indices(rastercoords, rlimits)
print('ind = ', ind)
rastercoords = rastercoords[ind[1]:ind[3], ind[0]:ind[2], ...]
rastervalues = rastervalues[ind[1]:ind[3], ind[0]:ind[2]]
print('rastercoords values = ', rastercoords)
print('rastervalues values = ', rastervalues)
polarvalues = wrl.ipol.cart2irregular_spline(rastercoords, rastervalues,
                                             polcoords, order=3,
                                             prefilter=False)


rastercoords.shape =  (991, 1074, 2)
rastervalues.shape =  (990, 1073)
ind =  (0, 991, 1074, 991)
rastercoords values =  []
rastervalues values =  []
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-511-86ac8862a3e9> in <module>()
     35 polarvalues = wrl.ipol.cart2irregular_spline(rastercoords, rastervalues,
     36                                              polcoords, order=3,
---> 37                                              prefilter=False)

/home/zsherman/anaconda3/envs/gdal_jupyter/lib/python3.5/site-packages/wradlib/ipol.py in cart2irregular_spline(cartgrid, values, newgrid, **kwargs)
   1137     ny = cartgrid.shape[0]
   1138 
-> 1139     cxmin = np.min(cartgrid[..., 0])
   1140     cxmax = np.max(cartgrid[..., 0])
   1141     cymin = np.min(cartgrid[..., 1])

/home/zsherman/anaconda3/envs/gdal_jupyter/lib/python3.5/site-packages/numpy/core/fromnumeric.py in amin(a, axis, out, keepdims)
   2350 
   2351     return _methods._amin(a, axis=axis,
-> 2352                           out=out, **kwargs)
   2353 
   2354 

/home/zsherman/anaconda3/envs/gdal_jupyter/lib/python3.5/site-packages/numpy/core/_methods.py in _amin(a, axis, out, keepdims)
     27 
     28 def _amin(a, axis=None, out=None, keepdims=False):
---> 29     return umr_minimum(a, axis, None, out, keepdims)
     30 
     31 def _sum(a, axis=None, dtype=None, out=None, keepdims=False):

ValueError: zero-size array to reduction operation minimum which has no identity
time: 1.97 s

In [504]:
ind


Out[504]:
(0, 991, 1074, 991)
time: 2.39 ms

In [517]:
rastercoords.shape


Out[517]:
(990, 1073, 2)
time: 1.61 ms

In [518]:
rastervalues.shape


Out[518]:
(990, 1073)
time: 2.21 ms

In [506]:
ind


Out[506]:
(0, 0, 1073, 990)
time: 2.22 ms

In [862]:
pbb_flags, cbb_flags = beam_block_flag(
    pbb_all, cbb_all)


time: 38.8 ms
/home/zsherman/anaconda3/envs/gdal_jupyter/lib/python3.5/site-packages/ipykernel/__main__.py:145: RuntimeWarning: invalid value encountered in greater
/home/zsherman/anaconda3/envs/gdal_jupyter/lib/python3.5/site-packages/ipykernel/__main__.py:146: RuntimeWarning: invalid value encountered in greater
/home/zsherman/anaconda3/envs/gdal_jupyter/lib/python3.5/site-packages/ipykernel/__main__.py:146: RuntimeWarning: invalid value encountered in less
/home/zsherman/anaconda3/envs/gdal_jupyter/lib/python3.5/site-packages/ipykernel/__main__.py:147: RuntimeWarning: invalid value encountered in less

In [863]:
pbb_dict, cbb_dict = _arrays_to_dict(
    pbb_all, cbb_all)
pbb_flag_dict, cbb_flag_dict = _flags_to_dict(
    pbb_flags, cbb_flags)


time: 1.7 ms

In [864]:
radar.add_field('partial_beam_block',
                pbb_dict, replace_existing=True)
radar.add_field('cumulative_beam_block',
                cbb_dict, replace_existing=True)
radar.add_field('partial_beam_block_flags',
                pbb_flag_dict, replace_existing=True)
radar.add_field('cumulative_beam_block_flags',
                cbb_flag_dict, replace_existing=True)


time: 5.89 ms

In [865]:
pyart.io.write_cfradial(
    '/home/zsherman/flag_radar.nc', radar)


time: 761 ms
/home/zsherman/.local/lib/python3.5/site-packages/pyart/io/cfradial.py:706: UserWarning: Warning, converting non-array to array:fixed_angle
  warnings.warn("Warning, converting non-array to array:%s" % name)

In [866]:
bb_radar = pyart.io.read(
    '/home/zsherman/flag_radar.nc')


time: 356 ms

In [825]:
bb_radar.fields['cumulative_beam_block_flags']['data'].max()


Out[825]:
2.0
time: 4.19 ms

In [749]:
bb_radar = pyart.io.read(
    '/home/zsherman/beam_block/data/radar_object_pbb_cbb_all_sweeps')


time: 354 ms

In [850]:
bb_radar.fields['partial_beam_block']['data']


Out[850]:
masked_array(data =
 [[-- -- -- ..., -- -- --]
 [-- -- -- ..., -- -- --]
 [-- -- -- ..., -- -- --]
 ..., 
 [-- -- -- ..., -- -- --]
 [-- -- -- ..., -- -- --]
 [-- -- -- ..., -- -- --]],
             mask =
 [[ True  True  True ...,  True  True  True]
 [ True  True  True ...,  True  True  True]
 [ True  True  True ...,  True  True  True]
 ..., 
 [ True  True  True ...,  True  True  True]
 [ True  True  True ...,  True  True  True]
 [ True  True  True ...,  True  True  True]],
       fill_value = 9.96920996839e+36)
time: 3.56 ms

In [868]:
first_sweep = bb_radar.extract_sweeps([0])


time: 35.5 ms

In [869]:
first_sweep.azimuth['data'] = np.linspace(0, 360, 1090)


time: 1.38 ms

In [853]:
PBB = first_sweep.fields['partial_beam_block']['data']


time: 763 µs

In [649]:
mask = np.argwhere(PBB > 0.0)[:, 0]
mask


Out[649]:
array([354, 354, 354, ..., 857, 857, 858])
time: 15.5 ms

In [633]:
loc = np.argwhere(PBB > 0.01)
type(loc)


Out[633]:
numpy.ndarray
time: 29.6 ms

In [92]:
from collections import OrderedDict
list_two = list(OrderedDict.fromkeys(mask))


time: 1.39 ms

In [93]:
list_one = np.linspace(0, 360, 990)


time: 1.08 ms

In [94]:
list_three = list_one[list_two]


time: 688 µs

In [95]:
list_three_vals = [x for x in list_one if x not in list_three]


time: 3.15 ms

In [96]:
print(str(np.round(list_three_vals, decimals=3)))


[   0.       0.364    0.728    1.092    1.456    1.82     2.184    2.548
    2.912    3.276    3.64     4.004    4.368    4.732    5.096    5.46
    5.824    6.188    6.552    6.916    7.28     7.644    8.008    8.372
    8.736    9.1      9.464    9.828   10.192   10.556   10.92    11.284
   11.648   12.012   12.376   12.74    13.104   13.468   13.832   14.196
   14.56    14.924   15.288   15.652   16.016   16.38    16.744   17.108
   17.472   17.836   18.2     18.564   18.928   19.292   19.656   20.02
   20.384   20.748   21.112   21.476   21.84    22.204   22.568   22.932
   23.296   23.66    24.024   24.388   24.752   25.116   25.48    25.844
   26.208   26.572   26.936   27.3     27.664   28.028   28.392   28.756
   29.12    29.484   29.848   30.212   30.576   30.94    31.304   31.668
   32.032   32.396   32.76    33.124   33.488   33.852   34.216   34.58
   34.944   35.308   35.672   36.036   36.4     36.764   37.128   37.492
   37.856   38.22    38.584   38.948   39.312   39.676   40.04    40.404
   40.768   41.132   41.496   41.86    42.224   42.588   42.952   43.316
   43.68    44.044   44.408   44.772   45.137   45.501   45.865   46.229
   46.593   46.957   47.321   47.685   48.049   48.413   48.777   49.141
   49.505   49.869   50.233   50.597   50.961   51.325   51.689   52.053
   52.417   52.781   53.145   53.509   53.873   54.237   54.601   54.965
   55.329   55.693   56.057   56.421   56.785   57.149   57.513   57.877
   58.241   58.605   58.969   59.333   59.697   60.061   60.425   60.789
   61.153   61.517   61.881   62.245   62.609   62.973   63.337   63.701
   64.065   64.429   64.793   65.157   65.521   65.885   66.249   66.613
   66.977   67.341   67.705   68.069   68.433   68.797   69.161   69.525
   69.889   70.253   70.617   70.981   71.345   71.709   72.073   72.437
   72.801   73.165   73.529   73.893   74.257   74.621   74.985   75.349
   75.713   76.077   76.441   76.805   77.169   77.533   77.897   78.261
   78.625   78.989   79.353   79.717   80.081   80.445   80.809   81.173
   81.537   81.901   82.265   82.629   82.993   83.357   83.721   84.085
   84.449   84.813   85.177   85.541   85.905   86.269   86.633   86.997
   87.361   87.725   88.089   88.453   88.817   89.181   89.545   89.909
   90.273   90.637   91.001   91.365   91.729   92.093   92.457   92.821
   93.185   93.549   93.913   94.277   94.641   95.005   95.369   95.733
   96.097   96.461   96.825   97.189   97.553   97.917   98.281   98.645
   99.009   99.373   99.737  100.101  100.465  100.829  101.193  101.557
  101.921  102.285  102.649  103.013  103.377  103.741  104.105  104.469
  104.833  105.197  105.561  105.925  106.289  106.653  107.017  107.381
  107.745  108.109  108.473  108.837  109.201  109.565  109.929  110.293
  110.657  111.021  111.385  111.749  112.113  112.477  112.841  113.205
  113.569  113.933  114.297  114.661  115.025  115.389  115.753  116.117
  116.481  116.845  117.209  117.573  124.489  124.853  125.217  125.581
  125.945  208.938  209.302  209.666  210.03   210.394  210.758  211.122
  211.486  211.85   212.214  212.578  212.942  213.306  213.67   214.034
  214.398  214.762  215.126  215.49   215.854  216.218  216.582  216.946
  217.31   217.674  218.038  218.402  218.766  219.13   219.494  219.858
  220.222  233.327  233.691  234.055  234.419  234.783  235.147  235.511
  235.875  236.239  236.603  236.967  237.331  237.695  238.059  238.423
  238.787  239.151  239.515  239.879  240.243  240.607  240.971  241.335
  241.699  242.063  242.427  242.791  243.155  243.519  243.883  244.247
  244.611  244.975  245.339  245.703  246.067  246.431  246.795  247.159
  247.523  247.887  248.251  248.615  248.979  249.343  249.707  250.071
  250.435  250.799  251.163  251.527  251.891  252.255  252.619  252.983
  253.347  253.711  254.075  254.439  254.803  255.167  255.531  255.895
  256.259  256.623  256.987  257.351  257.715  258.079  258.443  258.807
  259.171  259.535  259.899  260.263  260.627  260.991  261.355  261.719
  262.083  262.447  262.811  263.175  263.539  263.903  264.267  264.631
  264.995  265.359  265.723  266.087  266.451  266.815  267.179  267.543
  267.907  268.271  268.635  268.999  269.363  269.727  270.091  270.455
  270.819  271.183  271.547  271.911  272.275  272.639  273.003  273.367
  273.731  274.095  274.459  274.823  275.187  275.551  275.915  276.279
  276.643  277.007  277.371  277.735  278.099  278.463  278.827  279.191
  279.555  279.919  280.283  280.647  281.011  281.375  281.739  283.559
  283.923  284.287  284.651  285.015  285.379  285.743  286.107  286.471
  286.835  287.199  287.563  287.927  288.291  288.655  289.019  289.383
  289.747  290.111  290.475  290.839  291.203  291.567  291.931  292.295
  292.659  293.023  293.387  293.751  294.115  294.479  294.843  295.207
  295.571  295.935  296.299  296.663  297.027  297.391  297.755  298.119
  298.483  298.847  299.211  299.575  299.939  300.303  300.667  301.031
  301.395  301.759  302.123  302.487  302.851  303.215  303.579  303.943
  304.307  304.671  305.035  305.399  305.763  306.127  306.491  306.855
  307.219  307.583  307.947  308.311  308.675  309.039  309.403  309.767
  310.131  310.495  310.859  311.223  311.587  311.951  312.315  312.679
  313.043  313.407  313.771  314.135  314.499  314.863  315.228  315.592
  315.956  316.32   316.684  317.048  317.412  317.776  318.14   318.504
  318.868  319.232  319.596  319.96   320.324  320.688  321.052  321.416
  321.78   322.144  322.508  322.872  323.236  323.6    323.964  324.328
  324.692  325.056  325.42   325.784  326.148  326.512  326.876  327.24
  327.604  327.968  328.332  328.696  329.06   329.424  329.788  330.152
  330.516  330.88   331.244  331.608  331.972  332.336  332.7    333.064
  333.428  333.792  334.156  334.52   334.884  335.248  335.612  335.976
  336.34   336.704  337.068  337.432  337.796  338.16   338.524  338.888
  339.252  339.616  339.98   340.344  340.708  341.072  341.436  341.8
  342.164  342.528  342.892  343.256  343.62   343.984  344.348  344.712
  345.076  345.44   345.804  346.168  346.532  346.896  347.26   347.624
  347.988  348.352  348.716  349.08   349.444  349.808  350.172  350.536
  350.9    351.264  351.628  351.992  352.356  352.72   353.084  353.448
  353.812  354.176  354.54   354.904  355.268  355.632  355.996  356.36
  356.724  357.088  357.452  357.816  358.18   358.544  358.908  359.272
  359.636  360.   ]
time: 12.8 ms

In [97]:
# az_strings = (first_sweep.azimuth['data'][list_three_vals])
az_strings = list_three_vals


time: 965 µs

In [98]:
new_string = np.array(np.round(az_strings, decimals=3))


time: 1.44 ms

In [99]:
string = (', '.join([str(x) for x in new_string]))


time: 1.77 ms

In [100]:
spl = string.split(",")
new_fig_text = (','"\n".join([",".join(spl[i:i+15]) for i in range(0, len(spl), 15)]))


time: 1.74 ms

In [101]:
PBB = first_sweep.fields['partial_beam_block']['data']
CBB = first_sweep.fields['cumulative_beam_block']['data']
r = first_sweep.range['data']
az = first_sweep.azimuth['data']
el = first_sweep.azimuth['data']
azimuths = first_sweep.azimuth['data']
fig = plt.figure(figsize=(14, 9))
ax, dem = wrl.vis.plot_ppi(PBB, r=r,
                           az=az,
                           cmap=plt.cm.PuRd)
ax.set_xlim(-8000, 10000)
ax.set_ylim(-12000, 5000)
ax.plot(0, 0, 'ro', )
for az_string in az_strings:
    ax.plot(
        [0, np.sin(np.radians(az_string))*1e5],
        [0, np.cos(np.radians(az_string))*1e5],
        "r-", linewidth=0.2)

ax.grid(True)
ax.annotate('  ARM ENA Site', (r[0], az[1]))
ticks = (ax.get_xticks()/1000).astype(np.int)
ax.set_xticklabels(ticks)
ticks = (ax.get_yticks()/1000).astype(np.int)
ax.set_yticklabels(ticks)
ax.set_title('Partial Beam Block 0.5 Degrees Elevation')
ax.set_xlabel("Kilometers")
ax.set_ylabel("Kilometers")
ax.set_axis_bgcolor('#E0E0E0')
plt.colorbar(dem, ax=ax)
plt.figtext(.85, .04, ('Azimuths No Blockage:\n ' + new_fig_text))
plt.savefig(
    '/home/zsherman/beam_block/images/graciaso_0.5elev_azimuths_no_blockage.png',
    bbox_inches='tight')
plt.show()


time: 4.92 s

In [559]:
def convertXY(xy_source, inproj, outproj):
    # function to convert coordinates

    shape = xy_source[0, :, :].shape
    size = xy_source[0, :, :].size

    # the ct object takes and returns pairs of x,y, not 2d grids
    # so the the grid needs to be reshaped (flattened) and back.
    ct = osr.CoordinateTransformation(inproj, outproj)
    xy_target = np.array(ct.TransformPoints(xy_source.reshape(2, size).T))

    xx = xy_target[:, 0].reshape(shape)
    yy = xy_target[:, 1].reshape(shape)

    return xx, yy


time: 20.7 ms

In [870]:
ds = gdal.Open("/home/zsherman/beam_block/data/dtm_gra.tif")

data = ds.ReadAsArray()
gt = ds.GetGeoTransform()
proj = ds.GetProjection()


xres = gt[1]
yres = gt[5]

# get the edge coordinates and add half the resolution 
# to go to center coordinates
xmin = gt[0] + xres * 0.5
xmax = gt[0] + (xres * ds.RasterXSize) - xres * 0.5
ymin = gt[3] + (yres * ds.RasterYSize) + yres * 0.5
ymax = gt[3] - yres * 0.5

ds = None

# create a grid of xy coordinates in the original projection
xy_source = np.mgrid[xmin:xmax+xres:xres, ymax+yres:ymin:yres]


time: 71.7 ms

In [871]:
llcrnrlat=39
urcrnrlon=-27.9
llcrnrlon=-28.1
urcrnrlat=39.1
lats = np.arange(llcrnrlat, urcrnrlat, .04)
lons = np.arange(llcrnrlon, urcrnrlon, .04)

fig = plt.figure(figsize=(12, 7))
m = Basemap(projection='lcc', lon_0=-28, lat_0=39, resolution='c', 
            llcrnrlon=llcrnrlon, llcrnrlat=llcrnrlat,
            urcrnrlon=urcrnrlon, urcrnrlat=urcrnrlat)

inproj = osr.SpatialReference()
inproj.ImportFromWkt(proj)
# Get the target projection from the basemap object
outproj = osr.SpatialReference()
outproj.ImportFromProj4(m.proj4string)

# Convert from source projection to basemap projection
xx, yy = convertXY(xy_source, inproj, outproj)

elev = data.T
the_sea = data.T < 0.1
masked_data = np.ma.masked_where(the_sea, elev)


time: 1.35 s

In [874]:
title = 'Cumulative Beam Blockage Over Terrain 2.0 Degree Elevation'
fig = plt.figure(figsize=(14, 7))
my_display = pyart.graph.RadarMapDisplay(first_sweep)

my_display.plot_ppi_map('cumulative_beam_block', basemap=m,
                       lat_lines=lats, lon_lines=lons,
                       vmin=0, vmax=1, cmap=plt.cm.PuRd,
                       title=title)
my_display.plot_point(-28.0257, 39.0916,
                    symbol='ro')
plt.annotate('ARM ENA Site', m(-28.0217, 39.0916), color='k')
CS = m.contour(xx, yy, masked_data,
               levels=np.arange(0, 400, 100),
               linewidths=1, cmap=plt.cm.terrain)

plt.clabel(CS, inline=1, fontsize=10, fmt='%1.0f')
plt.savefig(
    '/home/zsherman/beam_block/images/cbb_graciosa_contour.png',
    bbox_inches='tight')
plt.show()


time: 3.74 s

In [890]:
ticks = ([0.33, 1, 1.67])
ticklabs = (['No\nBlockage', 'Partial\nBlockage', 'Complete\nBlockage'])
title = 'Partial Beam Blockage Flag 2.0 Degree Elevation'
fig = plt.figure(figsize=(14, 7))
my_display = pyart.graph.RadarMapDisplay(first_sweep)
lab_colors=['grey','yellow', 'red']
cmap = matplotlib.colors.ListedColormap(lab_colors)
my_display.plot_ppi_map('partial_beam_block_flags', basemap=m,
                        lat_lines=lats, lon_lines=lons,
                        cmap=cmap, title=title, ticklabs=ticklabs,
                        ticks=ticks)
my_display.plot_point(-28.0257, 39.0916,
                    symbol='ro')
plt.annotate('ARM ENA Site', m(-28.0217, 39.0916), color='k')
CS = m.contour(xx, yy, masked_data,
               levels=np.arange(0, 400, 100),
               linewidths=1, cmap=plt.cm.terrain)

plt.clabel(CS, inline=1, fontsize=10, fmt='%1.0f')
plt.savefig(
    '/home/zsherman/beam_block/images/pbb_flag_2degree_elev.png',
    bbox_inches='tight')
plt.show()


time: 3.62 s

In [889]:
title = 'Cumulative Beam Blockage Flag 2.0 Degree Elevation'
fig = plt.figure(figsize=(14, 7))
my_display = pyart.graph.RadarMapDisplay(first_sweep)
lab_colors=['grey','yellow', 'red']
cmap = matplotlib.colors.ListedColormap(lab_colors)
my_display.plot_ppi_map('cumulative_beam_block_flags', basemap=m,
                        lat_lines=lats, lon_lines=lons,
                        cmap=cmap, title=title, ticklabs=ticklabs,
                        ticks=ticks)
my_display.plot_point(-28.0257, 39.0916,
                    symbol='ro')
plt.annotate('ARM ENA Site', m(-28.0217, 39.0916), color='k')
CS = m.contour(xx, yy, masked_data,
               levels=np.arange(0, 400, 100),
               linewidths=1, cmap=plt.cm.terrain)

plt.clabel(CS, inline=1, fontsize=10, fmt='%1.0f')
plt.savefig(
    '/home/zsherman/beam_block/images/cbb_flag_2degree_elev.png',
    bbox_inches='tight')
plt.show()


time: 3.57 s

In [558]:
tif_name = '/home/zsherman/beam_block/data/dtm_gra.tif
elevations = np.array([0.0, 0.5, 1.0, 2.0, 3.0, 4.0, 5.0, 10.0])
radars = []
for elevation in elevations:
    radar = empty_radar_beam_block_ppi(
        1800, 1090, 1, -28.0257, 39.0916, 40.0, 0, 10,
        elevations=elevation)
    pbb_all, cbb_all = beam_block(
    radar, tif_name, 1.0)
    pbb_dict, cbb_dict = _arrays_to_dict(
    pbb_all, cbb_all)
    radar.add_field('partial_beam_block',
                    pbb_dict, replace_existing=True)
    radar.add_field('cumulative_beam_block',
                    cbb_dict, replace_existing=True)
    radar.azimuth['data'] = np.linspace(0, 360, 1090)
    radars += [radar]


/home/zsherman/anaconda3/envs/gdal_jupyter/lib/python3.5/site-packages/wradlib/qual.py:205: RuntimeWarning: invalid value encountered in sqrt
  (a ** 2 * np.arcsin(y / a)) + (np.pi * a ** 2 / 2.)
/home/zsherman/anaconda3/envs/gdal_jupyter/lib/python3.5/site-packages/wradlib/qual.py:205: RuntimeWarning: divide by zero encountered in true_divide
  (a ** 2 * np.arcsin(y / a)) + (np.pi * a ** 2 / 2.)
/home/zsherman/anaconda3/envs/gdal_jupyter/lib/python3.5/site-packages/wradlib/qual.py:205: RuntimeWarning: invalid value encountered in arcsin
  (a ** 2 * np.arcsin(y / a)) + (np.pi * a ** 2 / 2.)
time: 34 s

In [560]:
llcrnrlat=39
urcrnrlon=-27.9
llcrnrlon=-28.1
urcrnrlat=39.1
lats = np.arange(llcrnrlat, urcrnrlat, .02)
lons = np.arange(llcrnrlon, urcrnrlon, .04)


time: 8.07 ms

In [561]:
m = Basemap(projection='lcc', lon_0=-28, lat_0=39, resolution='c', 
           llcrnrlon=llcrnrlon, llcrnrlat=llcrnrlat,
            urcrnrlon=urcrnrlon, urcrnrlat=urcrnrlat)


time: 226 ms

In [578]:
def animate(nframe):
    plt.clf()
    title = 'Partial Beam Block ' + str(radars[nframe].fixed_angle['data']) + ' Degrees Elevation'
    ax.set_axis_bgcolor('#E0E0E0')
    display = pyart.graph.RadarMapDisplay(radars[nframe])
    display.plot_ppi_map('partial_beam_block', resolution='l',
                         vmin=0, vmax=1, basemap=m, lat_lines=lats,
                         lon_lines=lons, cmap=plt.cm.PuRd, title=title)
    display.plot_point(-28.0257, 39.0916,
                       symbol='ro')
    plt.annotate('ARM ENA Site', m(-28.0217, 39.0916), color='k')
    
    CS = m.contour(xx, yy, masked_data,
                   levels=np.arange(0, 400, 100),
                   linewidths=1, cmap=plt.cm.terrain)

    plt.clabel(CS, inline=1, fontsize=10, fmt='%1.0f')
fig = plt.figure(figsize=(15, 7))
anim = animation.FuncAnimation(fig, animate, frames=len(radars))
anim.save('/home/zsherman/pbb_graciosa_animation.gif',
          writer='imagemagick', fps=1)
plt.close()


time: 14.4 s

In [579]:
def animate(nframe):
    plt.clf()
    title = 'Cumulative Beam Block ' + str(radars[nframe].fixed_angle['data']) + ' Degrees Elevation'
    ax.set_axis_bgcolor('#E0E0E0')
    display = pyart.graph.RadarMapDisplay(radars[nframe])
    display.plot_ppi_map('cumulative_beam_block', resolution='l',
                         vmin=0, vmax=1, basemap=m, lat_lines=lats,
                         lon_lines=lons, cmap=plt.cm.PuRd, title=title)
    display.plot_point(-28.0257, 39.0916,
                       symbol='ro')
    plt.annotate('ARM ENA Site', m(-28.0217, 39.0916), color='k')
    CS = m.contour(xx, yy, masked_data,
                   levels=np.arange(0, 400, 100),
                   linewidths=1, cmap=plt.cm.terrain)

    plt.clabel(CS, inline=1, fontsize=10, fmt='%1.0f')
fig = plt.figure(figsize=(15, 7))
anim = animation.FuncAnimation(fig, animate, frames=len(radars))
anim.save('/home/zsherman/cbb_graciosa_animation.gif',
          writer='imagemagick', fps=1)
plt.close()


time: 14.4 s

In [ ]: