Beispiel #1
0
def polar_coords_to_latlon(radar, sweep_number):
    """Function under construction, not currently used"""
    # Radar location needed to get lat/lon of every gate
    klat, klon, klatr, klonr = get_radar_latlon_plus_radians(radar)

    # Initialize information on sweep geometry
    sweep_sw = get_sweep_data(radar, DEFAULT_SW, sweep_number)
    sweep_az_sw = get_sweep_azimuths(radar, sweep_number)
    sweep_elev_sw = get_sweep_elevations(radar, sweep_number)
    sw_lonr = 0.0 * sweep_sw
    sw_azr_1d = np.deg2rad(sweep_az_sw)
    sw_sr_1d = radar.range['data'][:] / RNG_MULT
    result = np.meshgrid(sw_sr_1d, sweep_az_sw)
    sw_azr_2d = np.deg2rad(result[1])
    sw_sr_2d = result[0]
    result = np.meshgrid(sw_sr_1d, sweep_elev_sw)
    sw_el = result[1]
    sweep_size = radar.sweep_end_ray_index['data'][sweep_number] + 1 - \
        radar.sweep_start_ray_index['data'][sweep_number]
    sw_gr, sw_ht = rsl_get_groundr_and_h(sw_sr_2d, sw_el)
    sw_latr = np.arcsin((np.sin(klatr) * np.cos(sw_gr/re)) +
                        (np.cos(klatr) * np.sin(sw_gr/re) * np.cos(sw_azr_2d)))

    # Get longitude at every gate as well as precompute eps_sw
    for j in np.arange(sweep_size):
        for i in np.arange(radar.ngates):
            sw_lonr[j, i] = klonr + \
                atan2c_longitude(sw_azr_1d[j], sw_gr[j, i], klatr,
                                 sw_latr[j, i])
    sw_lat = np.rad2deg(sw_latr)
    sw_lon = np.rad2deg(sw_lonr)
    return sw_lat, sw_lon
Beispiel #2
0
def calc_turb_sweep(radar, sweep_number, radius=DEFAULT_RADIUS,
                    split_cut=False,
                    xran=MAX_INT, yran=MAX_INT, verbose=False,
                    name_dz=DEFAULT_DZ, name_sw=DEFAULT_SW,
                    use_ntda=True, beamwidth=DEFAULT_BEAMWIDTH,
                    gate_spacing=DEFAULT_GATE_SPACING):
    """
    Provide a Py-ART radar object containing reflectivity and spectrum width
    variables as an argument, along with the sweep number and any necessary
    changes to the keywords, and receive back turbulence for the same sweep
    as spectrum width (along with longitude and latitude on the same coordinate
    system).
    radar = Py-ART radar object
    sweep_number = Can be as low as 0, as high as # of sweeps minus 1
    radius = radius of influence (km)
    split_cut = Set to True if using NEXRAD or similar radar that has two
                separate low-level sweeps at the same tilt angle for DZ & SW
    verbose = Set to True to get more information about calculation progress.
    xran = [Min X from radar, Max X from radar], subsectioning improves
           performance
    yran = [Min Y from radar, Max Y from radar], subsectioning improves
           performance
    name_dz = Name of reflectivity field, used by Py-ART to access field
    name_sw = Name of spectrum width field, used by Py-ART to access field
    use_ntda = Flag to use the spatial averaging and weighting employed by NTDA
    beamwidth = Beamwidth of radar in degrees
    gate_spacing = Gate spacing of radar in km

    """

    if verbose:
        overall_time = time.time()
        begin_time = time.time()

    sweep_dz = get_sweep_data(radar, name_dz, sweep_number)
    try:
        fill_val_sw = radar.fields[name_sw]['_FillValue']
    except KeyError:
        fill_val_sw = BAD_DATA_VAL
    try:
        fill_val_dz = radar.fields[name_dz]['_FillValue']
    except KeyError:
        fill_val_dz = BAD_DATA_VAL
    sweep_sw, sweep_az_sw, sweep_elev_sw, dz_sw = \
        _retrieve_sweep_fields(radar, name_sw, name_dz, sweep_number,
                               sweep_dz, split_cut)

    # Radar location needed to get lat/lon
    # of every gate for distance calculations
    klat, klon, klatr, klonr = get_radar_latlon_plus_radians(radar)

    # Initialize information on sweep geomtery
    sw_lonr = 0.0 * sweep_sw
    sw_azr_1d = np.deg2rad(sweep_az_sw)
    sw_sr_1d = radar.range['data'][:] / RNG_MULT
    result = np.meshgrid(sw_sr_1d, sweep_az_sw)
    sw_azr_2d = np.deg2rad(result[1])
    sw_sr_2d = result[0]
    result = np.meshgrid(sw_sr_1d, sweep_elev_sw)
    sw_el = result[1]
    sweep_size = radar.sweep_end_ray_index['data'][sweep_number] + 1 - \
        radar.sweep_start_ray_index['data'][sweep_number]
    sw_gr, sw_ht = rsl_get_groundr_and_h(sw_sr_2d, sw_el)
    sw_latr = np.arcsin((np.sin(klatr) * np.cos(sw_gr/re)) +
                        (np.cos(klatr) * np.sin(sw_gr/re) * np.cos(sw_azr_2d)))

    if verbose:
        print(time.time() - begin_time,
              'seconds to complete all preliminary processing')
        begin_time = time.time()

    # Get longitude at every gate
    for j in np.arange(sweep_size):
        for i in np.arange(radar.ngates):
            sw_lonr[j, i] = klonr +\
                atan2c_longitude(sw_azr_1d[j], sw_gr[j, i],
                                 klatr, sw_latr[j, i])
    sw_lat = np.rad2deg(sw_latr)
    sw_lon = np.rad2deg(sw_lonr)

    # Determine NTDA interest fields
    csnr_sw = _calc_csnr_for_every_gate(dz_sw, sw_sr_2d)
    crng_sw = _calc_crng_for_every_gate(sw_sr_2d)
    czh_sw = _calc_czh_for_every_gate(dz_sw, sw_ht)
    cpr = 1.0  # Not calculating Cpr, user must remove second trip manually.

    if verbose:
        print(time.time() - begin_time,
              'seconds to compute longitudes and precompute Csnr, Crng, Czh')
        begin_time = time.time()

    xx, yy = calc_cartesian_coords_radians(sw_lonr, sw_latr, klonr, klatr)

    # Flatten all arrays to avoid performance buzzkill of nested loops.
    # Then reduce the data using masks to make the job manageable.
    sweep_sw = sweep_sw.ravel()
    dz_sw = dz_sw.ravel()
    condition = np.logical_and(dz_sw != fill_val_dz, sweep_sw != fill_val_sw)
    sweep_sw = sweep_sw[condition]
    dz_sw = dz_sw[condition]

    # Brief detour to get eps and check to see if that's all user wants.
    # Placing this code here with reduced sweep_sw improves performance.
    sr_1d = flatten_and_reduce_data_array(sw_sr_2d, condition)
    cond = gate_spacing >= sr_1d * np.deg2rad(beamwidth)
    eps_sw = edr_long_range(sweep_sw, sr_1d, beamwidth, gate_spacing)
    eps_sw[cond] = edr_short_range(sweep_sw[cond], sr_1d[cond],
                                   beamwidth, gate_spacing)
    if not use_ntda:
        turb_radar_f = 1.0 * eps_sw
        turb_radar = sw_lat.flatten() * 0.0 + fill_val_sw
        turb_radar[condition] = turb_radar_f
        eps_sw = np.reshape(turb_radar, (len(sweep_az_sw), radar.ngates))
        if verbose:
            print(time.time() - overall_time,
                  'seconds to process radar sweep')
        return eps_sw, sw_lat, sw_lon

    # Provided NTDA is wanted, continue flattening/reducing arrays
    xx = flatten_and_reduce_data_array(xx, condition)
    yy = flatten_and_reduce_data_array(yy, condition)
    csnr_sw = flatten_and_reduce_data_array(csnr_sw, condition)
    crng_sw = flatten_and_reduce_data_array(crng_sw, condition)
    czh_sw = flatten_and_reduce_data_array(czh_sw, condition)
    turb_radar_f = 0.0 * sweep_sw + fill_val_sw

    # Find the distance to every other good gate
    ind, ind_sw = _calc_tree(xx, yy, radius)
    cswv_sw = _calc_cswv_for_every_gate(xx, sweep_sw, ind_sw)
    if verbose:
        print(time.time() - begin_time,
              'seconds to get eps, reduce data,',
              'compute BallTree, and get Cswv')
        begin_time = time.time()

    # Loop thru data and do NTDA filtering
    for i in np.arange(len(xx)):
        if verbose:
            if i % 50000 == 0:
                print('i =', i, 'of', len(xx) - 1,
                      time.time() - begin_time, 'seconds elapsed during loop')
        if xran[0] < xx[i] < xran[1] and yran[0] < yy[i] < yran[1]:
            # Broadcating employed to minimize the amount of looping
            eps = eps_sw[ind[i]]**2
            csnr = csnr_sw[ind[i]]**0.6667
            crng = crng_sw[ind[i]]
            czh = czh_sw[ind[i]]
            cswv = cswv_sw[ind[i]]
            # Begin NTDA-specific calculation
            tot = csnr * cpr * cswv * czh * crng
            num = tot * eps
            tot = np.sum(tot)
            num = np.sum(num)
            if tot > 0:
                turb_radar_f[i] = np.sqrt(num/tot)

    # Restore turbulence to a full 2-D sweep array and return along w/ lat/lon.
    turb_radar = sw_lat.flatten() * 0.0 + fill_val_sw
    turb_radar[condition] = turb_radar_f
    turb_radar = np.reshape(turb_radar, (len(sweep_az_sw), radar.ngates))
    if verbose:
        print(time.time() - overall_time, 'seconds to process radar sweep')
    return turb_radar, sw_lat, sw_lon