예제 #1
0
    def test_buffer_simple_polygon_large(self):
        """Ensures correct output from buffer_simple_polygon.

        In this case the buffer distance is larger.
        """

        this_buffer_polygon_object = polygons.buffer_simple_polygon(
            EXTERIOR_VERTEX_X_METRES,
            EXTERIOR_VERTEX_Y_METRES,
            max_buffer_dist_metres=LARGE_BUFFER_DIST_METRES,
            preserve_angles=True)

        this_buffer_vertex_dict = polygons.polygon_object_to_vertex_arrays(
            this_buffer_polygon_object)

        this_buffer_vertex_x_metres, this_buffer_vertex_y_metres = (
            polygons.merge_exterior_and_holes(
                this_buffer_vertex_dict[polygons.EXTERIOR_X_COLUMN],
                this_buffer_vertex_dict[polygons.EXTERIOR_Y_COLUMN],
                hole_x_coords_list=this_buffer_vertex_dict[
                    polygons.HOLE_X_COLUMN],
                hole_y_coords_list=this_buffer_vertex_dict[
                    polygons.HOLE_Y_COLUMN]))

        self.assertTrue(
            numpy.allclose(this_buffer_vertex_x_metres,
                           VERTEX_X_METRES_LARGE_BUFFER,
                           atol=TOLERANCE))
        self.assertTrue(
            numpy.allclose(this_buffer_vertex_y_metres,
                           VERTEX_Y_METRES_LARGE_BUFFER,
                           atol=TOLERANCE))
    def test_buffer_simple_polygon_large_inclusive(self):
        """Ensures correct output from buffer_simple_polygon.

        In this case the buffer is large and inclusive (includes original
        polygon).
        """

        this_buffered_polygon_object = polygons.buffer_simple_polygon(
            vertex_x_metres=EXTERIOR_VERTEX_X_METRES,
            vertex_y_metres=EXTERIOR_VERTEX_Y_METRES,
            max_buffer_dist_metres=LARGE_BUFFER_DIST_METRES,
            preserve_angles=True)

        this_buffer_vertex_dict = polygons.polygon_object_to_vertex_arrays(
            this_buffered_polygon_object)

        self.assertTrue(
            numpy.allclose(this_buffer_vertex_dict[polygons.EXTERIOR_X_COLUMN],
                           LARGE_BUFFER_VERTEX_X_METRES,
                           atol=TOLERANCE))
        self.assertTrue(
            numpy.allclose(this_buffer_vertex_dict[polygons.EXTERIOR_Y_COLUMN],
                           LARGE_BUFFER_VERTEX_Y_METRES,
                           atol=TOLERANCE))

        self.assertTrue(
            len(this_buffer_vertex_dict[polygons.HOLE_X_COLUMN]) == 0)
        self.assertTrue(
            len(this_buffer_vertex_dict[polygons.HOLE_Y_COLUMN]) == 0)
    def test_buffer_simple_polygon_exclusive(self):
        """Ensures correct output from buffer_simple_polygon.

        In this case the buffer is exclusive (does not include original
        polygon).
        """

        this_buffer_polygon_object = polygons.buffer_simple_polygon(
            EXTERIOR_VERTEX_X_METRES,
            EXTERIOR_VERTEX_Y_METRES,
            min_buffer_dist_metres=SMALL_BUFFER_DIST_METRES,
            max_buffer_dist_metres=LARGE_BUFFER_DIST_METRES,
            preserve_angles=True)

        this_buffer_vertex_dict = polygons.polygon_object_to_vertex_arrays(
            this_buffer_polygon_object)

        self.assertTrue(
            numpy.allclose(this_buffer_vertex_dict[polygons.EXTERIOR_X_COLUMN],
                           EXCLUSIVE_BUFFER_EXTERIOR_X_METRES,
                           atol=TOLERANCE))
        self.assertTrue(
            numpy.allclose(this_buffer_vertex_dict[polygons.EXTERIOR_Y_COLUMN],
                           EXCLUSIVE_BUFFER_EXTERIOR_Y_METRES,
                           atol=TOLERANCE))

        self.assertTrue(
            len(this_buffer_vertex_dict[polygons.HOLE_X_COLUMN]) == 1)
        self.assertTrue(
            len(this_buffer_vertex_dict[polygons.HOLE_Y_COLUMN]) == 1)
        self.assertTrue(
            numpy.allclose(this_buffer_vertex_dict[polygons.HOLE_X_COLUMN][0],
                           EXCLUSIVE_BUFFER_HOLE_X_METRES,
                           atol=TOLERANCE))
        self.assertTrue(
            numpy.allclose(this_buffer_vertex_dict[polygons.HOLE_Y_COLUMN][0],
                           EXCLUSIVE_BUFFER_HOLE_Y_METRES,
                           atol=TOLERANCE))
예제 #4
0
    def test_buffer_simple_polygon_nested(self):
        """Ensures correct output from buffer_simple_polygon.

        In this case the buffer is nested (large distance used to create
        exterior, small distance used to create hole).
        """

        this_buffer_polygon_object = polygons.buffer_simple_polygon(
            EXTERIOR_VERTEX_X_METRES,
            EXTERIOR_VERTEX_Y_METRES,
            min_buffer_dist_metres=SMALL_BUFFER_DIST_METRES,
            max_buffer_dist_metres=LARGE_BUFFER_DIST_METRES,
            preserve_angles=True)

        this_buffer_vertex_dict = polygons.polygon_object_to_vertex_arrays(
            this_buffer_polygon_object)

        this_buffer_vertex_x_metres, this_buffer_vertex_y_metres = (
            polygons.merge_exterior_and_holes(
                this_buffer_vertex_dict[polygons.EXTERIOR_X_COLUMN],
                this_buffer_vertex_dict[polygons.EXTERIOR_Y_COLUMN],
                hole_x_coords_list=this_buffer_vertex_dict[
                    polygons.HOLE_X_COLUMN],
                hole_y_coords_list=this_buffer_vertex_dict[
                    polygons.HOLE_Y_COLUMN]))

        self.assertTrue(
            numpy.allclose(this_buffer_vertex_x_metres,
                           VERTEX_X_METRES_NESTED_BUFFER,
                           atol=TOLERANCE,
                           equal_nan=True))
        self.assertTrue(
            numpy.allclose(this_buffer_vertex_y_metres,
                           VERTEX_Y_METRES_NESTED_BUFFER,
                           atol=TOLERANCE,
                           equal_nan=True))
LIVE_SELECTED_INDICES_FOR_MIN_OBS_SAMPLING = numpy.array(
    [5, 6, 9, 10, 12, 13, 14, 15, 18, 20, 21])
LIVE_SELECTED_INDICES_FOR_MIN_OBS_PLUS_SAMPLING = numpy.array(
    [5, 6, 9, 10, 12, 13, 14, 15, 18, 20, 21, 23, 24])
LIVE_SELECTED_INDICES_FOR_MIN_DENSITY_SAMPLING = copy.deepcopy(
    LIVE_SELECTED_INDICES_FOR_MIN_OBS_SAMPLING)
LIVE_SELECTED_INDICES_FOR_MIN_DENSITY_PLUS_SAMPLING = copy.deepcopy(
    LIVE_SELECTED_INDICES_FOR_MIN_OBS_PLUS_SAMPLING)

# The following constants are used to test _get_observation_densities.
POLYGON_OBJECT_XY, THIS_PROJECTION_OBJECT = polygons.project_latlng_to_xy(
    POLYGON_OBJECT_LATLNG)
VERTEX_DICT_XY = polygons.polygon_object_to_vertex_arrays(POLYGON_OBJECT_XY)
BUFFERED_POLYGON_OBJECT_XY = polygons.buffer_simple_polygon(
    VERTEX_DICT_XY[polygons.EXTERIOR_X_COLUMN],
    VERTEX_DICT_XY[polygons.EXTERIOR_Y_COLUMN],
    min_buffer_dist_metres=MIN_DISTANCE_METRES,
    max_buffer_dist_metres=MAX_DISTANCE_METRES)

BUFFER_AREA_METRES2 = BUFFERED_POLYGON_OBJECT_XY.area
OBSERVATION_DENSITY_BY_STORM_OBJECT_M02 = (NUM_OBSERVATIONS_BY_STORM_OBJECT /
                                           BUFFER_AREA_METRES2)
MIN_OBS_DENSITY_FOR_SAMPLING_M02 = (MIN_OBSERVATIONS_FOR_SAMPLING /
                                    BUFFER_AREA_METRES2)

BUFFERED_POLYGON_OBJECT_LATLNG = polygons.project_xy_to_latlng(
    BUFFERED_POLYGON_OBJECT_XY, THIS_PROJECTION_OBJECT)
BUFFERED_POLYGON_OBJECT_ARRAY_LATLNG = numpy.full(
    NUM_STORM_OBJECTS, BUFFERED_POLYGON_OBJECT_LATLNG, dtype=object)

BUFFER_COLUMN_NAME = tracking_io.distance_buffer_to_column_name(
def create_distance_buffers(storm_object_table, min_distances_metres,
                            max_distances_metres):
    """Creates one or more distance buffers around each storm object.

    K = number of buffers

    :param storm_object_table: pandas DataFrame with the following columns.
        Each row is one storm object.
    storm_object_table.centroid_latitude_deg: Latitude (deg N) of storm-object
        centroid.
    storm_object_table.centroid_longitude_deg: Longitude (deg E) of storm-object
        centroid.
    storm_object_table.polygon_object_latlng_deg: Instance of
        `shapely.geometry.Polygon`, with x-coords in longitude (deg E) and
        y-coords in latitude (deg N).

    :param min_distances_metres: length-K numpy array of minimum distances.  If
        the storm object is inside the [k]th buffer -- i.e., the [k]th buffer
        has no minimum distance -- then min_distances_metres[k] should be NaN.
    :param max_distances_metres: length-K numpy array of max distances.
    :return: storm_object_table: Same as input but with K additional columns
        (one per distance buffer).  Column names are generated by
        `buffer_to_column_name`, and each value in these columns is a
        `shapely.geometry.Polygon` object, with x-coords in longitude (deg E) and
        y-coords in latitude (deg N).
    """

    num_buffers = len(min_distances_metres)
    these_expected_dim = numpy.array([num_buffers], dtype=int)
    error_checking.assert_is_numpy_array(max_distances_metres,
                                         exact_dimensions=these_expected_dim)

    global_centroid_lat_deg, global_centroid_lng_deg = (
        geodetic_utils.get_latlng_centroid(
            latitudes_deg=storm_object_table[CENTROID_LATITUDE_COLUMN].values,
            longitudes_deg=storm_object_table[CENTROID_LONGITUDE_COLUMN].values
        ))

    projection_object = projections.init_azimuthal_equidistant_projection(
        central_latitude_deg=global_centroid_lat_deg,
        central_longitude_deg=global_centroid_lng_deg)

    num_storm_objects = len(storm_object_table.index)
    object_array = numpy.full(num_storm_objects, numpy.nan, dtype=object)
    buffer_column_names = [''] * num_buffers

    for j in range(num_buffers):
        buffer_column_names[j] = buffer_to_column_name(
            min_distance_metres=min_distances_metres[j],
            max_distance_metres=max_distances_metres[j])

        storm_object_table = storm_object_table.assign(
            **{buffer_column_names[j]: object_array})

    for i in range(num_storm_objects):
        this_orig_vertex_dict_latlng_deg = (
            polygons.polygon_object_to_vertex_arrays(
                storm_object_table[LATLNG_POLYGON_COLUMN].values[i]))

        these_orig_x_metres, these_orig_y_metres = (
            projections.project_latlng_to_xy(
                latitudes_deg=this_orig_vertex_dict_latlng_deg[
                    polygons.EXTERIOR_Y_COLUMN],
                longitudes_deg=this_orig_vertex_dict_latlng_deg[
                    polygons.EXTERIOR_X_COLUMN],
                projection_object=projection_object))

        for j in range(num_buffers):
            this_buffer_poly_object_xy_metres = polygons.buffer_simple_polygon(
                vertex_x_metres=these_orig_x_metres,
                vertex_y_metres=these_orig_y_metres,
                min_buffer_dist_metres=min_distances_metres[j],
                max_buffer_dist_metres=max_distances_metres[j])

            this_buffer_vertex_dict = polygons.polygon_object_to_vertex_arrays(
                this_buffer_poly_object_xy_metres)

            (this_buffer_vertex_dict[polygons.EXTERIOR_Y_COLUMN],
             this_buffer_vertex_dict[polygons.EXTERIOR_X_COLUMN]
             ) = projections.project_xy_to_latlng(
                 x_coords_metres=this_buffer_vertex_dict[
                     polygons.EXTERIOR_X_COLUMN],
                 y_coords_metres=this_buffer_vertex_dict[
                     polygons.EXTERIOR_Y_COLUMN],
                 projection_object=projection_object)

            this_num_holes = len(
                this_buffer_vertex_dict[polygons.HOLE_X_COLUMN])

            for k in range(this_num_holes):
                (this_buffer_vertex_dict[polygons.HOLE_Y_COLUMN][k],
                 this_buffer_vertex_dict[polygons.HOLE_X_COLUMN][k]
                 ) = projections.project_xy_to_latlng(
                     x_coords_metres=this_buffer_vertex_dict[
                         polygons.HOLE_X_COLUMN][k],
                     y_coords_metres=this_buffer_vertex_dict[
                         polygons.HOLE_Y_COLUMN][k],
                     projection_object=projection_object)

            this_buffer_poly_object_latlng_deg = (
                polygons.vertex_arrays_to_polygon_object(
                    exterior_x_coords=this_buffer_vertex_dict[
                        polygons.EXTERIOR_X_COLUMN],
                    exterior_y_coords=this_buffer_vertex_dict[
                        polygons.EXTERIOR_Y_COLUMN],
                    hole_x_coords_list=this_buffer_vertex_dict[
                        polygons.HOLE_X_COLUMN],
                    hole_y_coords_list=this_buffer_vertex_dict[
                        polygons.HOLE_Y_COLUMN]))

            storm_object_table[buffer_column_names[j]].values[i] = (
                this_buffer_poly_object_latlng_deg)

    return storm_object_table
예제 #7
0
def make_buffers_around_polygons(storm_object_table,
                                 min_buffer_dists_metres=None,
                                 max_buffer_dists_metres=None):
    """Creates one or more buffers around each storm polygon.

    N = number of buffers
    V = number of vertices in a given polygon

    :param storm_object_table: pandas DataFrame with the following columns.
    storm_object_table.storm_id: String ID for storm cell.
    storm_object_table.polygon_object_latlng: Instance of
        `shapely.geometry.Polygon`, with vertices in lat-long coordinates.
    :param min_buffer_dists_metres: length-N numpy array of minimum buffer
        distances.  If min_buffer_dists_metres[i] is NaN, the [i]th buffer
        includes the original polygon.  If min_buffer_dists_metres[i] is
        defined, the [i]th buffer is a "nested" buffer, not including the
        original polygon.
    :param max_buffer_dists_metres: length-N numpy array of maximum buffer
        distances.  Must be all real numbers (no NaN).
    :return: storm_object_table: Same as input, but with N extra columns.
    storm_object_table.polygon_object_latlng_buffer_<D>m: Instance of
        `shapely.geometry.Polygon` for D-metre buffer around storm.
    storm_object_table.polygon_object_latlng_buffer_<d>_<D>m: Instance of
        `shapely.geometry.Polygon` for d-to-D-metre buffer around storm.
    """

    error_checking.assert_is_geq_numpy_array(min_buffer_dists_metres,
                                             0.,
                                             allow_nan=True)
    error_checking.assert_is_numpy_array(min_buffer_dists_metres,
                                         num_dimensions=1)

    num_buffers = len(min_buffer_dists_metres)
    error_checking.assert_is_geq_numpy_array(max_buffer_dists_metres,
                                             0.,
                                             allow_nan=False)
    error_checking.assert_is_numpy_array(max_buffer_dists_metres,
                                         exact_dimensions=numpy.array(
                                             [num_buffers]))

    for j in range(num_buffers):
        if numpy.isnan(min_buffer_dists_metres[j]):
            continue
        error_checking.assert_is_greater(max_buffer_dists_metres[j],
                                         min_buffer_dists_metres[j],
                                         allow_nan=False)

    num_storm_objects = len(storm_object_table.index)
    centroid_latitudes_deg = numpy.full(num_storm_objects, numpy.nan)
    centroid_longitudes_deg = numpy.full(num_storm_objects, numpy.nan)

    for i in range(num_storm_objects):
        this_centroid_object = storm_object_table[
            POLYGON_OBJECT_LATLNG_COLUMN].values[0].centroid
        centroid_latitudes_deg[i] = this_centroid_object.y
        centroid_longitudes_deg[i] = this_centroid_object.x

    global_centroid_lat_deg, global_centroid_lng_deg = (
        polygons.get_latlng_centroid(centroid_latitudes_deg,
                                     centroid_longitudes_deg))
    projection_object = projections.init_azimuthal_equidistant_projection(
        global_centroid_lat_deg, global_centroid_lng_deg)

    object_array = numpy.full(num_storm_objects, numpy.nan, dtype=object)
    argument_dict = {}
    buffer_column_names = [''] * num_buffers

    for j in range(num_buffers):
        buffer_column_names[j] = distance_buffer_to_column_name(
            min_buffer_dists_metres[j], max_buffer_dists_metres[j])
        argument_dict.update({buffer_column_names[j]: object_array})
    storm_object_table = storm_object_table.assign(**argument_dict)

    for i in range(num_storm_objects):
        orig_vertex_dict_latlng = polygons.polygon_object_to_vertex_arrays(
            storm_object_table[POLYGON_OBJECT_LATLNG_COLUMN].values[i])

        (orig_vertex_x_metres,
         orig_vertex_y_metres) = projections.project_latlng_to_xy(
             orig_vertex_dict_latlng[polygons.EXTERIOR_Y_COLUMN],
             orig_vertex_dict_latlng[polygons.EXTERIOR_X_COLUMN],
             projection_object=projection_object)

        for j in range(num_buffers):
            buffer_polygon_object_xy = polygons.buffer_simple_polygon(
                orig_vertex_x_metres,
                orig_vertex_y_metres,
                min_buffer_dist_metres=min_buffer_dists_metres[j],
                max_buffer_dist_metres=max_buffer_dists_metres[j])

            buffer_vertex_dict = polygons.polygon_object_to_vertex_arrays(
                buffer_polygon_object_xy)

            (buffer_vertex_dict[polygons.EXTERIOR_Y_COLUMN],
             buffer_vertex_dict[polygons.EXTERIOR_X_COLUMN]) = (
                 projections.project_xy_to_latlng(
                     buffer_vertex_dict[polygons.EXTERIOR_X_COLUMN],
                     buffer_vertex_dict[polygons.EXTERIOR_Y_COLUMN],
                     projection_object=projection_object))

            this_num_holes = len(buffer_vertex_dict[polygons.HOLE_X_COLUMN])
            for k in range(this_num_holes):
                (buffer_vertex_dict[polygons.HOLE_Y_COLUMN][k],
                 buffer_vertex_dict[polygons.HOLE_X_COLUMN][k]) = (
                     projections.project_xy_to_latlng(
                         buffer_vertex_dict[polygons.HOLE_X_COLUMN][k],
                         buffer_vertex_dict[polygons.HOLE_Y_COLUMN][k],
                         projection_object=projection_object))

            buffer_polygon_object_latlng = (
                polygons.vertex_arrays_to_polygon_object(
                    buffer_vertex_dict[polygons.EXTERIOR_X_COLUMN],
                    buffer_vertex_dict[polygons.EXTERIOR_Y_COLUMN],
                    hole_x_coords_list=buffer_vertex_dict[
                        polygons.HOLE_X_COLUMN],
                    hole_y_coords_list=buffer_vertex_dict[
                        polygons.HOLE_Y_COLUMN]))

            storm_object_table[buffer_column_names[j]].values[
                i] = buffer_polygon_object_latlng

    return storm_object_table
def make_buffers_around_storm_objects(
        storm_object_table, min_distances_metres, max_distances_metres):
    """Creates one or more distance buffers around each storm object.

    N = number of storm objects
    B = number of buffers around each storm object
    V = number of vertices in a given buffer

    :param storm_object_table: N-row pandas DataFrame with the following
        columns.
    storm_object_table.storm_id: String ID for storm cell.
    storm_object_table.polygon_object_latlng: Instance of
        `shapely.geometry.Polygon`, containing vertices of storm object in
        lat-long coordinates.

    :param min_distances_metres: length-B numpy array of minimum buffer
        distances.  If min_distances_metres[i] is NaN, the storm object is
        included in the [i]th buffer, so the [i]th buffer is inclusive.  If
        min_distances_metres[i] is a real number, the storm object is *not*
        included in the [i]th buffer, so the [i]th buffer is exclusive.
    :param max_distances_metres: length-B numpy array of maximum buffer
        distances.  Must be all real numbers (no NaN).
    :return: storm_object_table: Same as input, but with B additional columns.
        Each additional column (listed below) contains a
        `shapely.geometry.Polygon` instance for each storm object.  Each
        `shapely.geometry.Polygon` instance contains the lat-long vertices of
        one distance buffer around one storm object.
    storm_object_table.polygon_object_latlng_buffer_<D>m: For an inclusive
        buffer of D metres around the storm.
    storm_object_table.polygon_object_latlng_buffer_<d>_<D>m: For an exclusive
        buffer of d...D metres around the storm.
    """

    error_checking.assert_is_geq_numpy_array(
        min_distances_metres, 0., allow_nan=True)
    error_checking.assert_is_numpy_array(
        min_distances_metres, num_dimensions=1)

    num_buffers = len(min_distances_metres)
    error_checking.assert_is_geq_numpy_array(
        max_distances_metres, 0., allow_nan=False)
    error_checking.assert_is_numpy_array(
        max_distances_metres, exact_dimensions=numpy.array([num_buffers]))

    for j in range(num_buffers):
        if numpy.isnan(min_distances_metres[j]):
            continue
        error_checking.assert_is_greater(
            max_distances_metres[j], min_distances_metres[j],
            allow_nan=False)

    num_storm_objects = len(storm_object_table.index)
    centroid_latitudes_deg = numpy.full(num_storm_objects, numpy.nan)
    centroid_longitudes_deg = numpy.full(num_storm_objects, numpy.nan)

    for i in range(num_storm_objects):
        this_centroid_object = storm_object_table[
            POLYGON_OBJECT_LATLNG_COLUMN].values[0].centroid
        centroid_latitudes_deg[i] = this_centroid_object.y
        centroid_longitudes_deg[i] = this_centroid_object.x

    (global_centroid_lat_deg, global_centroid_lng_deg
    ) = geodetic_utils.get_latlng_centroid(
        latitudes_deg=centroid_latitudes_deg,
        longitudes_deg=centroid_longitudes_deg)
    projection_object = projections.init_azimuthal_equidistant_projection(
        global_centroid_lat_deg, global_centroid_lng_deg)

    object_array = numpy.full(num_storm_objects, numpy.nan, dtype=object)
    argument_dict = {}
    buffer_column_names = [''] * num_buffers

    for j in range(num_buffers):
        buffer_column_names[j] = distance_buffer_to_column_name(
            min_distances_metres[j], max_distances_metres[j])
        argument_dict.update({buffer_column_names[j]: object_array})
    storm_object_table = storm_object_table.assign(**argument_dict)

    for i in range(num_storm_objects):
        orig_vertex_dict_latlng = polygons.polygon_object_to_vertex_arrays(
            storm_object_table[POLYGON_OBJECT_LATLNG_COLUMN].values[i])

        (orig_vertex_x_metres,
         orig_vertex_y_metres) = projections.project_latlng_to_xy(
             orig_vertex_dict_latlng[polygons.EXTERIOR_Y_COLUMN],
             orig_vertex_dict_latlng[polygons.EXTERIOR_X_COLUMN],
             projection_object=projection_object)

        for j in range(num_buffers):
            buffer_polygon_object_xy = polygons.buffer_simple_polygon(
                orig_vertex_x_metres, orig_vertex_y_metres,
                min_buffer_dist_metres=min_distances_metres[j],
                max_buffer_dist_metres=max_distances_metres[j])

            buffer_vertex_dict = polygons.polygon_object_to_vertex_arrays(
                buffer_polygon_object_xy)

            (buffer_vertex_dict[polygons.EXTERIOR_Y_COLUMN],
             buffer_vertex_dict[polygons.EXTERIOR_X_COLUMN]) = (
                 projections.project_xy_to_latlng(
                     buffer_vertex_dict[polygons.EXTERIOR_X_COLUMN],
                     buffer_vertex_dict[polygons.EXTERIOR_Y_COLUMN],
                     projection_object=projection_object))

            this_num_holes = len(buffer_vertex_dict[polygons.HOLE_X_COLUMN])
            for k in range(this_num_holes):
                (buffer_vertex_dict[polygons.HOLE_Y_COLUMN][k],
                 buffer_vertex_dict[polygons.HOLE_X_COLUMN][k]) = (
                     projections.project_xy_to_latlng(
                         buffer_vertex_dict[polygons.HOLE_X_COLUMN][k],
                         buffer_vertex_dict[polygons.HOLE_Y_COLUMN][k],
                         projection_object=projection_object))

            buffer_polygon_object_latlng = (
                polygons.vertex_arrays_to_polygon_object(
                    buffer_vertex_dict[polygons.EXTERIOR_X_COLUMN],
                    buffer_vertex_dict[polygons.EXTERIOR_Y_COLUMN],
                    hole_x_coords_list=
                    buffer_vertex_dict[polygons.HOLE_X_COLUMN],
                    hole_y_coords_list=
                    buffer_vertex_dict[polygons.HOLE_Y_COLUMN]))

            storm_object_table[buffer_column_names[j]].values[
                i] = buffer_polygon_object_latlng

    return storm_object_table