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
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 }
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]