def test_check_field_name_valid(self):
        """Ensures correct output from check_field_name.

        In this case, field name is valid.
        """

        radar_utils.check_field_name(LL_SHEAR_NAME_NEW)
    def test_check_field_name_invalid(self):
        """Ensures correct output from check_field_name.

        In this case, field name is invalid.
        """

        with self.assertRaises(ValueError):
            radar_utils.check_field_name(LL_SHEAR_NAME_NEW_FAKE)
def get_default_colour_scheme(field_name, opacity=DEFAULT_OPACITY):
    """Returns default colour scheme for radar field.

    :param field_name: Field name (must be accepted by
        `radar_utils.check_field_name`).
    :param opacity: Opacity (in range 0...1).
    :return: colour_map_object: Instance of `matplotlib.colors.ListedColormap`.
    :return: colour_norm_object: Instance of `matplotlib.colors.BoundaryNorm`.
    """

    radar_utils.check_field_name(field_name)
    error_checking.assert_is_greater(opacity, 0.)
    error_checking.assert_is_leq(opacity, 1.)

    colour_map_object = None
    colour_norm_object = None

    if field_name in radar_utils.REFLECTIVITY_NAMES:
        colour_map_object, colour_norm_object = (
            _get_reflectivity_colour_scheme())
    elif field_name in radar_utils.SHEAR_NAMES:
        colour_map_object, colour_norm_object = _get_az_shear_colour_scheme()
    elif field_name in radar_utils.ECHO_TOP_NAMES:
        colour_map_object, colour_norm_object = _get_echo_top_colour_scheme()
    elif field_name == radar_utils.MESH_NAME:
        colour_map_object, colour_norm_object = _get_mesh_colour_scheme()
    elif field_name == radar_utils.SHI_NAME:
        colour_map_object, colour_norm_object = _get_shi_colour_scheme()
    elif field_name == radar_utils.VIL_NAME:
        colour_map_object, colour_norm_object = _get_vil_colour_scheme()
    elif field_name == radar_utils.DIFFERENTIAL_REFL_NAME:
        colour_map_object, colour_norm_object = _get_zdr_colour_scheme()
    elif field_name == radar_utils.SPEC_DIFF_PHASE_NAME:
        colour_map_object, colour_norm_object = _get_kdp_colour_scheme()
    elif field_name == radar_utils.CORRELATION_COEFF_NAME:
        colour_map_object, colour_norm_object = _get_rho_hv_colour_scheme()
    elif field_name == radar_utils.SPECTRUM_WIDTH_NAME:
        colour_map_object, colour_norm_object = (
            _get_spectrum_width_colour_scheme())
    elif field_name == radar_utils.VORTICITY_NAME:
        colour_map_object, colour_norm_object = _get_vorticity_colour_scheme()
    elif field_name == radar_utils.DIVERGENCE_NAME:
        colour_map_object, colour_norm_object = _get_divergence_colour_scheme()

    num_colours = len(colour_map_object.colors)

    for i in range(num_colours):
        colour_map_object.colors[i] = matplotlib.colors.to_rgba(
            colour_map_object.colors[i], opacity)

    return colour_map_object, colour_norm_object
def get_default_colour_scheme(field_name):
    """Returns default colour scheme for radar field.

    :param field_name: Field name (must be accepted by
        `radar_utils.check_field_name`).
    :return: colour_map_object: Instance of `matplotlib.colors.ListedColormap`.
    :return: colour_norm_object: Instance of `matplotlib.colors.BoundaryNorm`.
    """

    radar_utils.check_field_name(field_name)

    if field_name in radar_utils.REFLECTIVITY_NAMES:
        return _get_reflectivity_colour_scheme()

    if field_name in radar_utils.SHEAR_NAMES:
        return _get_az_shear_colour_scheme()

    if field_name in radar_utils.ECHO_TOP_NAMES:
        return _get_echo_top_colour_scheme()

    if field_name == radar_utils.MESH_NAME:
        return _get_mesh_colour_scheme()

    if field_name == radar_utils.SHI_NAME:
        return _get_shi_colour_scheme()

    if field_name == radar_utils.VIL_NAME:
        return _get_vil_colour_scheme()

    if field_name == radar_utils.DIFFERENTIAL_REFL_NAME:
        return _get_zdr_colour_scheme()

    if field_name == radar_utils.SPEC_DIFF_PHASE_NAME:
        return _get_kdp_colour_scheme()

    if field_name == radar_utils.CORRELATION_COEFF_NAME:
        return _get_rho_hv_colour_scheme()

    if field_name == radar_utils.SPECTRUM_WIDTH_NAME:
        return _get_spectrum_width_colour_scheme()

    if field_name == radar_utils.VORTICITY_NAME:
        return _get_vorticity_colour_scheme()

    if field_name == radar_utils.DIVERGENCE_NAME:
        return _get_divergence_colour_scheme()

    return None
def _field_name_to_plotting_units(field_name):
    """Converts field *name* from default units to plotting units.

    :param field_name: Name of radar field (must be accepted by
        `radar_utils.check_field_name`).
    :return: new_field_name: Same as input, except in plotting units.
    """

    radar_utils.check_field_name(field_name)

    if field_name in radar_utils.ECHO_TOP_NAMES:
        return field_name.replace('_km', '_kft')

    if field_name in SHEAR_VORT_DIV_NAMES:
        return field_name.replace('_s01', '_ks01')

    return field_name
def _field_to_plotting_units(field_matrix, field_name):
    """Converts radar field from default units to plotting units.

    :param field_matrix: numpy array in default units.
    :param field_name: Name of radar field (must be accepted by
        `radar_utils.check_field_name`).
    :return: new_field_matrix: Same as input, except in plotting units.
    """

    radar_utils.check_field_name(field_name)

    if field_name in radar_utils.ECHO_TOP_NAMES:
        return field_matrix * KM_TO_KILOFEET

    if field_name in SHEAR_VORT_DIV_NAMES:
        return field_matrix * PER_SECOND_TO_PER_KILOSECOND

    return field_matrix
Exemple #7
0
def _column_name_to_statistic_params(column_name):
    """Determines parameters of statistic from column name.

    If column name does not correspond to a statistic, this method will return
    None.

    :param column_name: Name of column.
    :return: parameter_dict: Dictionary with the following keys.
    parameter_dict['is_gridrad_statistic']: Boolean flag (True if statistic was
        computed by GridRad software, not GewitterGefahr).
    parameter_dict['radar_field_name']: Name of radar field on which statistic
        is based.  None for GridRad statistics.
    parameter_dict['radar_height_m_asl']: Radar height (metres above sea level).
        None for GridRad statistics.
    parameter_dict['statistic_name']: Name of statistic.  None for GridRad
        statistics and percentiles.
    parameter_dict['percentile_level']: Percentile level.  None for GridRad
        statistics and non-percentile statistics.
    """

    column_name_parts = column_name.split('_')
    if len(column_name_parts) < 2:
        return None

    # Determine statistic name or percentile level.
    if column_name_parts[-1] in STATISTIC_NAMES:
        statistic_name = column_name_parts[-1]
        percentile_level = None
    else:
        statistic_name = None
        if not column_name_parts[-1].startswith('percentile'):
            return None

        percentile_part = column_name_parts[-1].replace('percentile', '')
        try:
            percentile_level = float(percentile_part)
        except ValueError:
            return None

    # Determine radar field.
    radar_field_name = '_'.join(column_name_parts[:-2])
    try:
        radar_utils.check_field_name(radar_field_name)
    except ValueError:
        return None

    # Determine radar height.
    radar_height_part = column_name_parts[-2]
    if not radar_height_part.endswith('metres'):
        return None

    radar_height_part = radar_height_part.replace('metres', '')
    try:
        radar_height_m_asl = int(radar_height_part)
    except ValueError:
        return None

    return {
        IS_GRIDRAD_STATISTIC_KEY: False,
        RADAR_FIELD_NAME_KEY: radar_field_name,
        RADAR_HEIGHT_KEY: radar_height_m_asl,
        STATISTIC_NAME_KEY: statistic_name,
        PERCENTILE_LEVEL_KEY: percentile_level
    }
Exemple #8
0
def find_raw_file_inexact_time(desired_time_unix_sec,
                               spc_date_string,
                               field_name,
                               data_source,
                               top_directory_name,
                               height_m_asl=None,
                               max_time_offset_sec=None,
                               raise_error_if_missing=False):
    """Finds raw file at inexact time.

    If you know the exact valid time, use `find_raw_file`.

    :param desired_time_unix_sec: Desired valid time.
    :param spc_date_string: SPC date (format "yyyymmdd").
    :param field_name: Field name in GewitterGefahr format.
    :param data_source: Data source (string).
    :param top_directory_name: Name of top-level directory with raw files.
    :param height_m_asl: Radar height (metres above sea level).
    :param max_time_offset_sec: Maximum offset between actual and desired valid
        time.

    For example, if `desired_time_unix_sec` is 162933 UTC 5 Jan 2018 and
    `max_time_offset_sec` = 60, this method will look for az-shear at valid
    times from 162833...163033 UTC 5 Jan 2018.

    If None, this defaults to `DEFAULT_MAX_TIME_OFFSET_FOR_AZ_SHEAR_SEC` for
    azimuthal-shear fields and `DEFAULT_MAX_TIME_OFFSET_FOR_NON_SHEAR_SEC` for
    all other fields.

    :param raise_error_if_missing: Boolean flag.  If no file is found and
        raise_error_if_missing = True, this method will error out.  If no file
        is found and raise_error_if_missing = False, will return None.
    :return: raw_file_name: Path to raw file.
    :raises: ValueError: if no file is found and raise_error_if_missing = True.
    """

    # Error-checking.
    error_checking.assert_is_integer(desired_time_unix_sec)
    _ = time_conversion.spc_date_string_to_unix_sec(spc_date_string)
    error_checking.assert_is_boolean(raise_error_if_missing)

    radar_utils.check_field_name(field_name)
    if max_time_offset_sec is None:
        if field_name in AZIMUTHAL_SHEAR_FIELD_NAMES:
            max_time_offset_sec = DEFAULT_MAX_TIME_OFFSET_FOR_AZ_SHEAR_SEC
        else:
            max_time_offset_sec = DEFAULT_MAX_TIME_OFFSET_FOR_NON_SHEAR_SEC

    error_checking.assert_is_integer(max_time_offset_sec)
    error_checking.assert_is_greater(max_time_offset_sec, 0)

    first_allowed_minute_unix_sec = numpy.round(
        int(
            rounder.floor_to_nearest(
                float(desired_time_unix_sec - max_time_offset_sec),
                MINUTES_TO_SECONDS)))
    last_allowed_minute_unix_sec = numpy.round(
        int(
            rounder.floor_to_nearest(
                float(desired_time_unix_sec + max_time_offset_sec),
                MINUTES_TO_SECONDS)))

    allowed_minutes_unix_sec = time_periods.range_and_interval_to_list(
        start_time_unix_sec=first_allowed_minute_unix_sec,
        end_time_unix_sec=last_allowed_minute_unix_sec,
        time_interval_sec=MINUTES_TO_SECONDS,
        include_endpoint=True).astype(int)

    relative_directory_name = get_relative_dir_for_raw_files(
        field_name=field_name,
        data_source=data_source,
        height_m_asl=height_m_asl)

    raw_file_names = []
    for this_time_unix_sec in allowed_minutes_unix_sec:
        this_pathless_file_pattern = _get_pathless_raw_file_pattern(
            this_time_unix_sec)

        this_file_pattern = '{0:s}/{1:s}/{2:s}/{3:s}/{4:s}'.format(
            top_directory_name, spc_date_string[:4], spc_date_string,
            relative_directory_name, this_pathless_file_pattern)

        raw_file_names += glob.glob(this_file_pattern)

    file_times_unix_sec = []
    for this_raw_file_name in raw_file_names:
        file_times_unix_sec.append(raw_file_name_to_time(this_raw_file_name))

    if len(file_times_unix_sec):
        file_times_unix_sec = numpy.array(file_times_unix_sec)
        time_differences_sec = numpy.absolute(file_times_unix_sec -
                                              desired_time_unix_sec)
        nearest_index = numpy.argmin(time_differences_sec)
        min_time_diff_sec = time_differences_sec[nearest_index]
    else:
        min_time_diff_sec = numpy.inf

    if min_time_diff_sec > max_time_offset_sec:
        if raise_error_if_missing:
            desired_time_string = time_conversion.unix_sec_to_string(
                desired_time_unix_sec, TIME_FORMAT_FOR_LOG_MESSAGES)

            error_string = (
                'Could not find "{0:s}" file within {1:d} seconds of {2:s}.'
            ).format(field_name, max_time_offset_sec, desired_time_string)

            raise ValueError(error_string)

        return None

    return raw_file_names[nearest_index]