def _center_points_latlng_to_rowcol(center_latitudes_deg,
                                    center_longitudes_deg,
                                    nw_grid_point_lat_deg=None,
                                    nw_grid_point_lng_deg=None,
                                    lat_spacing_deg=None,
                                    lng_spacing_deg=None):
    """Converts center points from lat-long to row-column coordinates.

    Each "center point" is meant for input to extract_points_as_2d_array.

    P = number of center points

    :param center_latitudes_deg: length-P numpy array of latitudes (deg N).
    :param center_longitudes_deg: length-P numpy array of longitudes (deg E).
    :param nw_grid_point_lat_deg: Latitude (deg N) of northwesternmost grid
        point.
    :param nw_grid_point_lng_deg: Longitude (deg E) of northwesternmost grid
        point.
    :param lat_spacing_deg: Spacing (deg N) between adjacent rows.
    :param lng_spacing_deg: Spacing (deg E) between adjacent columns.
    :return: center_row_indices: Row indices (half-integers) of center points.
    :return: center_column_indices: Column indices (half-integers) of center
        points.
    """

    center_row_indices, center_column_indices = radar_io.latlng_to_rowcol(
        center_latitudes_deg,
        center_longitudes_deg,
        nw_grid_point_lat_deg=nw_grid_point_lat_deg,
        nw_grid_point_lng_deg=nw_grid_point_lng_deg,
        lat_spacing_deg=lat_spacing_deg,
        lng_spacing_deg=lng_spacing_deg)

    return (rounder.round_to_half_integer(center_row_indices),
            rounder.round_to_half_integer(center_column_indices))
Beispiel #2
0
def get_grid_points_in_storm_objects(storm_object_table,
                                     metadata_dict_for_storm_objects,
                                     new_metadata_dict):
    """Finds grid points inside each storm object.

    :param storm_object_table: pandas DataFrame with columns specified by
        `storm_tracking_io.write_processed_file`.
    :param metadata_dict_for_storm_objects: Dictionary (with keys specified by
        `radar_io.read_metadata_from_raw_file`) describing grid used to create
        storm objects.
    :param new_metadata_dict: Dictionary (with keys specified by
        `radar_io.read_metadata_from_raw_file`) describing new grid, for which
        points in each storm object will be found.
    :return: storm_object_to_grid_points_table: pandas DataFrame with the
        following columns.  Each row is one storm object.
    storm_object_to_grid_points_table.storm_id: String ID for storm cell.
    storm_object_to_grid_points_table.grid_point_rows: 1-D numpy array with row
        indices (integers) of grid points in storm object.
    storm_object_to_grid_points_table.grid_point_columns: 1-D numpy array with
        column indices (integers) of grid points in storm object.
    """

    if _are_grids_equal(metadata_dict_for_storm_objects, new_metadata_dict):
        return storm_object_table[STORM_OBJECT_TO_GRID_PTS_COLUMNS]

    storm_object_to_grid_points_table = storm_object_table[
        STORM_OBJECT_TO_GRID_PTS_COLUMNS + GRID_POINT_LATLNG_COLUMNS]
    num_storm_objects = len(storm_object_to_grid_points_table.index)

    for i in range(num_storm_objects):
        (storm_object_to_grid_points_table[
            tracking_io.GRID_POINT_ROW_COLUMN].values[i],
         storm_object_to_grid_points_table[
             tracking_io.GRID_POINT_COLUMN_COLUMN].values[i]
         ) = (radar_io.latlng_to_rowcol(
             storm_object_to_grid_points_table[
                 tracking_io.GRID_POINT_LAT_COLUMN].values[i],
             storm_object_to_grid_points_table[
                 tracking_io.GRID_POINT_LNG_COLUMN].values[i],
             nw_grid_point_lat_deg=new_metadata_dict[
                 radar_io.NW_GRID_POINT_LAT_COLUMN],
             nw_grid_point_lng_deg=new_metadata_dict[
                 radar_io.NW_GRID_POINT_LNG_COLUMN],
             lat_spacing_deg=new_metadata_dict[radar_io.LAT_SPACING_COLUMN],
             lng_spacing_deg=new_metadata_dict[radar_io.LNG_SPACING_COLUMN]))

    return storm_object_to_grid_points_table[STORM_OBJECT_TO_GRID_PTS_COLUMNS]
    def test_latlng_to_rowcol(self):
        """Ensures correct output from latlng_to_rowcol."""

        (these_row_indices, these_column_indices) = radar_io.latlng_to_rowcol(
            GRID_POINT_LATITUDES_DEG,
            GRID_POINT_LONGITUDES_DEG,
            nw_grid_point_lat_deg=NW_GRID_POINT_LAT_DEG,
            nw_grid_point_lng_deg=NW_GRID_POINT_LNG_DEG,
            lat_spacing_deg=LAT_SPACING_DEG,
            lng_spacing_deg=LNG_SPACING_DEG)

        self.assertTrue(
            numpy.allclose(these_row_indices, GRID_ROW_INDICES,
                           atol=TOLERANCE))
        self.assertTrue(
            numpy.allclose(these_column_indices,
                           GRID_COLUMN_INDICES,
                           atol=TOLERANCE))
def read_storm_objects_from_raw_file(json_file_name):
    """Reads storm objects from raw file.

    This file should contain all storm objects for one tracking scale and one
    time step.

    P = number of grid points in given storm object
    V = number of vertices in bounding polygon of given storm object

    :param json_file_name: Path to input file.
    :return: storm_object_table: pandas DataFrame with the following columns.
    storm_object_table.storm_id: String ID for storm cell.
    storm_object_table.unix_time_sec: Time in Unix format.
    storm_object_table.spc_date_unix_sec: SPC date in Unix format.
    storm_object_table.tracking_start_time_unix_sec: Start time for tracking
        period.
    storm_object_table.tracking_end_time_unix_sec: End time for tracking
        period.
    storm_object_table.east_velocity_m_s01: Eastward velocity (m/s).
    storm_object_table.north_velocity_m_s01: Northward velocity (m/s).
    storm_object_table.age_sec: Age of storm cell (seconds).
    storm_object_table.centroid_lat_deg: Latitude at centroid of storm object
        (deg N).
    storm_object_table.centroid_lng_deg: Longitude at centroid of storm object
        (deg E).
    storm_object_table.grid_point_latitudes_deg: length-P numpy array with
        latitudes (deg N) of grid points in storm object.
    storm_object_table.grid_point_longitudes_deg: length-P numpy array with
        longitudes (deg E) of grid points in storm object.
    storm_object_table.grid_point_rows: length-P numpy array with row indices
        (integers) of grid points in storm object.
    storm_object_table.grid_point_columns: length-P numpy array with column
        indices (integers) of grid points in storm object.
    storm_object_table.polygon_object_latlng: Instance of
        `shapely.geometry.Polygon` with vertices in lat-long coordinates.
    storm_object_table.polygon_object_rowcol: Instance of
        `shapely.geometry.Polygon` with vertices in row-column coordinates.
    """

    error_checking.assert_file_exists(json_file_name)
    with open(json_file_name) as json_file_handle:
        probsevere_dict = json.load(json_file_handle)

    unix_time_sec = time_conversion.string_to_unix_sec(
        probsevere_dict[TIME_COLUMN_ORIG].encode('ascii', 'ignore'),
        TIME_FORMAT_IN_RAW_FILES)
    spc_date_unix_sec = time_conversion.time_to_spc_date_unix_sec(unix_time_sec)

    num_storms = len(probsevere_dict[FEATURES_COLUMN_ORIG])
    unix_times_sec = numpy.full(num_storms, unix_time_sec, 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)

    storm_ids = [None] * num_storms
    east_velocities_m_s01 = numpy.full(num_storms, numpy.nan)
    north_velocities_m_s01 = numpy.full(num_storms, numpy.nan)

    for i in range(num_storms):
        storm_ids[i] = str(
            probsevere_dict[FEATURES_COLUMN_ORIG][i][PROPERTIES_COLUMN_ORIG][
                STORM_ID_COLUMN_ORIG])
        east_velocities_m_s01[i] = float(
            probsevere_dict[FEATURES_COLUMN_ORIG][i][PROPERTIES_COLUMN_ORIG][
                EAST_VELOCITY_COLUMN_ORIG])
        north_velocities_m_s01[i] = -1 * float(
            probsevere_dict[FEATURES_COLUMN_ORIG][i][PROPERTIES_COLUMN_ORIG][
                NORTH_VELOCITY_COLUMN_ORIG])

    storm_object_dict = {
        tracking_io.STORM_ID_COLUMN: storm_ids,
        tracking_io.EAST_VELOCITY_COLUMN: east_velocities_m_s01,
        tracking_io.NORTH_VELOCITY_COLUMN: north_velocities_m_s01,
        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}
    storm_object_table = pandas.DataFrame.from_dict(storm_object_dict)
    storm_object_table = tracking_io.remove_rows_with_nan(storm_object_table)

    num_storms = len(storm_object_table.index)
    storm_ages_sec = numpy.full(num_storms, numpy.nan)

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

    argument_dict = {tracking_io.AGE_COLUMN: storm_ages_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.GRID_POINT_ROW_COLUMN: nested_array,
                     tracking_io.GRID_POINT_COLUMN_COLUMN: nested_array,
                     tracking_io.POLYGON_OBJECT_LATLNG_COLUMN: object_array,
                     tracking_io.POLYGON_OBJECT_ROWCOL_COLUMN: object_array}
    storm_object_table = storm_object_table.assign(**argument_dict)

    for i in range(num_storms):
        this_vertex_matrix_deg = numpy.asarray(
            probsevere_dict[FEATURES_COLUMN_ORIG][i][GEOMETRY_COLUMN_ORIG][
                COORDINATES_COLUMN_ORIG][0])
        these_vertex_lat_deg = this_vertex_matrix_deg[:, LAT_COLUMN_INDEX_ORIG]
        these_vertex_lng_deg = this_vertex_matrix_deg[:, LNG_COLUMN_INDEX_ORIG]

        (these_vertex_rows, these_vertex_columns) = radar_io.latlng_to_rowcol(
            these_vertex_lat_deg, these_vertex_lng_deg,
            nw_grid_point_lat_deg=NW_GRID_POINT_LAT_DEG,
            nw_grid_point_lng_deg=NW_GRID_POINT_LNG_DEG,
            lat_spacing_deg=GRID_LAT_SPACING_DEG,
            lng_spacing_deg=GRID_LNG_SPACING_DEG)

        these_vertex_rows, these_vertex_columns = (
            polygons.fix_probsevere_vertices(
                these_vertex_rows, these_vertex_columns))

        these_vertex_lat_deg, these_vertex_lng_deg = radar_io.rowcol_to_latlng(
            these_vertex_rows, these_vertex_columns,
            nw_grid_point_lat_deg=NW_GRID_POINT_LAT_DEG,
            nw_grid_point_lng_deg=NW_GRID_POINT_LNG_DEG,
            lat_spacing_deg=GRID_LAT_SPACING_DEG,
            lng_spacing_deg=GRID_LNG_SPACING_DEG)

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

        (storm_object_table[tracking_io.GRID_POINT_LAT_COLUMN].values[i],
         storm_object_table[tracking_io.GRID_POINT_LNG_COLUMN].values[i]) = (
             radar_io.rowcol_to_latlng(
                 storm_object_table[tracking_io.GRID_POINT_ROW_COLUMN].values[i],
                 storm_object_table[
                     tracking_io.GRID_POINT_COLUMN_COLUMN].values[i],
                 nw_grid_point_lat_deg=NW_GRID_POINT_LAT_DEG,
                 nw_grid_point_lng_deg=NW_GRID_POINT_LNG_DEG,
                 lat_spacing_deg=GRID_LAT_SPACING_DEG,
                 lng_spacing_deg=GRID_LNG_SPACING_DEG))

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

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

    return storm_object_table
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()