コード例 #1
0
def read_target_values(netcdf_file_name, target_name):
    """Reads target values from NetCDF file.

    N = number of storm objects

    :param netcdf_file_name: Path to input file.
    :param target_name: Name of target variable.
    :return: storm_label_dict: Dictionary with the following keys.
    storm_label_dict['storm_ids']: length-N list of storm IDs.
    storm_label_dict['valid_times_unix_sec']: length-N numpy array of valid
        times.
    storm_label_dict['target_values']: length-N numpy array with values of
        `target_name`.
    """

    error_checking.assert_is_string(target_name)
    netcdf_dataset = netcdf_io.open_netcdf(netcdf_file_name=netcdf_file_name,
                                           raise_error_if_fails=True)

    storm_ids = netCDF4.chartostring(
        netcdf_dataset.variables[STORM_IDS_KEY][:])
    valid_times_unix_sec = numpy.array(
        netcdf_dataset.variables[VALID_TIMES_KEY][:], dtype=int)
    target_values = numpy.array(netcdf_dataset.variables[target_name][:],
                                dtype=int)

    netcdf_dataset.close()

    return {
        STORM_IDS_KEY: [str(s) for s in storm_ids],
        VALID_TIMES_KEY: valid_times_unix_sec,
        TARGET_VALUES_KEY: target_values
    }
コード例 #2
0
def read_field_from_full_grid_file(netcdf_file_name,
                                   field_name=None,
                                   metadata_dict=None,
                                   raise_error_if_fails=True):
    """Reads one radar field from full-grid (not sparse-grid) file.

    This file should contain all radar variables for one time step.

    M = number of rows (unique grid-point latitudes)
    N = number of columns (unique grid-point longitudes)
    H = number of height levels (unique grid-point heights)

    :param netcdf_file_name: Path to input file.
    :param field_name: Name of radar field.
    :param metadata_dict: Dictionary created by
        read_metadata_from_full_grid_file.
    :param raise_error_if_fails: Boolean flag.  If True and file cannot be
        opened, this method will raise an error.  If False and file cannot be
        opened, will return None for all output variables.
    :return: field_matrix: H-by-M-by-N numpy array with values of radar field.
    :return: grid_point_heights_m_asl: length-H numpy array of height levels
        (integer metres above sea level).  If array is increasing (decreasing),
        height increases (decreases) with the first index of field_matrix.
    :return: grid_point_latitudes_deg: length-M numpy array of grid-point
        latitudes (deg N).  If array is increasing (decreasing), latitude
        increases (decreases) with the second index of field_matrix.
    :return: grid_point_longitudes_deg: length-N numpy array of grid-point
        longitudes (deg N).  If array is increasing (decreasing), latitude
        increases (decreases) with the third index of field_matrix.
    """

    error_checking.assert_file_exists(netcdf_file_name)
    netcdf_dataset = netcdf_io.open_netcdf(netcdf_file_name,
                                           raise_error_if_fails)
    if netcdf_dataset is None:
        return None, None, None, None

    field_name_orig = radar_utils.field_name_new_to_orig(
        field_name=field_name, data_source_name=radar_utils.GRIDRAD_SOURCE_ID)
    field_matrix = numpy.array(
        netcdf_dataset.variables[field_name_orig][0, :, :, :])

    grid_point_latitudes_deg = numpy.array(
        netcdf_dataset.variables[LATITUDE_NAME_ORIG])
    grid_point_longitudes_deg = lng_conversion.convert_lng_positive_in_west(
        numpy.array(netcdf_dataset.variables[LONGITUDE_NAME_ORIG]))

    _check_grid_points(grid_point_latitudes_deg=grid_point_latitudes_deg,
                       grid_point_longitudes_deg=grid_point_longitudes_deg,
                       metadata_dict=metadata_dict)

    grid_point_heights_m_asl = KM_TO_METRES * numpy.array(
        netcdf_dataset.variables[HEIGHT_NAME_ORIG])
    grid_point_heights_m_asl = numpy.round(grid_point_heights_m_asl).astype(
        int)

    netcdf_dataset.close()
    return (field_matrix, grid_point_heights_m_asl, grid_point_latitudes_deg,
            grid_point_longitudes_deg)
コード例 #3
0
def read_data_from_sparse_grid_file(netcdf_file_name, field_name_orig=None,
                                    data_source=None, sentinel_values=None,
                                    raise_error_if_fails=True):
    """Reads sparse radar grid from raw (either MYRORSS or MRMS) file.

    This file should contain one radar field at one height and one time step.

    :param netcdf_file_name: Path to input file.
    :param field_name_orig: Name of radar field in original (either MYRORSS or
        MRMS) format.
    :param data_source: Data source (either "myrorss" or "mrms").
    :param sentinel_values: 1-D numpy array of sentinel values.
    :param raise_error_if_fails: Boolean flag.  If True and file cannot be
        opened, this method will raise an error.  If False and file cannot be
        opened, this method will return None.
    :return: sparse_grid_table: pandas DataFrame with the following columns.
        Each row corresponds to one grid cell.
    sparse_grid_table.grid_row: Row index.
    sparse_grid_table.grid_column: Column index.
    sparse_grid_table.<field_name>: Radar measurement (field_name is determined
        by the method `field_name_orig_to_new`).
    sparse_grid_table.num_grid_cells: Number of consecutive grid cells --
        starting at the current one and counting along rows first, columns
        second -- with the same radar measurement.
    """

    error_checking.assert_file_exists(netcdf_file_name)
    error_checking.assert_is_numpy_array_without_nan(sentinel_values)
    error_checking.assert_is_numpy_array(sentinel_values, num_dimensions=1)

    netcdf_dataset = netcdf_io.open_netcdf(netcdf_file_name,
                                           raise_error_if_fails)
    if netcdf_dataset is None:
        return None

    field_name = _field_name_orig_to_new(field_name_orig,
                                         data_source=data_source)
    num_values = len(netcdf_dataset.variables[GRID_ROW_COLUMN_ORIG])

    if num_values == 0:
        sparse_grid_dict = {
            GRID_ROW_COLUMN: numpy.array([], dtype=int),
            GRID_COLUMN_COLUMN: numpy.array([], dtype=int),
            NUM_GRID_CELL_COLUMN: numpy.array([], dtype=int),
            field_name: numpy.array([], dtype=int)}
    else:
        sparse_grid_dict = {
            GRID_ROW_COLUMN: netcdf_dataset.variables[GRID_ROW_COLUMN_ORIG][:],
            GRID_COLUMN_COLUMN:
                netcdf_dataset.variables[GRID_COLUMN_COLUMN_ORIG][:],
            NUM_GRID_CELL_COLUMN:
                netcdf_dataset.variables[NUM_GRID_CELL_COLUMN_ORIG][:],
            field_name: netcdf_dataset.variables[field_name_orig][:]}

    netcdf_dataset.close()
    sparse_grid_table = pandas.DataFrame.from_dict(sparse_grid_dict)
    return _remove_sentinels_from_sparse_grid(
        sparse_grid_table, field_name, sentinel_values)
コード例 #4
0
def read_classifications(netcdf_file_name):
    """Reads echo classifications from NetCDF file.

    :param netcdf_file_name: Path to input file.
    :return: convective_flag_matrix: M-by-N numpy array of Boolean flags (True
        if convective, False if not).
    :return: other_metadata_dict: Dictionary with the following keys.
    other_metadata_dict['valid_time_unix_sec']: Valid time.
    other_metadata_dict['grid_point_latitudes_deg']: length-M numpy array with
        latitudes (deg N) of grid points.
    other_metadata_dict['grid_point_longitudes_deg']: length-N numpy array with
        longitudes (deg E) of grid points.

    :return: option_dict: See doc for `find_convective_pixels`.
    """

    netcdf_dataset = netcdf_io.open_netcdf(netcdf_file_name)

    option_dict = {
        PEAKEDNESS_NEIGH_KEY:
        getattr(netcdf_dataset, PEAKEDNESS_NEIGH_KEY),
        MAX_PEAKEDNESS_HEIGHT_KEY:
        getattr(netcdf_dataset, MAX_PEAKEDNESS_HEIGHT_KEY),
        HALVE_RESOLUTION_KEY:
        bool(getattr(netcdf_dataset, HALVE_RESOLUTION_KEY)),
        MIN_ECHO_TOP_KEY:
        getattr(netcdf_dataset, MIN_ECHO_TOP_KEY),
        ECHO_TOP_LEVEL_KEY:
        getattr(netcdf_dataset, ECHO_TOP_LEVEL_KEY),
        MIN_COMPOSITE_REFL_CRITERION1_KEY:
        getattr(netcdf_dataset, MIN_COMPOSITE_REFL_CRITERION1_KEY),
        MIN_COMPOSITE_REFL_CRITERION5_KEY:
        getattr(netcdf_dataset, MIN_COMPOSITE_REFL_CRITERION5_KEY),
        MIN_COMPOSITE_REFL_AML_KEY:
        getattr(netcdf_dataset, MIN_COMPOSITE_REFL_AML_KEY)
    }

    if option_dict[MIN_COMPOSITE_REFL_CRITERION1_KEY] < 0:
        option_dict[MIN_COMPOSITE_REFL_CRITERION1_KEY] = None

    option_dict = _check_input_args(option_dict)

    other_metadata_dict = {
        VALID_TIME_KEY:
        int(getattr(netcdf_dataset, VALID_TIME_KEY)),
        LATITUDES_KEY:
        numpy.array(netcdf_dataset.variables[LATITUDES_KEY][:], dtype=float),
        LONGITUDES_KEY:
        numpy.array(netcdf_dataset.variables[LONGITUDES_KEY][:], dtype=float)
    }

    convective_flag_matrix = numpy.array(
        netcdf_dataset.variables[FLAG_MATRIX_KEY][:], dtype=bool)
    netcdf_dataset.close()

    return convective_flag_matrix, other_metadata_dict, option_dict
コード例 #5
0
def read_metadata_from_full_grid_file(netcdf_file_name,
                                      raise_error_if_fails=True):
    """Reads metadata from full-grid (not sparse-grid) file.

    This file should contain all radar variables for one time step.

    :param netcdf_file_name: Path to input file.
    :param raise_error_if_fails: Boolean flag.  If True and file cannot be
        opened, this method will raise an error.  If False and file cannot be
        opened, will return None.
    :return: metadata_dict: Dictionary with the following keys.
    metadata_dict['nw_grid_point_lat_deg']: Latitude (deg N) of northwesternmost
        grid point.
    metadata_dict['nw_grid_point_lng_deg']: Longitude (deg E) of
        northwesternmost grid point.
    metadata_dict['lat_spacing_deg']: Spacing (deg N) between adjacent rows.
    metadata_dict['lng_spacing_deg']: Spacing (deg E) between adjacent columns.
    metadata_dict['num_lat_in_grid']: Number of rows (unique grid-point
        latitudes).
    metadata_dict['num_lng_in_grid']: Number of columns (unique grid-point
        longitudes).
    metadata_dict['unix_time_sec']: Valid time.
    """

    error_checking.assert_file_exists(netcdf_file_name)
    netcdf_dataset = netcdf_io.open_netcdf(netcdf_file_name,
                                           raise_error_if_fails)
    if netcdf_dataset is None:
        return None

    grid_point_latitudes_deg = numpy.array(
        netcdf_dataset.variables[LATITUDE_NAME_ORIG])
    grid_point_longitudes_deg = lng_conversion.convert_lng_positive_in_west(
        numpy.array(netcdf_dataset.variables[LONGITUDE_NAME_ORIG]))

    metadata_dict = {
        radar_utils.NW_GRID_POINT_LAT_COLUMN:
        numpy.max(grid_point_latitudes_deg),
        radar_utils.NW_GRID_POINT_LNG_COLUMN:
        numpy.min(grid_point_longitudes_deg),
        radar_utils.LAT_SPACING_COLUMN:
        numpy.mean(numpy.diff(grid_point_latitudes_deg)),
        radar_utils.LNG_SPACING_COLUMN:
        numpy.mean(numpy.diff(grid_point_longitudes_deg)),
        radar_utils.NUM_LAT_COLUMN:
        len(grid_point_latitudes_deg),
        radar_utils.NUM_LNG_COLUMN:
        len(grid_point_longitudes_deg),
        radar_utils.UNIX_TIME_COLUMN:
        _time_from_gridrad_to_unix(netcdf_dataset.variables[TIME_NAME_ORIG][0])
    }

    netcdf_dataset.close()
    return metadata_dict
コード例 #6
0
def read_data_from_full_grid_file(netcdf_file_name, metadata_dict,
                                  raise_error_if_fails=True):
    """Reads full radar grid from raw (either MYRORSS or MRMS) file.

    This file should contain one radar field at one height and one time step.

    M = number of rows (unique grid-point latitudes)
    N = number of columns (unique grid-point longitudes)

    :param netcdf_file_name: Path to input file.
    :param metadata_dict: Dictionary with metadata for NetCDF file, created by
        read_metadata_from_raw_file.
    :param raise_error_if_fails: Boolean flag.  If True and file cannot be
        opened, this method will raise an error.  If False and file cannot be
        opened, this method will return None for all output variables.
    :return: field_matrix: M-by-N numpy array with values of radar field.
    :return: unique_grid_point_lat_deg: length-M numpy array of grid-point
        latitudes (deg N).  If array is increasing (decreasing), latitude
        increases (decreases) while traveling down the columns of field_matrix.
    :return: unique_grid_point_lng_deg: length-N numpy array of grid-point
        longitudes (deg E).  If array is increasing (decreasing), longitude
        increases (decreases) while traveling right across the rows of
        field_matrix.
    """

    error_checking.assert_file_exists(netcdf_file_name)

    netcdf_dataset = netcdf_io.open_netcdf(netcdf_file_name,
                                           raise_error_if_fails)
    if netcdf_dataset is None:
        return None, None, None

    field_matrix = netcdf_dataset.variables[
        metadata_dict[FIELD_NAME_COLUMN_ORIG]]
    netcdf_dataset.close()

    min_latitude_deg = metadata_dict[NW_GRID_POINT_LAT_COLUMN] - (
        metadata_dict[LAT_SPACING_COLUMN] * (metadata_dict[NUM_LAT_COLUMN] - 1))
    unique_grid_point_lat_deg, unique_grid_point_lng_deg = (
        grids.get_latlng_grid_points(
            min_latitude_deg=min_latitude_deg,
            min_longitude_deg=metadata_dict[NW_GRID_POINT_LNG_COLUMN],
            lat_spacing_deg=metadata_dict[LAT_SPACING_COLUMN],
            lng_spacing_deg=metadata_dict[LNG_SPACING_COLUMN],
            num_rows=metadata_dict[NUM_LAT_COLUMN],
            num_columns=metadata_dict[NUM_LNG_COLUMN]))

    field_matrix = _remove_sentinels_from_full_grid(
        field_matrix, metadata_dict[SENTINEL_VALUE_COLUMN])
    return (numpy.flipud(field_matrix), unique_grid_point_lat_deg[::-1],
            unique_grid_point_lng_deg)
コード例 #7
0
def read_data_from_full_grid_file(netcdf_file_name,
                                  metadata_dict,
                                  raise_error_if_fails=True):
    """Reads full radar grid from raw (either MYRORSS or MRMS) file.

    This file should contain one radar field at one height and valid time.

    :param netcdf_file_name: Path to input file.
    :param metadata_dict: Dictionary created by `read_metadata_from_raw_file`.
    :param raise_error_if_fails: Boolean flag.  If True and file cannot be read,
        this method will raise an error.  If False and file cannot be read, will
        return None for all output vars.
    :return: field_matrix: M-by-N numpy array with radar field.  Latitude
        increases while moving up each column, and longitude increases while
        moving right along each row.
    :return: grid_point_latitudes_deg: length-M numpy array of grid-point
        latitudes (deg N).  This array is monotonically decreasing.
    :return: grid_point_longitudes_deg: length-N numpy array of grid-point
        longitudes (deg E).  This array is monotonically increasing.
    """

    error_checking.assert_file_exists(netcdf_file_name)
    netcdf_dataset = netcdf_io.open_netcdf(netcdf_file_name,
                                           raise_error_if_fails)
    if netcdf_dataset is None:
        return None, None, None

    field_matrix = netcdf_dataset.variables[
        metadata_dict[FIELD_NAME_COLUMN_ORIG]]
    netcdf_dataset.close()

    min_latitude_deg = metadata_dict[radar_utils.NW_GRID_POINT_LAT_COLUMN] - (
        metadata_dict[radar_utils.LAT_SPACING_COLUMN] *
        (metadata_dict[radar_utils.NUM_LAT_COLUMN] - 1))
    grid_point_latitudes_deg, grid_point_longitudes_deg = (
        grids.get_latlng_grid_points(
            min_latitude_deg=min_latitude_deg,
            min_longitude_deg=metadata_dict[
                radar_utils.NW_GRID_POINT_LNG_COLUMN],
            lat_spacing_deg=metadata_dict[radar_utils.LAT_SPACING_COLUMN],
            lng_spacing_deg=metadata_dict[radar_utils.LNG_SPACING_COLUMN],
            num_rows=metadata_dict[radar_utils.NUM_LAT_COLUMN],
            num_columns=metadata_dict[radar_utils.NUM_LNG_COLUMN]))

    field_matrix = _remove_sentinels_from_full_grid(
        field_matrix, metadata_dict[radar_utils.SENTINEL_VALUE_COLUMN])
    return (numpy.flipud(field_matrix), grid_point_latitudes_deg[::-1],
            grid_point_longitudes_deg)
コード例 #8
0
ファイル: cnn.py プロジェクト: theweathermanda/GewitterGefahr
def read_features(netcdf_file_name):
    """Reads features (activations of intermediate layer) from NetCDF file.

    :param netcdf_file_name: Path to input file.
    :return: feature_matrix: E-by-Z numpy array of features.
    :return: target_values: length-E numpy array of target values.  All in
        0...(K - 1), where K = number of classes.
    :return: num_classes: Number of classes.
    """

    netcdf_dataset = netcdf_io.open_netcdf(netcdf_file_name=netcdf_file_name,
                                           raise_error_if_fails=True)

    feature_matrix = numpy.array(
        netcdf_dataset.variables[FEATURE_MATRIX_KEY][:])
    target_values = numpy.array(netcdf_dataset.variables[TARGET_VALUES_KEY][:],
                                dtype=int)
    num_classes = getattr(netcdf_dataset, NUM_CLASSES_KEY)
    netcdf_dataset.close()

    return feature_matrix, target_values, num_classes
コード例 #9
0
def read_target_values(netcdf_file_name, target_names=None):
    """Reads target values from NetCDF file.

    E = number of examples (storm objects)
    T = number of target variables

    :param netcdf_file_name: Path to input file.
    :param target_names: 1-D list with names of target variables to read.  If
        None, will read all target variables.
    :return: storm_label_dict: Dictionary with the following keys.
    storm_label_dict['full_id_strings']: length-E list of full storm IDs.
    storm_label_dict['valid_times_unix_sec']: length-E numpy array of valid
        times.
    storm_label_dict['target_names']: length-T list with names of target
        variables.
    storm_label_dict['target_matrix']: E-by-T of target values (integer class
        labels).
    """

    netcdf_dataset = netcdf_io.open_netcdf(
        netcdf_file_name=netcdf_file_name, raise_error_if_fails=True)

    try:
        full_id_strings = netCDF4.chartostring(
            netcdf_dataset.variables[FULL_IDS_KEY][:]
        )
    except KeyError:
        full_id_strings = netCDF4.chartostring(
            netcdf_dataset.variables['storm_ids'][:]
        )

    valid_times_unix_sec = numpy.array(
        netcdf_dataset.variables[VALID_TIMES_KEY][:], dtype=int
    )

    if target_names is None:
        target_names = list(netcdf_dataset.variables.keys())
        target_names.remove(FULL_IDS_KEY)
        target_names.remove(VALID_TIMES_KEY)

    error_checking.assert_is_string_list(target_names)
    error_checking.assert_is_numpy_array(
        numpy.array(target_names), num_dimensions=1
    )

    num_storm_objects = len(full_id_strings)
    target_matrix = None

    for this_target_name in target_names:
        these_target_values = numpy.array(
            netcdf_dataset.variables[this_target_name][:], dtype=int
        )

        these_target_values = numpy.reshape(
            these_target_values, (num_storm_objects, 1)
        )

        if target_matrix is None:
            target_matrix = these_target_values + 0
        else:
            target_matrix = numpy.concatenate(
                (target_matrix, these_target_values), axis=1
            )

    netcdf_dataset.close()

    return {
        FULL_IDS_KEY: [str(f) for f in full_id_strings],
        VALID_TIMES_KEY: valid_times_unix_sec,
        TARGET_NAMES_KEY: target_names,
        TARGET_MATRIX_KEY: target_matrix
    }
コード例 #10
0
def read_winds_from_raw_file(netcdf_file_name, secondary_source=None,
                             raise_error_if_fails=True):
    """Reads wind observations from raw file.

    This file should contain all fields for one secondary data source and one
    hour.

    :param netcdf_file_name: Path to input file.
    :param secondary_source: String ID for secondary data source.
    :param raise_error_if_fails: Boolean flag.  If True and the read fails, this
        method will raise an error.  If False and the read fails, this method
        will return None.
    :return: wind_table: If file cannot be opened and raise_error_if_fails =
        False, this is None.  Otherwise, it is a pandas DataFrame with the
        following columns.
    wind_table.station_id: String ID for station.
    wind_table.station_name: Verbose name for station.
    wind_table.latitude_deg: Latitude (deg N).
    wind_table.longitude_deg: Longitude (deg E).
    wind_table.elevation_m_asl: Elevation (metres above sea level).
    wind_table.unix_time_sec: Observation time (seconds since 0000 UTC 1 Jan
        1970).
    wind_table.wind_speed_m_s01: Speed of sustained wind (m/s).
    wind_table.wind_direction_deg: Direction of sustained wind (degrees of
        origin -- i.e., direction that the wind is coming from -- as per
        meteorological convention).
    wind_table.wind_gust_speed_m_s01: Speed of wind gust (m/s).
    wind_table.wind_gust_direction_deg: Direction of wind gust (degrees of
        origin).
    """

    error_checking.assert_file_exists(netcdf_file_name)
    netcdf_dataset = netcdf_io.open_netcdf(netcdf_file_name,
                                           raise_error_if_fails)
    if netcdf_dataset is None:
        return None

    # TODO(thunderhoser): This is hacky (accounts for length-0 arrays of station
    # names).  Find a better way to handle this exception.
    try:
        station_names = _char_matrix_to_string_list(
            netcdf_dataset.variables[STATION_NAME_COLUMN_ORIG][:])
    except IndexError:
        return None

    try:
        station_ids = _char_matrix_to_string_list(
            netcdf_dataset.variables[STATION_ID_COLUMN_ORIG][:])
    except KeyError:
        station_ids = station_names

    for i in range(len(station_ids)):
        station_ids[i] = raw_wind_io.append_source_to_station_id(
            station_ids[i], primary_source=raw_wind_io.MADIS_DATA_SOURCE,
            secondary_source=secondary_source)

    try:
        unix_times_sec = netcdf_dataset.variables[TIME_COLUMN_ORIG][:]
    except KeyError:
        unix_times_sec = netcdf_dataset.variables[TIME_COLUMN_ORIG_BACKUP][:]

    wind_speeds_m_s01 = netcdf_dataset.variables[WIND_SPEED_COLUMN_ORIG][:]
    wind_speed_quality_flags = netcdf_dataset.variables[
        WIND_SPEED_FLAG_COLUMN_ORIG][:]
    num_observations = len(wind_speeds_m_s01)

    try:
        wind_directions_deg = netcdf_dataset.variables[WIND_DIR_COLUMN_ORIG][:]
        wind_dir_quality_flags = netcdf_dataset.variables[
            WIND_DIR_FLAG_COLUMN_ORIG][:]
    except KeyError:
        wind_directions_deg = numpy.full(num_observations, numpy.nan)
        wind_dir_quality_flags = [DEFAULT_QUALITY_FLAG] * num_observations

    try:
        wind_gust_speeds_m_s01 = netcdf_dataset.variables[
            WIND_GUST_SPEED_COLUMN_ORIG][:]
        wind_gust_speed_quality_flags = netcdf_dataset.variables[
            WIND_GUST_SPEED_FLAG_COLUMN_ORIG][:]
    except KeyError:
        wind_gust_speeds_m_s01 = numpy.full(num_observations, numpy.nan)
        wind_gust_speed_quality_flags = (
            [DEFAULT_QUALITY_FLAG] * num_observations)

    try:
        wind_gust_directions_deg = netcdf_dataset.variables[
            WIND_GUST_DIR_COLUMN_ORIG][:]
        wind_gust_dir_quality_flags = netcdf_dataset.variables[
            WIND_GUST_DIR_FLAG_COLUMN_ORIG][:]
    except KeyError:
        wind_gust_directions_deg = numpy.full(num_observations, numpy.nan)
        wind_gust_dir_quality_flags = [DEFAULT_QUALITY_FLAG] * num_observations

    wind_dict = {raw_wind_io.STATION_ID_COLUMN: station_ids,
                 raw_wind_io.STATION_NAME_COLUMN: station_names,
                 raw_wind_io.LATITUDE_COLUMN: netcdf_dataset.variables[
                     LATITUDE_COLUMN_ORIG][:],
                 raw_wind_io.LONGITUDE_COLUMN: netcdf_dataset.variables[
                     LONGITUDE_COLUMN_ORIG][:],
                 raw_wind_io.ELEVATION_COLUMN: netcdf_dataset.variables[
                     ELEVATION_COLUMN_ORIG][:],
                 raw_wind_io.TIME_COLUMN: numpy.array(unix_times_sec).astype(
                     int),
                 raw_wind_io.WIND_SPEED_COLUMN: wind_speeds_m_s01,
                 raw_wind_io.WIND_DIR_COLUMN: wind_directions_deg,
                 raw_wind_io.WIND_GUST_SPEED_COLUMN: wind_gust_speeds_m_s01,
                 raw_wind_io.WIND_GUST_DIR_COLUMN: wind_gust_directions_deg,
                 WIND_SPEED_FLAG_COLUMN: wind_speed_quality_flags,
                 WIND_DIR_FLAG_COLUMN: wind_dir_quality_flags,
                 WIND_GUST_SPEED_FLAG_COLUMN: wind_gust_speed_quality_flags,
                 WIND_GUST_DIR_FLAG_COLUMN: wind_gust_dir_quality_flags}

    netcdf_dataset.close()
    wind_table = pandas.DataFrame.from_dict(wind_dict)
    wind_table = _remove_invalid_wind_rows(wind_table)
    return _remove_low_quality_data(wind_table)
コード例 #11
0
def read_field_from_full_grid_file(netcdf_file_name,
                                   field_name=None,
                                   metadata_dict=None,
                                   raise_error_if_fails=True):
    """Reads one radar field from full-grid (not sparse-grid) file.

    This file should contain all radar variables for one time step.

    M = number of rows (unique grid-point latitudes)
    N = number of columns (unique grid-point longitudes)
    H = number of height levels (unique grid-point heights)

    :param netcdf_file_name: Path to input file.
    :param field_name: Name of radar field.
    :param metadata_dict: Dictionary created by
        read_metadata_from_full_grid_file.
    :param raise_error_if_fails: Boolean flag.  If True and file cannot be
        opened, this method will raise an error.  If False and file cannot be
        opened, will return None for all output variables.
    :return: field_matrix: H-by-M-by-N numpy array with values of radar field.
    :return: unique_grid_point_heights_m_asl: length-H numpy array of grid-point
        heights (metres above sea level).  If array is increasing
        (decreasing), height increases (decreases) with the first index of
        field_matrix.
    :return: unique_grid_point_lat_deg: length-M numpy array of grid-point
        latitudes (deg N).  If array is increasing (decreasing), latitude
        increases (decreases) with the second index of field_matrix.
    :return: unique_grid_point_lng_deg: length-N numpy array of grid-point
        longitudes (deg E).  If array is increasing (decreasing), longitude
        increases (decreases) with the third index of field_matrix.
    """

    error_checking.assert_file_exists(netcdf_file_name)
    netcdf_dataset = netcdf_io.open_netcdf(netcdf_file_name,
                                           raise_error_if_fails)
    if netcdf_dataset is None:
        return None, None, None, None

    field_name_orig = _field_name_new_to_orig(field_name)
    field_matrix = numpy.array(
        netcdf_dataset.variables[field_name_orig][0, :, :, :])

    min_latitude_deg = metadata_dict[radar_io.NW_GRID_POINT_LAT_COLUMN] - (
        metadata_dict[radar_io.LAT_SPACING_COLUMN] *
        (metadata_dict[radar_io.NUM_LAT_COLUMN] - 1))
    unique_grid_point_lat_deg, unique_grid_point_lng_deg = (
        grids.get_latlng_grid_points(
            min_latitude_deg=min_latitude_deg,
            min_longitude_deg=metadata_dict[radar_io.NW_GRID_POINT_LNG_COLUMN],
            lat_spacing_deg=metadata_dict[radar_io.LAT_SPACING_COLUMN],
            lng_spacing_deg=metadata_dict[radar_io.LNG_SPACING_COLUMN],
            num_rows=metadata_dict[radar_io.NUM_LAT_COLUMN],
            num_columns=metadata_dict[radar_io.NUM_LNG_COLUMN]))

    max_height_m_asl = metadata_dict[MIN_GRID_POINT_HEIGHT_COLUMN] + (
        metadata_dict[HEIGHT_SPACING_COLUMN] *
        (metadata_dict[NUM_HEIGHTS_COLUMN] - 1))
    unique_grid_point_heights_m_asl = numpy.linspace(
        metadata_dict[MIN_GRID_POINT_HEIGHT_COLUMN],
        max_height_m_asl,
        num=metadata_dict[NUM_HEIGHTS_COLUMN])

    netcdf_dataset.close()
    return (field_matrix, unique_grid_point_heights_m_asl,
            unique_grid_point_lat_deg, unique_grid_point_lng_deg)
コード例 #12
0
def read_polygons_from_netcdf(netcdf_file_name,
                              metadata_dict=None,
                              spc_date_unix_sec=None,
                              tracking_start_time_unix_sec=None,
                              tracking_end_time_unix_sec=None,
                              raise_error_if_fails=True):
    """Reads storm polygons (outlines of storm cells) from NetCDF file.

    P = number of grid points in storm cell (different for each storm cell)
    V = number of vertices in storm polygon (different for each storm cell)

    If file cannot be opened, returns None.

    :param netcdf_file_name: Path to input file.
    :param metadata_dict: Dictionary with metadata for NetCDF file, created by
        `radar_io.read_metadata_from_raw_file`.
    :param spc_date_unix_sec: SPC date;
    :param tracking_start_time_unix_sec: Start time for tracking period.  This
        can be found by `get_start_end_times_for_spc_date`.
    :param tracking_end_time_unix_sec: End time for tracking period.  This can
        be found by `get_start_end_times_for_spc_date`.
    :param raise_error_if_fails: Boolean flag.  If True and file cannot be
        opened, this method will raise an error.
    :return: polygon_table: If file cannot be opened and raise_error_if_fails =
        False, this is None.  Otherwise, it is a pandas DataFrame with the
        following columns.
    polygon_table.storm_id: String ID for storm cell.
    polygon_table.unix_time_sec: Time in Unix format.
    polygon_table.spc_date_unix_sec: SPC date in Unix format.
    polygon_table.tracking_start_time_unix_sec: Start time for tracking period.
    polygon_table.tracking_end_time_unix_sec: End time for tracking period.
    polygon_table.centroid_lat_deg: Latitude at centroid of storm cell (deg N).
    polygon_table.centroid_lng_deg: Longitude at centroid of storm cell (deg E).
    polygon_table.grid_point_latitudes_deg: length-P numpy array with latitudes
        (deg N) of grid points in storm cell.
    polygon_table.grid_point_longitudes_deg: length-P numpy array with
        longitudes (deg E) of grid points in storm cell.
    polygon_table.grid_point_rows: length-P numpy array with row indices (all
        integers) of grid points in storm cell.
    polygon_table.grid_point_columns: length-P numpy array with column indices
        (all integers) of grid points in storm cell.
    polygon_table.polygon_object_latlng: Instance of `shapely.geometry.Polygon`
        with vertices in lat-long coordinates.
    polygon_table.polygon_object_rowcol: Instance of `shapely.geometry.Polygon`
        with vertices in row-column coordinates.
    """

    error_checking.assert_file_exists(netcdf_file_name)
    error_checking.assert_is_integer(spc_date_unix_sec)
    error_checking.assert_is_not_nan(spc_date_unix_sec)
    error_checking.assert_is_integer(tracking_start_time_unix_sec)
    error_checking.assert_is_not_nan(tracking_start_time_unix_sec)
    error_checking.assert_is_integer(tracking_end_time_unix_sec)
    error_checking.assert_is_not_nan(tracking_end_time_unix_sec)

    netcdf_dataset = netcdf_io.open_netcdf(netcdf_file_name,
                                           raise_error_if_fails)
    if netcdf_dataset is None:
        return None

    storm_id_var_name = metadata_dict[radar_io.FIELD_NAME_COLUMN]
    storm_id_var_name_orig = metadata_dict[radar_io.FIELD_NAME_COLUMN_ORIG]
    num_values = len(netcdf_dataset.variables[radar_io.GRID_ROW_COLUMN_ORIG])

    if num_values == 0:
        sparse_grid_dict = {
            radar_io.GRID_ROW_COLUMN: numpy.array([], dtype=int),
            radar_io.GRID_COLUMN_COLUMN: numpy.array([], dtype=int),
            radar_io.NUM_GRID_CELL_COLUMN: numpy.array([], dtype=int),
            storm_id_var_name: numpy.array([], dtype=int)
        }
    else:
        sparse_grid_dict = {
            radar_io.GRID_ROW_COLUMN:
            netcdf_dataset.variables[radar_io.GRID_ROW_COLUMN_ORIG][:],
            radar_io.GRID_COLUMN_COLUMN:
            netcdf_dataset.variables[radar_io.GRID_COLUMN_COLUMN_ORIG][:],
            radar_io.NUM_GRID_CELL_COLUMN:
            netcdf_dataset.variables[radar_io.NUM_GRID_CELL_COLUMN_ORIG][:],
            storm_id_var_name:
            netcdf_dataset.variables[storm_id_var_name_orig][:]
        }

    netcdf_dataset.close()
    sparse_grid_table = pandas.DataFrame.from_dict(sparse_grid_dict)
    numeric_storm_id_matrix, _, _ = (radar_s2f.sparse_to_full_grid(
        sparse_grid_table, metadata_dict))
    polygon_table = _storm_id_matrix_to_coord_lists(numeric_storm_id_matrix)

    num_storms = len(polygon_table.index)
    unix_times_sec = numpy.full(num_storms,
                                metadata_dict[radar_io.UNIX_TIME_COLUMN],
                                dtype=int)
    spc_dates_unix_sec = numpy.full(num_storms, spc_date_unix_sec, dtype=int)
    tracking_start_times_unix_sec = numpy.full(num_storms,
                                               tracking_start_time_unix_sec,
                                               dtype=int)
    tracking_end_times_unix_sec = numpy.full(num_storms,
                                             tracking_end_time_unix_sec,
                                             dtype=int)

    spc_date_string = time_conversion.time_to_spc_date_string(
        spc_date_unix_sec)
    storm_ids = _append_spc_date_to_storm_ids(
        polygon_table[tracking_io.STORM_ID_COLUMN].values, spc_date_string)

    simple_array = numpy.full(num_storms, numpy.nan)
    object_array = numpy.full(num_storms, numpy.nan, dtype=object)
    nested_array = polygon_table[[
        tracking_io.STORM_ID_COLUMN, tracking_io.STORM_ID_COLUMN
    ]].values.tolist()

    argument_dict = {
        tracking_io.STORM_ID_COLUMN: storm_ids,
        tracking_io.TIME_COLUMN: unix_times_sec,
        tracking_io.SPC_DATE_COLUMN: spc_dates_unix_sec,
        tracking_io.TRACKING_START_TIME_COLUMN: tracking_start_times_unix_sec,
        tracking_io.TRACKING_END_TIME_COLUMN: tracking_end_times_unix_sec,
        tracking_io.CENTROID_LAT_COLUMN: simple_array,
        tracking_io.CENTROID_LNG_COLUMN: simple_array,
        tracking_io.GRID_POINT_LAT_COLUMN: nested_array,
        tracking_io.GRID_POINT_LNG_COLUMN: nested_array,
        tracking_io.POLYGON_OBJECT_LATLNG_COLUMN: object_array,
        tracking_io.POLYGON_OBJECT_ROWCOL_COLUMN: object_array
    }
    polygon_table = polygon_table.assign(**argument_dict)

    for i in range(num_storms):
        these_vertex_rows, these_vertex_columns = (
            polygons.grid_points_in_poly_to_vertices(
                polygon_table[tracking_io.GRID_POINT_ROW_COLUMN].values[i],
                polygon_table[tracking_io.GRID_POINT_COLUMN_COLUMN].values[i]))

        (polygon_table[tracking_io.GRID_POINT_ROW_COLUMN].values[i],
         polygon_table[tracking_io.GRID_POINT_COLUMN_COLUMN].values[i]) = (
             polygons.simple_polygon_to_grid_points(these_vertex_rows,
                                                    these_vertex_columns))

        (polygon_table[tracking_io.GRID_POINT_LAT_COLUMN].values[i],
         polygon_table[tracking_io.GRID_POINT_LNG_COLUMN].values[i]) = (
             radar_io.rowcol_to_latlng(
                 polygon_table[tracking_io.GRID_POINT_ROW_COLUMN].values[i],
                 polygon_table[tracking_io.GRID_POINT_COLUMN_COLUMN].values[i],
                 nw_grid_point_lat_deg=metadata_dict[
                     radar_io.NW_GRID_POINT_LAT_COLUMN],
                 nw_grid_point_lng_deg=metadata_dict[
                     radar_io.NW_GRID_POINT_LNG_COLUMN],
                 lat_spacing_deg=metadata_dict[radar_io.LAT_SPACING_COLUMN],
                 lng_spacing_deg=metadata_dict[radar_io.LNG_SPACING_COLUMN]))

        these_vertex_lat_deg, these_vertex_lng_deg = radar_io.rowcol_to_latlng(
            these_vertex_rows,
            these_vertex_columns,
            nw_grid_point_lat_deg=metadata_dict[
                radar_io.NW_GRID_POINT_LAT_COLUMN],
            nw_grid_point_lng_deg=metadata_dict[
                radar_io.NW_GRID_POINT_LNG_COLUMN],
            lat_spacing_deg=metadata_dict[radar_io.LAT_SPACING_COLUMN],
            lng_spacing_deg=metadata_dict[radar_io.LNG_SPACING_COLUMN])

        (polygon_table[tracking_io.CENTROID_LAT_COLUMN].values[i],
         polygon_table[tracking_io.CENTROID_LNG_COLUMN].values[i]) = (
             polygons.get_latlng_centroid(these_vertex_lat_deg,
                                          these_vertex_lng_deg))

        polygon_table[tracking_io.POLYGON_OBJECT_ROWCOL_COLUMN].values[i] = (
            polygons.vertex_arrays_to_polygon_object(these_vertex_columns,
                                                     these_vertex_rows))
        polygon_table[tracking_io.POLYGON_OBJECT_LATLNG_COLUMN].values[i] = (
            polygons.vertex_arrays_to_polygon_object(these_vertex_lng_deg,
                                                     these_vertex_lat_deg))

    return polygon_table
コード例 #13
0
def read_data_from_sparse_grid_file(netcdf_file_name,
                                    field_name_orig,
                                    data_source,
                                    sentinel_values,
                                    raise_error_if_fails=True):
    """Reads sparse radar grid from raw (either MYRORSS or MRMS) file.

    This file should contain one radar field at one height and valid time.

    :param netcdf_file_name: Path to input file.
    :param field_name_orig: Name of radar field in original (either MYRORSS or
        MRMS) format.
    :param data_source: Data source (string).
    :param sentinel_values: 1-D numpy array of sentinel values.
    :param raise_error_if_fails: Boolean flag.  If True and file cannot be read,
        this method will raise an error.  If False and file cannot be read, will
        return None.
    :return: sparse_grid_table: pandas DataFrame with the following columns.
        Each row corresponds to one grid point.
    sparse_grid_table.grid_row: Row index.
    sparse_grid_table.grid_column: Column index.
    sparse_grid_table.<field_name>: Radar measurement (column name is produced
        by _field_name_orig_to_new).
    sparse_grid_table.num_grid_cells: Number of consecutive grid points with the
        same radar measurement.  Counting is row-major (to the right along the
        row, then down to the next column if necessary).
    """

    error_checking.assert_file_exists(netcdf_file_name)
    error_checking.assert_is_numpy_array_without_nan(sentinel_values)
    error_checking.assert_is_numpy_array(sentinel_values, num_dimensions=1)

    netcdf_dataset = netcdf_io.open_netcdf(netcdf_file_name,
                                           raise_error_if_fails)
    if netcdf_dataset is None:
        return None

    field_name = radar_utils.field_name_orig_to_new(
        field_name_orig=field_name_orig, data_source_name=data_source)
    num_values = len(netcdf_dataset.variables[GRID_ROW_COLUMN_ORIG])

    if num_values == 0:
        sparse_grid_dict = {
            GRID_ROW_COLUMN: numpy.array([], dtype=int),
            GRID_COLUMN_COLUMN: numpy.array([], dtype=int),
            NUM_GRID_CELL_COLUMN: numpy.array([], dtype=int),
            field_name: numpy.array([])
        }
    else:
        sparse_grid_dict = {
            GRID_ROW_COLUMN:
            netcdf_dataset.variables[GRID_ROW_COLUMN_ORIG][:],
            GRID_COLUMN_COLUMN:
            netcdf_dataset.variables[GRID_COLUMN_COLUMN_ORIG][:],
            NUM_GRID_CELL_COLUMN:
            netcdf_dataset.variables[NUM_GRID_CELL_COLUMN_ORIG][:],
            field_name:
            netcdf_dataset.variables[field_name_orig][:]
        }

    netcdf_dataset.close()
    sparse_grid_table = pandas.DataFrame.from_dict(sparse_grid_dict)
    return _remove_sentinels_from_sparse_grid(sparse_grid_table,
                                              field_name=field_name,
                                              sentinel_values=sentinel_values)
コード例 #14
0
def read_metadata_from_raw_file(netcdf_file_name, data_source=None,
                                raise_error_if_fails=True):
    """Reads metadata raw (either MYRORSS or MRMS) file..

    This file should contain one radar field at one height and one time step.

    :param netcdf_file_name: Path to input file.
    :param data_source: Data source (either "myrorss" or "mrms").
    :param raise_error_if_fails: Boolean flag.  If True and file cannot be
        opened, this method will raise an error.  If False and file cannot be
        opened, this method will return None.
    :return: metadata_dict: Dictionary with the following keys.
    metadata_dict['nw_grid_point_lat_deg']: Latitude (deg N) of northwesternmost
        grid point.
    metadata_dict['nw_grid_point_lng_deg']: Longitude (deg E) of
        northwesternmost grid point.
    metadata_dict['lat_spacing_deg']: Spacing (deg N) between adjacent rows.
    metadata_dict['lng_spacing_deg']: Spacing (deg E) between adjacent columns.
    metadata_dict['num_lat_in_grid']: Number of rows (unique grid-point
        latitudes).
    metadata_dict['num_lng_in_grid']: Number of columns (unique grid-point
        longitudes).
    metadata_dict['height_m_agl']: Height (metres above ground level).
    metadata_dict['unix_time_sec']: Time in Unix format.
    metadata_dict['field_name']: Name of radar field in new format.
    metadata_dict['field_name_orig']: Name of radar field in original (MYRORSS
        or MRMS) format.
    metadata_dict['sentinel_values']: 1-D numpy array of sentinel values.
    """

    error_checking.assert_file_exists(netcdf_file_name)
    netcdf_dataset = netcdf_io.open_netcdf(netcdf_file_name,
                                           raise_error_if_fails)
    if netcdf_dataset is None:
        return None

    field_name_orig = str(getattr(netcdf_dataset, FIELD_NAME_COLUMN_ORIG))

    metadata_dict = {
        NW_GRID_POINT_LAT_COLUMN: getattr(netcdf_dataset,
                                          NW_GRID_POINT_LAT_COLUMN_ORIG),
        NW_GRID_POINT_LNG_COLUMN: lng_conversion.convert_lng_positive_in_west(
            getattr(netcdf_dataset, NW_GRID_POINT_LNG_COLUMN_ORIG),
            allow_nan=False),
        LAT_SPACING_COLUMN: getattr(netcdf_dataset, LAT_SPACING_COLUMN_ORIG),
        LNG_SPACING_COLUMN: getattr(netcdf_dataset, LNG_SPACING_COLUMN_ORIG),
        NUM_LAT_COLUMN: netcdf_dataset.dimensions[NUM_LAT_COLUMN_ORIG].size + 1,
        NUM_LNG_COLUMN: netcdf_dataset.dimensions[NUM_LNG_COLUMN_ORIG].size + 1,
        HEIGHT_COLUMN: getattr(netcdf_dataset, HEIGHT_COLUMN_ORIG),
        UNIX_TIME_COLUMN: getattr(netcdf_dataset, UNIX_TIME_COLUMN_ORIG),
        FIELD_NAME_COLUMN_ORIG: field_name_orig,
        FIELD_NAME_COLUMN: _field_name_orig_to_new(field_name_orig,
                                                   data_source=data_source)}

    metadata_dict[NW_GRID_POINT_LAT_COLUMN] = rounder.floor_to_nearest(
        metadata_dict[NW_GRID_POINT_LAT_COLUMN],
        metadata_dict[LAT_SPACING_COLUMN])
    metadata_dict[NW_GRID_POINT_LNG_COLUMN] = rounder.ceiling_to_nearest(
        metadata_dict[NW_GRID_POINT_LNG_COLUMN],
        metadata_dict[LNG_SPACING_COLUMN])

    sentinel_values = numpy.full(len(SENTINEL_VALUE_COLUMNS_ORIG), numpy.nan)
    for i in range(len(SENTINEL_VALUE_COLUMNS_ORIG)):
        sentinel_values[i] = getattr(netcdf_dataset,
                                     SENTINEL_VALUE_COLUMNS_ORIG[i])

    metadata_dict.update({SENTINEL_VALUE_COLUMN: sentinel_values})
    netcdf_dataset.close()
    return metadata_dict
コード例 #15
0
def read_file(netcdf_file_name,
              field_name,
              valid_time_unix_sec,
              pressure_level_mb=None):
    """Reads data from NetCDF file.

    This method will extract one field at one pressure level (or surface) at one
    time.

    M = number of rows in grid
    N = number of columns in grid

    :param netcdf_file_name: Path to input file.
    :param field_name: Field to extract (must be accepted by
        `processed_narr_io.check_field_name`).
    :param valid_time_unix_sec: Valid time.
    :param pressure_level_mb: [used only if file contains isobaric data]
        Pressure level to extract (millibars).
    :return: data_matrix: M-by-N numpy array with values of the given field at
        the given pressure level (or surface).
    """

    field_name_orig = _std_to_netcdf_field_name(field_name)
    valid_time_narr_hours = _unix_to_narr_time(valid_time_unix_sec)

    if pressure_level_mb is None:

        # TODO(thunderhoser): This is a HACK.
        if field_name_orig == HEIGHT_NAME_NETCDF:
            field_name_orig = 'pres'
        if field_name_orig == VERTICAL_VELOCITY_NAME_NETCDF:
            field_name_orig = 'vvel'
    else:
        error_checking.assert_is_integer(pressure_level_mb)

    dataset_object = netcdf_io.open_netcdf(netcdf_file_name=netcdf_file_name,
                                           raise_error_if_fails=True)

    is_surface = PRESSURE_KEY not in dataset_object.variables

    all_times_narr_hours = numpy.round(
        dataset_object.variables[TIME_KEY]).astype(int)

    time_index = numpy.where(
        all_times_narr_hours == valid_time_narr_hours)[0][0]

    if is_surface:
        field_matrix = numpy.array(
            dataset_object.variables[field_name_orig][time_index, ...])
    else:
        all_pressure_levels_mb = numpy.round(
            dataset_object.variables[PRESSURE_KEY]).astype(int)

        pressure_index = numpy.where(
            all_pressure_levels_mb == pressure_level_mb)[0][0]

        field_matrix = numpy.array(
            dataset_object.variables[field_name_orig][time_index,
                                                      pressure_index, ...])

    return _remove_sentinel_values(field_matrix)
コード例 #16
0
def read_metadata_from_raw_file(netcdf_file_name,
                                data_source,
                                raise_error_if_fails=True):
    """Reads metadata from raw (either MYRORSS or MRMS) file.

    This file should contain one radar field at one height and valid time.

    :param netcdf_file_name: Path to input file.
    :param data_source: Data source (string).
    :param raise_error_if_fails: Boolean flag.  If True and file cannot be read,
        this method will raise an error.  If False and file cannot be read, will
        return None.
    :return: metadata_dict: Dictionary with the following keys.
    metadata_dict['nw_grid_point_lat_deg']: Latitude (deg N) of northwesternmost
        grid point.
    metadata_dict['nw_grid_point_lng_deg']: Longitude (deg E) of
        northwesternmost grid point.
    metadata_dict['lat_spacing_deg']: Spacing (deg N) between meridionally
        adjacent grid points.
    metadata_dict['lng_spacing_deg']: Spacing (deg E) between zonally adjacent
        grid points.
    metadata_dict['num_lat_in_grid']: Number of rows (unique grid-point
        latitudes).
    metadata_dict['num_lng_in_grid']: Number of columns (unique grid-point
        longitudes).
    metadata_dict['height_m_asl']: Radar height (metres above ground level).
    metadata_dict['unix_time_sec']: Valid time.
    metadata_dict['field_name']: Name of radar field in GewitterGefahr format.
    metadata_dict['field_name_orig']: Name of radar field in original (either
        MYRORSS or MRMS) format.
    metadata_dict['sentinel_values']: 1-D numpy array of sentinel values.
    """

    error_checking.assert_file_exists(netcdf_file_name)
    netcdf_dataset = netcdf_io.open_netcdf(netcdf_file_name,
                                           raise_error_if_fails)
    if netcdf_dataset is None:
        return None

    field_name_orig = str(getattr(netcdf_dataset, FIELD_NAME_COLUMN_ORIG))

    metadata_dict = {
        radar_utils.NW_GRID_POINT_LAT_COLUMN:
        getattr(netcdf_dataset, NW_GRID_POINT_LAT_COLUMN_ORIG),
        radar_utils.NW_GRID_POINT_LNG_COLUMN:
        lng_conversion.convert_lng_positive_in_west(getattr(
            netcdf_dataset, NW_GRID_POINT_LNG_COLUMN_ORIG),
                                                    allow_nan=False),
        radar_utils.LAT_SPACING_COLUMN:
        getattr(netcdf_dataset, LAT_SPACING_COLUMN_ORIG),
        radar_utils.LNG_SPACING_COLUMN:
        getattr(netcdf_dataset, LNG_SPACING_COLUMN_ORIG),
        radar_utils.NUM_LAT_COLUMN:
        netcdf_dataset.dimensions[NUM_LAT_COLUMN_ORIG].size + 1,
        radar_utils.NUM_LNG_COLUMN:
        netcdf_dataset.dimensions[NUM_LNG_COLUMN_ORIG].size + 1,
        radar_utils.HEIGHT_COLUMN:
        getattr(netcdf_dataset, HEIGHT_COLUMN_ORIG),
        radar_utils.UNIX_TIME_COLUMN:
        getattr(netcdf_dataset, UNIX_TIME_COLUMN_ORIG),
        FIELD_NAME_COLUMN_ORIG:
        field_name_orig,
        radar_utils.FIELD_NAME_COLUMN:
        radar_utils.field_name_orig_to_new(field_name_orig=field_name_orig,
                                           data_source_name=data_source)
    }

    latitude_spacing_deg = metadata_dict[radar_utils.LAT_SPACING_COLUMN]
    longitude_spacing_deg = metadata_dict[radar_utils.LNG_SPACING_COLUMN]

    # TODO(thunderhoser): The following "if" condition is a hack.  The purpose
    # is to change grid corners only for actual MYRORSS data, not GridRad data
    # in MYRORSS format.
    if latitude_spacing_deg < 0.011 and longitude_spacing_deg < 0.011:
        metadata_dict[radar_utils.NW_GRID_POINT_LAT_COLUMN] = (
            rounder.floor_to_nearest(
                metadata_dict[radar_utils.NW_GRID_POINT_LAT_COLUMN],
                metadata_dict[radar_utils.LAT_SPACING_COLUMN]))
        metadata_dict[radar_utils.NW_GRID_POINT_LNG_COLUMN] = (
            rounder.ceiling_to_nearest(
                metadata_dict[radar_utils.NW_GRID_POINT_LNG_COLUMN],
                metadata_dict[radar_utils.LNG_SPACING_COLUMN]))

    sentinel_values = []
    for this_column in SENTINEL_VALUE_COLUMNS_ORIG:
        sentinel_values.append(getattr(netcdf_dataset, this_column))

    metadata_dict.update(
        {radar_utils.SENTINEL_VALUE_COLUMN: numpy.array(sentinel_values)})
    netcdf_dataset.close()
    return metadata_dict
コード例 #17
0
def read_polygons_from_netcdf(netcdf_file_name,
                              metadata_dict,
                              spc_date_string,
                              tracking_start_time_unix_sec,
                              tracking_end_time_unix_sec,
                              raise_error_if_fails=True):
    """Reads storm polygons (outlines of storm cells) from NetCDF file.

    P = number of grid points in storm cell (different for each storm cell)
    V = number of vertices in storm polygon (different for each storm cell)

    If file cannot be opened, returns None.

    :param netcdf_file_name: Path to input file.
    :param metadata_dict: Dictionary with metadata for NetCDF file, created by
        `myrorss_and_mrms_io.read_metadata_from_raw_file`.
    :param spc_date_string: SPC date (format "yyyymmdd").
    :param tracking_start_time_unix_sec: Start time for tracking period.  This
        can be found by `get_start_end_times_for_spc_date`.
    :param tracking_end_time_unix_sec: End time for tracking period.  This can
        be found by `get_start_end_times_for_spc_date`.
    :param raise_error_if_fails: Boolean flag.  If True and file cannot be
        opened, this method will raise an error.
    :return: polygon_table: pandas DataFrame with the following columns.  Each
        row is one storm object.
    polygon_table.primary_id_string: See documentation for
        `storm_tracking_io.write_file`.
    polygon_table.valid_time_unix_sec: Same.
    polygon_table.spc_date_string: Same.
    polygon_table.tracking_start_time_unix_sec: Same.
    polygon_table.tracking_end_time_unix_sec: Same.
    polygon_table.centroid_latitude_deg: Same.
    polygon_table.centroid_longitude_deg: Same.
    polygon_table.grid_point_latitudes_deg: Same.
    polygon_table.grid_point_longitudes_deg: Same.
    polygon_table.grid_point_rows: Same.
    polygon_table.grid_point_columns: Same.
    polygon_table.polygon_object_latlng_deg: Same.
    polygon_table.polygon_object_rowcol: Same.
    """

    error_checking.assert_file_exists(netcdf_file_name)
    error_checking.assert_is_integer(tracking_start_time_unix_sec)
    error_checking.assert_is_not_nan(tracking_start_time_unix_sec)
    error_checking.assert_is_integer(tracking_end_time_unix_sec)
    error_checking.assert_is_not_nan(tracking_end_time_unix_sec)

    netcdf_dataset = netcdf_io.open_netcdf(netcdf_file_name,
                                           raise_error_if_fails)
    if netcdf_dataset is None:
        return None

    storm_id_column = metadata_dict[radar_utils.FIELD_NAME_COLUMN]
    storm_id_column_orig = metadata_dict[
        myrorss_and_mrms_io.FIELD_NAME_COLUMN_ORIG]
    num_values = len(
        netcdf_dataset.variables[myrorss_and_mrms_io.GRID_ROW_COLUMN_ORIG])

    if num_values == 0:
        sparse_grid_dict = {
            myrorss_and_mrms_io.GRID_ROW_COLUMN: numpy.array([], dtype=int),
            myrorss_and_mrms_io.GRID_COLUMN_COLUMN: numpy.array([], dtype=int),
            myrorss_and_mrms_io.NUM_GRID_CELL_COLUMN: numpy.array([],
                                                                  dtype=int),
            storm_id_column: numpy.array([], dtype=int)
        }
    else:
        sparse_grid_dict = {
            myrorss_and_mrms_io.GRID_ROW_COLUMN:
            netcdf_dataset.variables[myrorss_and_mrms_io.GRID_ROW_COLUMN_ORIG]
            [:],
            myrorss_and_mrms_io.GRID_COLUMN_COLUMN:
            netcdf_dataset.variables[
                myrorss_and_mrms_io.GRID_COLUMN_COLUMN_ORIG][:],
            myrorss_and_mrms_io.NUM_GRID_CELL_COLUMN:
            netcdf_dataset.variables[
                myrorss_and_mrms_io.NUM_GRID_CELL_COLUMN_ORIG][:],
            storm_id_column:
            netcdf_dataset.variables[storm_id_column_orig][:]
        }

    netcdf_dataset.close()

    sparse_grid_table = pandas.DataFrame.from_dict(sparse_grid_dict)
    numeric_id_matrix = radar_s2f.sparse_to_full_grid(sparse_grid_table,
                                                      metadata_dict)[0]

    polygon_table = _id_matrix_to_coord_lists(numeric_id_matrix)
    num_storms = len(polygon_table.index)

    valid_times_unix_sec = numpy.full(
        num_storms, metadata_dict[radar_utils.UNIX_TIME_COLUMN], dtype=int)
    spc_date_strings = num_storms * [
        time_conversion.time_to_spc_date_string(valid_times_unix_sec[0])
    ]

    tracking_start_times_unix_sec = numpy.full(num_storms,
                                               tracking_start_time_unix_sec,
                                               dtype=int)
    tracking_end_times_unix_sec = numpy.full(num_storms,
                                             tracking_end_time_unix_sec,
                                             dtype=int)

    simple_array = numpy.full(num_storms, numpy.nan)
    object_array = numpy.full(num_storms, numpy.nan, dtype=object)
    nested_array = polygon_table[[
        tracking_utils.PRIMARY_ID_COLUMN, tracking_utils.PRIMARY_ID_COLUMN
    ]].values.tolist()

    argument_dict = {
        tracking_utils.VALID_TIME_COLUMN: valid_times_unix_sec,
        tracking_utils.SPC_DATE_COLUMN: spc_date_strings,
        tracking_utils.TRACKING_START_TIME_COLUMN:
        tracking_start_times_unix_sec,
        tracking_utils.TRACKING_END_TIME_COLUMN: tracking_end_times_unix_sec,
        tracking_utils.CENTROID_LATITUDE_COLUMN: simple_array,
        tracking_utils.CENTROID_LONGITUDE_COLUMN: simple_array,
        tracking_utils.LATITUDES_IN_STORM_COLUMN: nested_array,
        tracking_utils.LONGITUDES_IN_STORM_COLUMN: nested_array,
        tracking_utils.LATLNG_POLYGON_COLUMN: object_array,
        tracking_utils.ROWCOL_POLYGON_COLUMN: object_array
    }

    polygon_table = polygon_table.assign(**argument_dict)

    for i in range(num_storms):
        these_vertex_rows, these_vertex_columns = (
            polygons.grid_points_in_poly_to_vertices(
                grid_point_row_indices=polygon_table[
                    tracking_utils.ROWS_IN_STORM_COLUMN].values[i],
                grid_point_column_indices=polygon_table[
                    tracking_utils.COLUMNS_IN_STORM_COLUMN].values[i]))

        (polygon_table[tracking_utils.ROWS_IN_STORM_COLUMN].values[i],
         polygon_table[tracking_utils.COLUMNS_IN_STORM_COLUMN].values[i]
         ) = polygons.simple_polygon_to_grid_points(
             vertex_row_indices=these_vertex_rows,
             vertex_column_indices=these_vertex_columns)

        (polygon_table[tracking_utils.LATITUDES_IN_STORM_COLUMN].values[i],
         polygon_table[tracking_utils.LONGITUDES_IN_STORM_COLUMN].values[i]
         ) = radar_utils.rowcol_to_latlng(
             grid_rows=polygon_table[
                 tracking_utils.ROWS_IN_STORM_COLUMN].values[i],
             grid_columns=polygon_table[
                 tracking_utils.COLUMNS_IN_STORM_COLUMN].values[i],
             nw_grid_point_lat_deg=metadata_dict[
                 radar_utils.NW_GRID_POINT_LAT_COLUMN],
             nw_grid_point_lng_deg=metadata_dict[
                 radar_utils.NW_GRID_POINT_LNG_COLUMN],
             lat_spacing_deg=metadata_dict[radar_utils.LAT_SPACING_COLUMN],
             lng_spacing_deg=metadata_dict[radar_utils.LNG_SPACING_COLUMN])

        these_vertex_lat_deg, these_vertex_lng_deg = (
            radar_utils.rowcol_to_latlng(
                grid_rows=these_vertex_rows,
                grid_columns=these_vertex_columns,
                nw_grid_point_lat_deg=metadata_dict[
                    radar_utils.NW_GRID_POINT_LAT_COLUMN],
                nw_grid_point_lng_deg=metadata_dict[
                    radar_utils.NW_GRID_POINT_LNG_COLUMN],
                lat_spacing_deg=metadata_dict[radar_utils.LAT_SPACING_COLUMN],
                lng_spacing_deg=metadata_dict[radar_utils.LNG_SPACING_COLUMN]))

        (polygon_table[tracking_utils.CENTROID_LATITUDE_COLUMN].values[i],
         polygon_table[tracking_utils.CENTROID_LONGITUDE_COLUMN].values[i]
         ) = geodetic_utils.get_latlng_centroid(
             latitudes_deg=these_vertex_lat_deg,
             longitudes_deg=these_vertex_lng_deg)

        polygon_table[tracking_utils.ROWCOL_POLYGON_COLUMN].values[i] = (
            polygons.vertex_arrays_to_polygon_object(
                exterior_x_coords=these_vertex_columns,
                exterior_y_coords=these_vertex_rows))

        polygon_table[tracking_utils.LATLNG_POLYGON_COLUMN].values[i] = (
            polygons.vertex_arrays_to_polygon_object(
                exterior_x_coords=these_vertex_lng_deg,
                exterior_y_coords=these_vertex_lat_deg))

    primary_id_strings = _append_spc_date_to_storm_ids(
        primary_id_strings=polygon_table[
            tracking_utils.PRIMARY_ID_COLUMN].values,
        spc_date_string=spc_date_string)

    return polygon_table.assign(
        **{tracking_utils.PRIMARY_ID_COLUMN: primary_id_strings})