Пример #1
0
def get_elevations(latitudes_deg, longitudes_deg, working_dir_name=None):
    """Returns elevation of each point.

    N = number of points

    :param latitudes_deg: length-N numpy array of latitudes (deg N).
    :param longitudes_deg: length-N numpy array of longitudes (deg E).
    :param working_dir_name: See doc for `__init__` in class
        `ElevationFileHandler`.
    :return: elevations_m_asl: length-N numpy array of elevations (metres above
        sea level).
    """

    error_checking.assert_is_valid_lat_numpy_array(latitudes_deg)
    error_checking.assert_is_numpy_array(latitudes_deg, num_dimensions=1)
    num_points = len(latitudes_deg)

    longitudes_deg = lng_conversion.convert_lng_negative_in_west(
        longitudes_deg, allow_nan=False)
    error_checking.assert_is_numpy_array(longitudes_deg,
                                         exact_dimensions=numpy.array(
                                             [num_points]))

    srtm_data_object = None
    elevations_m_asl = numpy.full(num_points, numpy.nan)

    for i in range(num_points):
        elevations_m_asl[i], srtm_data_object = _get_elevation(
            latitude_deg=latitudes_deg[i],
            longitude_deg=longitudes_deg[i],
            srtm_data_object=srtm_data_object,
            working_dir_name=working_dir_name)

    return elevations_m_asl
    def test_convert_lng_negative_in_west_inputs_positive(self):
        """Ensures correct output from convert_lng_negative_in_west.

        In this case, inputs are positive in western hemisphere.
        """

        these_longitudes_deg = lng_conversion.convert_lng_negative_in_west(
            LONGITUDES_POSITIVE_IN_WEST_DEG)
        self.assertTrue(
            numpy.allclose(these_longitudes_deg,
                           LONGITUDES_NEGATIVE_IN_WEST_DEG,
                           atol=TOLERANCE,
                           equal_nan=True))
    def test_convert_lng_negative_in_west_inputs_mixed(self):
        """Ensures correct output from convert_lng_negative_in_west.

        In this case, inputs have mixed signs.
        """

        these_longitudes_deg = lng_conversion.convert_lng_negative_in_west(
            LONGITUDES_MIXED_SIGNS_DEG)
        self.assertTrue(
            numpy.allclose(these_longitudes_deg,
                           LONGITUDES_NEGATIVE_IN_WEST_DEG,
                           atol=TOLERANCE,
                           equal_nan=True))
Пример #4
0
def write_field_to_myrorss_file(field_matrix,
                                netcdf_file_name,
                                field_name,
                                metadata_dict,
                                height_m_asl=None):
    """Writes field to MYRORSS-formatted file.

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

    :param field_matrix: M-by-N numpy array with one radar variable at one time.
        Latitude should increase down each column, and longitude should increase
        to the right along each row.
    :param netcdf_file_name: Path to output file.
    :param field_name: Name of radar field in GewitterGefahr format.
    :param metadata_dict: Dictionary created by either
        `gridrad_io.read_metadata_from_full_grid_file` or
        `radar_io.read_metadata_from_raw_file`.
    :param height_m_asl: Height of radar field (metres above sea level).
    """

    if field_name == radar_io.REFL_NAME:
        field_to_heights_dict_m_asl = radar_io.field_and_height_arrays_to_dict(
            [field_name],
            refl_heights_m_agl=numpy.array([height_m_asl]),
            data_source=radar_io.MYRORSS_SOURCE_ID)
    else:
        field_to_heights_dict_m_asl = radar_io.field_and_height_arrays_to_dict(
            [field_name],
            refl_heights_m_agl=None,
            data_source=radar_io.MYRORSS_SOURCE_ID)

    field_name = field_to_heights_dict_m_asl.keys()[0]
    radar_height_m_asl = field_to_heights_dict_m_asl[field_name][0]

    if field_name in radar_io.ECHO_TOP_NAMES:
        field_matrix = METRES_TO_KM * field_matrix
    field_name_myrorss = radar_io.field_name_new_to_orig(
        field_name, radar_io.MYRORSS_SOURCE_ID)

    file_system_utils.mkdir_recursive_if_necessary(file_name=netcdf_file_name)
    netcdf_dataset = Dataset(netcdf_file_name,
                             'w',
                             format='NETCDF3_64BIT_OFFSET')

    netcdf_dataset.setncattr(radar_io.FIELD_NAME_COLUMN_ORIG,
                             field_name_myrorss)
    netcdf_dataset.setncattr('DataType', 'SparseLatLonGrid')

    netcdf_dataset.setncattr(radar_io.NW_GRID_POINT_LAT_COLUMN_ORIG,
                             metadata_dict[radar_io.NW_GRID_POINT_LAT_COLUMN])
    netcdf_dataset.setncattr(
        radar_io.NW_GRID_POINT_LNG_COLUMN_ORIG,
        lng_conversion.convert_lng_negative_in_west(
            metadata_dict[radar_io.NW_GRID_POINT_LNG_COLUMN]))
    netcdf_dataset.setncattr(radar_io.HEIGHT_COLUMN_ORIG,
                             METRES_TO_KM * numpy.float(radar_height_m_asl))
    netcdf_dataset.setncattr(
        radar_io.UNIX_TIME_COLUMN_ORIG,
        numpy.int32(metadata_dict[radar_io.UNIX_TIME_COLUMN]))
    netcdf_dataset.setncattr('FractionalTime', 0.)

    netcdf_dataset.setncattr('attributes', ' ColorMap SubType Unit')
    netcdf_dataset.setncattr('ColorMap-unit', 'dimensionless')
    netcdf_dataset.setncattr('ColorMap-value', '')
    netcdf_dataset.setncattr('SubType-unit', 'dimensionless')
    netcdf_dataset.setncattr('SubType-value', numpy.float(radar_height_m_asl))
    netcdf_dataset.setncattr('Unit-unit', 'dimensionless')
    netcdf_dataset.setncattr('Unit-value', 'dimensionless')

    netcdf_dataset.setncattr(
        radar_io.LAT_SPACING_COLUMN_ORIG,
        rounder.round_to_nearest(metadata_dict[radar_io.LAT_SPACING_COLUMN],
                                 GRID_SPACING_MULTIPLE_DEG))
    netcdf_dataset.setncattr(
        radar_io.LNG_SPACING_COLUMN_ORIG,
        rounder.round_to_nearest(metadata_dict[radar_io.LNG_SPACING_COLUMN],
                                 GRID_SPACING_MULTIPLE_DEG))
    netcdf_dataset.setncattr(radar_io.SENTINEL_VALUE_COLUMNS_ORIG[0],
                             numpy.double(-99000.))
    netcdf_dataset.setncattr(radar_io.SENTINEL_VALUE_COLUMNS_ORIG[1],
                             numpy.double(-99001.))

    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_lats_deg, unique_grid_point_lngs_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]))

    num_grid_rows = len(unique_grid_point_lats_deg)
    num_grid_columns = len(unique_grid_point_lngs_deg)
    field_vector = numpy.reshape(field_matrix,
                                 num_grid_rows * num_grid_columns)

    grid_point_lat_matrix, grid_point_lng_matrix = (
        grids.latlng_vectors_to_matrices(unique_grid_point_lats_deg,
                                         unique_grid_point_lngs_deg))
    grid_point_lat_vector = numpy.reshape(grid_point_lat_matrix,
                                          num_grid_rows * num_grid_columns)
    grid_point_lng_vector = numpy.reshape(grid_point_lng_matrix,
                                          num_grid_rows * num_grid_columns)

    real_value_indices = numpy.where(numpy.invert(
        numpy.isnan(field_vector)))[0]
    netcdf_dataset.createDimension(radar_io.NUM_LAT_COLUMN_ORIG,
                                   num_grid_rows - 1)
    netcdf_dataset.createDimension(radar_io.NUM_LNG_COLUMN_ORIG,
                                   num_grid_columns - 1)
    netcdf_dataset.createDimension(radar_io.NUM_PIXELS_COLUMN_ORIG,
                                   len(real_value_indices))

    row_index_vector, column_index_vector = radar_io.latlng_to_rowcol(
        grid_point_lat_vector,
        grid_point_lng_vector,
        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])

    netcdf_dataset.createVariable(field_name_myrorss, numpy.single,
                                  (radar_io.NUM_PIXELS_COLUMN_ORIG, ))
    netcdf_dataset.createVariable(radar_io.GRID_ROW_COLUMN_ORIG, numpy.int16,
                                  (radar_io.NUM_PIXELS_COLUMN_ORIG, ))
    netcdf_dataset.createVariable(radar_io.GRID_COLUMN_COLUMN_ORIG,
                                  numpy.int16,
                                  (radar_io.NUM_PIXELS_COLUMN_ORIG, ))
    netcdf_dataset.createVariable(radar_io.NUM_GRID_CELL_COLUMN_ORIG,
                                  numpy.int32,
                                  (radar_io.NUM_PIXELS_COLUMN_ORIG, ))

    netcdf_dataset.variables[field_name_myrorss].setncattr(
        'BackgroundValue', numpy.int32(-99900))
    netcdf_dataset.variables[field_name_myrorss].setncattr(
        'units', 'dimensionless')
    netcdf_dataset.variables[field_name_myrorss].setncattr(
        'NumValidRuns', numpy.int32(len(real_value_indices)))

    netcdf_dataset.variables[field_name_myrorss][:] = field_vector[
        real_value_indices]
    netcdf_dataset.variables[radar_io.GRID_ROW_COLUMN_ORIG][:] = (
        row_index_vector[real_value_indices])
    netcdf_dataset.variables[radar_io.GRID_COLUMN_COLUMN_ORIG][:] = (
        column_index_vector[real_value_indices])
    netcdf_dataset.variables[radar_io.NUM_GRID_CELL_COLUMN_ORIG][:] = (
        numpy.full(len(real_value_indices), 1, dtype=int))

    netcdf_dataset.close()
Пример #5
0
def _find_domain_for_date(top_gridrad_dir_name, spc_date_string):
    """Finds GridRad domain for the given SPC date.

    If no GridRad files are found the given the SPC date, this method returns
    None for all output variables.

    :param top_gridrad_dir_name: See documentation at top of file.
    :param spc_date_string: SPC date or convective day (format "yyyymmdd").
    :return: domain_limits_deg: length-4 numpy array with
        [min latitude, max latitude, min longitude, max longitude].
        Units are deg N for latitude, deg W for longitude.
    """

    first_time_unix_sec = time_conversion.get_start_of_spc_date(spc_date_string)
    last_time_unix_sec = time_conversion.get_end_of_spc_date(spc_date_string)
    valid_times_unix_sec = time_periods.range_and_interval_to_list(
        start_time_unix_sec=first_time_unix_sec,
        end_time_unix_sec=last_time_unix_sec,
        time_interval_sec=TIME_INTERVAL_SEC, include_endpoint=True
    )

    num_times = len(valid_times_unix_sec)
    min_latitudes_deg = numpy.full(num_times, numpy.nan)
    max_latitudes_deg = numpy.full(num_times, numpy.nan)
    min_longitudes_deg = numpy.full(num_times, numpy.nan)
    max_longitudes_deg = numpy.full(num_times, numpy.nan)

    for i in range(num_times):
        this_file_name = gridrad_io.find_file(
            unix_time_sec=valid_times_unix_sec[i],
            top_directory_name=top_gridrad_dir_name,
            raise_error_if_missing=False
        )

        if not os.path.isfile(this_file_name):
            continue

        print('Reading data from: "{0:s}"...'.format(this_file_name))
        this_metadata_dict = gridrad_io.read_metadata_from_full_grid_file(
            this_file_name
        )

        max_latitudes_deg[i] = (
            this_metadata_dict[radar_utils.NW_GRID_POINT_LAT_COLUMN]
        )
        min_longitudes_deg[i] = (
            this_metadata_dict[radar_utils.NW_GRID_POINT_LNG_COLUMN]
        )

        max_longitudes_deg[i] = min_longitudes_deg[i] + (
            (this_metadata_dict[radar_utils.NUM_LNG_COLUMN] - 1) *
            this_metadata_dict[radar_utils.LNG_SPACING_COLUMN]
        )

        min_latitudes_deg[i] = max_latitudes_deg[i] - (
            (this_metadata_dict[radar_utils.NUM_LAT_COLUMN] - 1) *
            this_metadata_dict[radar_utils.LAT_SPACING_COLUMN]
        )

    good_indices = numpy.where(numpy.invert(numpy.isnan(min_latitudes_deg)))[0]
    if len(good_indices) == 0:
        return None

    coord_matrix = numpy.vstack((
        min_latitudes_deg[good_indices], max_latitudes_deg[good_indices],
        min_longitudes_deg[good_indices], max_longitudes_deg[good_indices]
    ))
    coord_matrix, num_instances_by_row = numpy.unique(
        numpy.transpose(coord_matrix), axis=0, return_counts=True
    )

    print(coord_matrix)
    print(num_instances_by_row)

    domain_limits_deg = coord_matrix[numpy.argmax(num_instances_by_row), :]
    domain_limits_deg[2:] = -1 * lng_conversion.convert_lng_negative_in_west(
        longitudes_deg=domain_limits_deg[2:], allow_nan=False
    )

    return domain_limits_deg
def _handle_one_storm_cell(storm_object_table, primary_id_string,
                           conus_latitudes_deg, conus_longitudes_deg,
                           max_lead_time_sec):
    """Handles (either keeps or removes) one storm cell.

    In this case, a "storm cell" is a group of storm objects with the same
    primary ID.

    V = number of vertices in CONUS boundary

    :param storm_object_table: pandas DataFrame with columns listed in doc for
        `storm_tracking_io.write_file`.
    :param primary_id_string: Primary ID of storm cell.
    :param conus_latitudes_deg: length-V numpy array of latitudes (deg N) in
        boundary.
    :param conus_longitudes_deg: length-V numpy array of longitudes (deg E) in
        boundary.
    :param max_lead_time_sec: See documentation at top of file.
    :return: bad_object_indices: 1-D numpy array with indices of bad storm
        objects (those with successor outside CONUS).  These are row indices for
        `storm_object_table`.
    """

    object_in_cell_indices = numpy.where(storm_object_table[
        tracking_utils.PRIMARY_ID_COLUMN].values == primary_id_string)[0]

    query_latitudes_deg = []
    query_longitudes_deg = []
    query_object_indices = []
    num_storm_objects = len(object_in_cell_indices)

    for i in range(num_storm_objects):
        j = object_in_cell_indices[i]

        this_polygon_object = (
            storm_object_table[tracking_utils.LATLNG_POLYGON_COLUMN].values[j])
        these_latitudes_deg = numpy.array(this_polygon_object.exterior.xy[1])
        these_longitudes_deg = numpy.array(this_polygon_object.exterior.xy[0])

        # Find northeasternmost point in storm boundary.
        this_index = numpy.argmax(these_latitudes_deg + these_longitudes_deg)
        query_latitudes_deg.append(these_latitudes_deg[this_index])
        query_longitudes_deg.append(these_longitudes_deg[this_index])
        query_object_indices.append(j)

        # Find southwesternmost point in storm boundary.
        this_index = numpy.argmin(these_latitudes_deg + these_longitudes_deg)
        query_latitudes_deg.append(these_latitudes_deg[this_index])
        query_longitudes_deg.append(these_longitudes_deg[this_index])
        query_object_indices.append(j)

        # Find northwesternmost point in storm boundary.
        this_index = numpy.argmax(these_latitudes_deg - these_longitudes_deg)
        query_latitudes_deg.append(these_latitudes_deg[this_index])
        query_longitudes_deg.append(these_longitudes_deg[this_index])
        query_object_indices.append(j)

        # Find northeasternmost point in storm boundary.
        this_index = numpy.argmax(these_longitudes_deg - these_latitudes_deg)
        query_latitudes_deg.append(these_latitudes_deg[this_index])
        query_longitudes_deg.append(these_longitudes_deg[this_index])
        query_object_indices.append(j)

    query_latitudes_deg = numpy.array(query_latitudes_deg)
    query_longitudes_deg = numpy.array(query_longitudes_deg)
    query_object_indices = numpy.array(query_object_indices, dtype=int)

    in_conus_flags = conus_boundary.find_points_in_conus(
        conus_latitudes_deg=conus_latitudes_deg,
        conus_longitudes_deg=conus_longitudes_deg,
        query_latitudes_deg=query_latitudes_deg,
        query_longitudes_deg=query_longitudes_deg,
        use_shortcuts=True,
        verbose=False)

    if numpy.all(in_conus_flags):
        return numpy.array([], dtype=int)

    first_bad_index = numpy.where(numpy.invert(in_conus_flags))[0][0]
    first_bad_longitude_deg = -1 * lng_conversion.convert_lng_negative_in_west(
        query_longitudes_deg[first_bad_index])
    print('Point ({0:.1f} deg N, {1:.1f} deg W) is not in CONUS!'.format(
        query_latitudes_deg[first_bad_index], first_bad_longitude_deg))

    object_not_in_conus_indices = numpy.unique(
        query_object_indices[in_conus_flags == False])
    bad_object_indices = numpy.array([], dtype=int)

    for i in object_not_in_conus_indices:
        these_indices = temporal_tracking.find_predecessors(
            storm_object_table=storm_object_table,
            target_row=i,
            num_seconds_back=max_lead_time_sec,
            max_num_sec_id_changes=1,
            return_all_on_path=True)

        bad_object_indices = numpy.concatenate(
            (bad_object_indices, these_indices))

    return numpy.unique(bad_object_indices)
Пример #7
0
def create_equidistant_grid(min_latitude_deg,
                            max_latitude_deg,
                            min_longitude_deg,
                            max_longitude_deg,
                            x_spacing_metres,
                            y_spacing_metres,
                            azimuthal=True):
    """Creates equidistant grid.

    M = number of rows
    N = number of columns

    :param min_latitude_deg: Minimum latitude (deg N) in grid.
    :param max_latitude_deg: Max latitude (deg N) in grid.
    :param min_longitude_deg: Minimum longitude (deg E) in grid.
    :param max_longitude_deg: Max longitude (deg E) in grid.
    :param x_spacing_metres: Spacing between grid points in adjacent columns.
    :param y_spacing_metres: Spacing between grid points in adjacent rows.
    :param azimuthal: Boolean flag.  If True, will create azimuthal equidistant
        grid.  If False, will create Lambert conformal grid.
    :return: grid_dict: Dictionary with the following keys.
    grid_dict['grid_point_x_coords_metres']: length-N numpy array with unique
        x-coordinates at grid points.
    grid_dict['grid_point_y_coords_metres']: length-M numpy array with unique
        y-coordinates at grid points.
    grid_dict['projection_object']: Instance of `pyproj.Proj` (used to convert
        between lat-long coordinates and the x-y coordinates of the grid).
    """

    # Check input args.
    error_checking.assert_is_valid_latitude(min_latitude_deg)
    error_checking.assert_is_valid_latitude(max_latitude_deg)
    error_checking.assert_is_greater(max_latitude_deg, min_latitude_deg)
    error_checking.assert_is_greater(x_spacing_metres, 0.)
    error_checking.assert_is_greater(y_spacing_metres, 0.)
    error_checking.assert_is_boolean(azimuthal)

    min_longitude_deg = lng_conversion.convert_lng_negative_in_west(
        min_longitude_deg, allow_nan=False)
    max_longitude_deg = lng_conversion.convert_lng_negative_in_west(
        max_longitude_deg, allow_nan=False)
    error_checking.assert_is_greater(max_longitude_deg, min_longitude_deg)

    # Create lat-long grid.
    num_grid_rows = 1 + int(
        numpy.round((max_latitude_deg - min_latitude_deg) /
                    DUMMY_LATITUDE_SPACING_DEG))
    num_grid_columns = 1 + int(
        numpy.round((max_longitude_deg - min_longitude_deg) /
                    DUMMY_LONGITUDE_SPACING_DEG))

    unique_latitudes_deg, unique_longitudes_deg = get_latlng_grid_points(
        min_latitude_deg=min_latitude_deg,
        min_longitude_deg=min_longitude_deg,
        lat_spacing_deg=DUMMY_LATITUDE_SPACING_DEG,
        lng_spacing_deg=DUMMY_LONGITUDE_SPACING_DEG,
        num_rows=num_grid_rows,
        num_columns=num_grid_columns)

    latitude_matrix_deg, longitude_matrix_deg = latlng_vectors_to_matrices(
        unique_latitudes_deg=unique_latitudes_deg,
        unique_longitudes_deg=unique_longitudes_deg)

    # Create projection.
    central_latitude_deg = 0.5 * (min_latitude_deg + max_latitude_deg)
    central_longitude_deg = 0.5 * (min_longitude_deg + max_longitude_deg)

    if azimuthal:
        projection_object = projections.init_azimuthal_equidistant_projection(
            central_latitude_deg=central_latitude_deg,
            central_longitude_deg=central_longitude_deg)
    else:
        projection_object = projections.init_lcc_projection(
            standard_latitudes_deg=numpy.full(2, central_latitude_deg),
            central_longitude_deg=central_longitude_deg)

    # Convert lat-long grid to preliminary x-y grid.
    prelim_x_matrix_metres, prelim_y_matrix_metres = (
        projections.project_latlng_to_xy(latitudes_deg=latitude_matrix_deg,
                                         longitudes_deg=longitude_matrix_deg,
                                         projection_object=projection_object))

    # Find corners of preliminary x-y grid.
    x_min_metres = numpy.min(prelim_x_matrix_metres)
    x_max_metres = numpy.max(prelim_x_matrix_metres)
    y_min_metres = numpy.min(prelim_y_matrix_metres)
    y_max_metres = numpy.max(prelim_y_matrix_metres)

    # Find corners of final x-y grid.
    x_min_metres = number_rounding.floor_to_nearest(x_min_metres,
                                                    x_spacing_metres)
    x_max_metres = number_rounding.ceiling_to_nearest(x_max_metres,
                                                      x_spacing_metres)
    y_min_metres = number_rounding.floor_to_nearest(y_min_metres,
                                                    y_spacing_metres)
    y_max_metres = number_rounding.ceiling_to_nearest(y_max_metres,
                                                      y_spacing_metres)

    # Create final x-y grid.
    num_grid_rows = 1 + int(
        numpy.round((y_max_metres - y_min_metres) / y_spacing_metres))
    num_grid_columns = 1 + int(
        numpy.round((x_max_metres - x_min_metres) / x_spacing_metres))

    unique_x_coords_metres, unique_y_coords_metres = get_xy_grid_points(
        x_min_metres=x_min_metres,
        y_min_metres=y_min_metres,
        x_spacing_metres=x_spacing_metres,
        y_spacing_metres=y_spacing_metres,
        num_rows=num_grid_rows,
        num_columns=num_grid_columns)

    return {
        X_COORDS_KEY: unique_x_coords_metres,
        Y_COORDS_KEY: unique_y_coords_metres,
        PROJECTION_KEY: projection_object
    }