Пример #1
0
def _check_polygons(polygon_objects_grid_coords, num_panel_rows,
                    num_panel_columns, panel_row_by_polygon,
                    panel_column_by_polygon):
    """Error-checks list of polygons.

    :param polygon_objects_grid_coords: See doc for
        `polygons_from_pixel_to_grid_coords`.
    :param num_panel_rows: Same.
    :param num_panel_columns: Same.
    :param panel_row_by_polygon: Same.
    :param panel_column_by_polygon: Same.
    """

    error_checking.assert_is_integer(num_panel_rows)
    error_checking.assert_is_greater(num_panel_rows, 0)
    error_checking.assert_is_integer(num_panel_columns)
    error_checking.assert_is_greater(num_panel_columns, 0)

    num_polygons = len(polygon_objects_grid_coords)
    if num_polygons == 0:
        return

    error_checking.assert_is_numpy_array(numpy.array(
        polygon_objects_grid_coords, dtype=object),
                                         num_dimensions=1)

    these_expected_dim = numpy.array([num_polygons], dtype=int)

    error_checking.assert_is_integer_numpy_array(panel_row_by_polygon)
    error_checking.assert_is_numpy_array(panel_row_by_polygon,
                                         exact_dimensions=these_expected_dim)
    error_checking.assert_is_geq_numpy_array(panel_row_by_polygon, 0)
    error_checking.assert_is_less_than_numpy_array(panel_row_by_polygon,
                                                   num_panel_rows)

    error_checking.assert_is_integer_numpy_array(panel_column_by_polygon)
    error_checking.assert_is_numpy_array(panel_column_by_polygon,
                                         exact_dimensions=these_expected_dim)
    error_checking.assert_is_geq_numpy_array(panel_column_by_polygon, 0)
    error_checking.assert_is_less_than_numpy_array(panel_column_by_polygon,
                                                   num_panel_columns)
Пример #2
0
def write_points(output_file_name,
                 grid_row_by_point,
                 grid_column_by_point,
                 panel_row_by_point,
                 panel_column_by_point,
                 full_storm_id_string=None,
                 storm_time_unix_sec=None):
    """Writes human points of interest for one image to NetCDF file.

    K = number of points of interest

    :param output_file_name: Path to output (NetCDF) file.
    :param grid_row_by_point: length-K numpy array of row indices in data grid
        (floats).
    :param grid_column_by_point: length-K numpy array of column indices in data
        grid (floats).
    :param panel_row_by_point: length-K numpy array of row indices in panel grid
        (integers).
    :param panel_column_by_point: length-K numpy array of column indices in
        panel grid (integers).
    :param full_storm_id_string: See doc for `write_polygons`.
    :param storm_time_unix_sec: Same.
    """

    is_composite = (full_storm_id_string is None
                    and storm_time_unix_sec is None)

    if is_composite:
        full_storm_id_string = DUMMY_STORM_ID_STRING
        storm_time_unix_sec = -1

    error_checking.assert_is_string(full_storm_id_string)
    error_checking.assert_is_integer(storm_time_unix_sec)

    # error_checking.assert_is_integer(num_grid_rows)
    # error_checking.assert_is_greater(num_grid_rows, 0)
    # error_checking.assert_is_integer(num_grid_columns)
    # error_checking.assert_is_greater(num_grid_columns, 0)

    error_checking.assert_is_numpy_array(grid_row_by_point, num_dimensions=1)
    error_checking.assert_is_geq_numpy_array(grid_row_by_point, -0.5)
    # error_checking.assert_is_leq_numpy_array(
    #     grid_row_by_point, num_grid_rows - 0.5)

    num_points = len(grid_row_by_point)
    these_expected_dim = numpy.array([num_points], dtype=int)

    error_checking.assert_is_numpy_array(grid_column_by_point,
                                         exact_dimensions=these_expected_dim)
    error_checking.assert_is_geq_numpy_array(grid_column_by_point, -0.5)
    # error_checking.assert_is_leq_numpy_array(
    #     grid_column_by_point, num_grid_columns - 0.5)

    error_checking.assert_is_numpy_array(panel_row_by_point,
                                         exact_dimensions=these_expected_dim)
    error_checking.assert_is_integer_numpy_array(panel_row_by_point)
    error_checking.assert_is_geq_numpy_array(panel_row_by_point, 0)

    error_checking.assert_is_numpy_array(panel_column_by_point,
                                         exact_dimensions=these_expected_dim)
    error_checking.assert_is_integer_numpy_array(panel_column_by_point)
    error_checking.assert_is_geq_numpy_array(panel_column_by_point, 0)

    file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name)
    dataset_object = netCDF4.Dataset(output_file_name,
                                     'w',
                                     format='NETCDF3_64BIT_OFFSET')

    dataset_object.setncattr(STORM_ID_KEY, full_storm_id_string)
    dataset_object.setncattr(STORM_TIME_KEY, storm_time_unix_sec)
    dataset_object.createDimension(POINT_DIMENSION_KEY, num_points)

    dataset_object.createVariable(GRID_ROW_BY_POINT_KEY,
                                  datatype=numpy.float32,
                                  dimensions=POINT_DIMENSION_KEY)
    dataset_object.variables[GRID_ROW_BY_POINT_KEY][:] = grid_row_by_point

    dataset_object.createVariable(GRID_COLUMN_BY_POINT_KEY,
                                  datatype=numpy.float32,
                                  dimensions=POINT_DIMENSION_KEY)
    dataset_object.variables[
        GRID_COLUMN_BY_POINT_KEY][:] = grid_column_by_point

    dataset_object.createVariable(PANEL_ROW_BY_POINT_KEY,
                                  datatype=numpy.int32,
                                  dimensions=POINT_DIMENSION_KEY)
    dataset_object.variables[PANEL_ROW_BY_POINT_KEY][:] = panel_row_by_point

    dataset_object.createVariable(PANEL_COLUMN_BY_POINT_KEY,
                                  datatype=numpy.int32,
                                  dimensions=POINT_DIMENSION_KEY)
    dataset_object.variables[
        PANEL_COLUMN_BY_POINT_KEY][:] = panel_column_by_point

    dataset_object.close()
Пример #3
0
def write_polygons(output_file_name,
                   positive_objects_grid_coords,
                   positive_panel_row_by_polygon,
                   positive_panel_column_by_polygon,
                   positive_mask_matrix,
                   negative_objects_grid_coords=None,
                   negative_panel_row_by_polygon=None,
                   negative_panel_column_by_polygon=None,
                   negative_mask_matrix=None,
                   full_storm_id_string=None,
                   storm_time_unix_sec=None):
    """Writes human polygons for one image to NetCDF file.

    P = number of positive regions of interest
    N = number of negative regions of interest

    :param output_file_name: Path to output (NetCDF) file.
    :param positive_objects_grid_coords: length-P list of polygons created by
        `polygons_from_pixel_to_grid_coords`, containing positive regions of
        interest.
    :param positive_panel_row_by_polygon: length-P numpy array of corresponding
        panel rows (non-negative integers).
    :param positive_panel_column_by_polygon: length-P numpy array of
        corresponding panel columns (non-negative integers).
    :param positive_mask_matrix: Binary mask for positive regions of interest,
        created by `polygons_to_mask`.
    :param negative_objects_grid_coords: length-N list of polygons created by
        `polygons_from_pixel_to_grid_coords`, containing negative regions of
        interest.
    :param negative_panel_row_by_polygon: length-N numpy array of corresponding
        panel rows (non-negative integers).
    :param negative_panel_column_by_polygon: length-N numpy array of
        corresponding panel columns (non-negative integers).
    :param negative_mask_matrix: Binary mask for negative regions of interest,
        created by `polygons_to_mask`.
    :param full_storm_id_string: Full storm ID (if polygons were drawn for
        composite, this should be None).
    :param storm_time_unix_sec: Valid time (if polygons were drawn for
        composite, this should be None).
    """

    is_composite = (full_storm_id_string is None
                    and storm_time_unix_sec is None)

    if is_composite:
        full_storm_id_string = DUMMY_STORM_ID_STRING
        storm_time_unix_sec = -1

    error_checking.assert_is_string(full_storm_id_string)
    error_checking.assert_is_integer(storm_time_unix_sec)

    error_checking.assert_is_boolean_numpy_array(positive_mask_matrix)
    error_checking.assert_is_numpy_array(positive_mask_matrix,
                                         num_dimensions=4)

    _check_polygons(polygon_objects_grid_coords=positive_objects_grid_coords,
                    num_panel_rows=positive_mask_matrix.shape[0],
                    num_panel_columns=positive_mask_matrix.shape[1],
                    panel_row_by_polygon=positive_panel_row_by_polygon,
                    panel_column_by_polygon=positive_panel_column_by_polygon)

    if negative_objects_grid_coords is None:
        negative_objects_grid_coords = []
        negative_panel_row_by_polygon = numpy.array([], dtype=int)
        negative_panel_column_by_polygon = numpy.array([], dtype=int)
        negative_mask_matrix = numpy.full(positive_mask_matrix.shape,
                                          False,
                                          dtype=bool)

    error_checking.assert_is_boolean_numpy_array(negative_mask_matrix)
    error_checking.assert_is_numpy_array(negative_mask_matrix,
                                         exact_dimensions=numpy.array(
                                             positive_mask_matrix.shape,
                                             dtype=int))

    _check_polygons(polygon_objects_grid_coords=negative_objects_grid_coords,
                    num_panel_rows=negative_mask_matrix.shape[0],
                    num_panel_columns=negative_mask_matrix.shape[1],
                    panel_row_by_polygon=negative_panel_row_by_polygon,
                    panel_column_by_polygon=negative_panel_column_by_polygon)

    (positive_vertex_rows, positive_vertex_columns,
     these_vertex_to_poly_indices
     ) = _polygon_list_to_vertex_list(positive_objects_grid_coords)

    positive_panel_row_by_vertex = numpy.array([
        positive_panel_row_by_polygon[k] if k >= 0 else numpy.nan
        for k in these_vertex_to_poly_indices
    ])

    positive_panel_column_by_vertex = numpy.array([
        positive_panel_column_by_polygon[k] if k >= 0 else numpy.nan
        for k in these_vertex_to_poly_indices
    ])

    if len(positive_vertex_rows) == 0:
        positive_vertex_rows = numpy.full(1, SENTINEL_VALUE - 1)
        positive_vertex_columns = numpy.full(1, SENTINEL_VALUE - 1)
        positive_panel_row_by_vertex = numpy.full(1, -1, dtype=int)
        positive_panel_column_by_vertex = numpy.full(1, -1, dtype=int)

    (negative_vertex_rows, negative_vertex_columns,
     these_vertex_to_poly_indices
     ) = _polygon_list_to_vertex_list(negative_objects_grid_coords)

    negative_panel_row_by_vertex = numpy.array([
        negative_panel_row_by_polygon[k] if k >= 0 else numpy.nan
        for k in these_vertex_to_poly_indices
    ])

    negative_panel_column_by_vertex = numpy.array([
        negative_panel_column_by_polygon[k] if k >= 0 else numpy.nan
        for k in these_vertex_to_poly_indices
    ])

    file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name)
    dataset_object = netCDF4.Dataset(output_file_name,
                                     'w',
                                     format='NETCDF3_64BIT_OFFSET')

    dataset_object.setncattr(STORM_ID_KEY, full_storm_id_string)
    dataset_object.setncattr(STORM_TIME_KEY, storm_time_unix_sec)

    dataset_object.createDimension(PANEL_ROW_DIMENSION_KEY,
                                   positive_mask_matrix.shape[0])
    dataset_object.createDimension(PANEL_COLUMN_DIMENSION_KEY,
                                   positive_mask_matrix.shape[1])
    dataset_object.createDimension(GRID_ROW_DIMENSION_KEY,
                                   positive_mask_matrix.shape[2])
    dataset_object.createDimension(GRID_COLUMN_DIMENSION_KEY,
                                   positive_mask_matrix.shape[3])
    dataset_object.createDimension(POSITIVE_VERTEX_DIM_KEY,
                                   len(positive_vertex_rows))
    dataset_object.createDimension(NEGATIVE_VERTEX_DIM_KEY,
                                   len(negative_vertex_rows))

    dataset_object.createVariable(POSITIVE_VERTEX_ROWS_KEY,
                                  datatype=numpy.float32,
                                  dimensions=POSITIVE_VERTEX_DIM_KEY)
    dataset_object.variables[
        POSITIVE_VERTEX_ROWS_KEY][:] = positive_vertex_rows

    dataset_object.createVariable(POSITIVE_VERTEX_COLUMNS_KEY,
                                  datatype=numpy.float32,
                                  dimensions=POSITIVE_VERTEX_DIM_KEY)
    dataset_object.variables[POSITIVE_VERTEX_COLUMNS_KEY][:] = (
        positive_vertex_columns)

    dataset_object.createVariable(POSITIVE_PANEL_ROW_BY_VERTEX_KEY,
                                  datatype=numpy.int32,
                                  dimensions=POSITIVE_VERTEX_DIM_KEY)
    dataset_object.variables[
        POSITIVE_PANEL_ROW_BY_VERTEX_KEY][:] = positive_panel_row_by_vertex

    dataset_object.createVariable(POSITIVE_PANEL_COLUMN_BY_VERTEX_KEY,
                                  datatype=numpy.int32,
                                  dimensions=POSITIVE_VERTEX_DIM_KEY)
    dataset_object.variables[
        POSITIVE_PANEL_COLUMN_BY_VERTEX_KEY][:] = positive_panel_column_by_vertex

    dataset_object.createVariable(NEGATIVE_VERTEX_ROWS_KEY,
                                  datatype=numpy.float32,
                                  dimensions=NEGATIVE_VERTEX_DIM_KEY)
    dataset_object.variables[
        NEGATIVE_VERTEX_ROWS_KEY][:] = negative_vertex_rows

    dataset_object.createVariable(NEGATIVE_VERTEX_COLUMNS_KEY,
                                  datatype=numpy.float32,
                                  dimensions=NEGATIVE_VERTEX_DIM_KEY)
    dataset_object.variables[NEGATIVE_VERTEX_COLUMNS_KEY][:] = (
        negative_vertex_columns)

    dataset_object.createVariable(NEGATIVE_PANEL_ROW_BY_VERTEX_KEY,
                                  datatype=numpy.int32,
                                  dimensions=NEGATIVE_VERTEX_DIM_KEY)
    dataset_object.variables[
        NEGATIVE_PANEL_ROW_BY_VERTEX_KEY][:] = negative_panel_row_by_vertex

    dataset_object.createVariable(NEGATIVE_PANEL_COLUMN_BY_VERTEX_KEY,
                                  datatype=numpy.int32,
                                  dimensions=NEGATIVE_VERTEX_DIM_KEY)
    dataset_object.variables[
        NEGATIVE_PANEL_COLUMN_BY_VERTEX_KEY][:] = negative_panel_column_by_vertex

    dataset_object.createVariable(
        POSITIVE_MASK_MATRIX_KEY,
        datatype=numpy.int32,
        dimensions=(PANEL_ROW_DIMENSION_KEY, PANEL_COLUMN_DIMENSION_KEY,
                    GRID_ROW_DIMENSION_KEY, GRID_COLUMN_DIMENSION_KEY))
    dataset_object.variables[POSITIVE_MASK_MATRIX_KEY][:] = (
        positive_mask_matrix.astype(int))

    dataset_object.createVariable(
        NEGATIVE_MASK_MATRIX_KEY,
        datatype=numpy.int32,
        dimensions=(PANEL_ROW_DIMENSION_KEY, PANEL_COLUMN_DIMENSION_KEY,
                    GRID_ROW_DIMENSION_KEY, GRID_COLUMN_DIMENSION_KEY))
    dataset_object.variables[NEGATIVE_MASK_MATRIX_KEY][:] = (
        negative_mask_matrix.astype(int))

    dataset_object.close()
Пример #4
0
def pixel_columns_to_grid_columns(pixel_column_by_vertex, num_pixel_columns,
                                  num_panel_columns, num_grid_columns,
                                  assert_same_panel):
    """Converts pixel columns to grid columns.

    V = number of vertices in object

    :param pixel_column_by_vertex: length-V numpy array with column coordinates
        of vertices in pixel space.
    :param num_pixel_columns: Total number of pixel columns in image.
    :param num_panel_columns: Total number of panel columns in image.
    :param num_grid_columns: Total number of columns in grid (one grid per
        panel).
    :param assert_same_panel: Boolean flag.  If True, all vertices must be in
        the same panel.
    :return: grid_column_by_vertex: length-V numpy array with column coordinates
        (floats) of vertices in grid space.
    :return: panel_column_by_vertex: length-V numpy array with column
        coordinates (integers) of vertices in panel space.
    """

    error_checking.assert_is_integer(num_pixel_columns)
    error_checking.assert_is_greater(num_pixel_columns, 0)
    error_checking.assert_is_integer(num_panel_columns)
    error_checking.assert_is_greater(num_panel_columns, 0)
    error_checking.assert_is_integer(num_grid_columns)
    error_checking.assert_is_greater(num_grid_columns, 0)
    error_checking.assert_is_boolean(assert_same_panel)

    error_checking.assert_is_numpy_array(pixel_column_by_vertex,
                                         num_dimensions=1)

    pixel_column_by_vertex += 0.5
    error_checking.assert_is_geq_numpy_array(pixel_column_by_vertex, 0.)
    error_checking.assert_is_leq_numpy_array(pixel_column_by_vertex,
                                             num_pixel_columns)

    panel_column_to_first_px_column = {}
    for j in range(num_panel_columns):
        panel_column_to_first_px_column[j] = (j * float(num_pixel_columns) /
                                              num_panel_columns)

    panel_column_by_vertex = numpy.floor(pixel_column_by_vertex *
                                         float(num_panel_columns) /
                                         num_pixel_columns).astype(int)

    panel_column_by_vertex[panel_column_by_vertex ==
                           num_panel_columns] = num_panel_columns - 1

    if assert_same_panel and len(numpy.unique(panel_column_by_vertex)) > 1:
        error_string = (
            'Object is in multiple panels.  Panel columns listed below.\n{0:s}'
        ).format(str(panel_column_by_vertex))

        raise ValueError(error_string)

    num_vertices = len(pixel_column_by_vertex)
    for i in range(num_vertices):
        pixel_column_by_vertex[i] = (
            pixel_column_by_vertex[i] -
            panel_column_to_first_px_column[panel_column_by_vertex[i]])

    grid_column_by_vertex = -0.5 + (pixel_column_by_vertex * float(
        num_grid_columns * num_panel_columns) / num_pixel_columns)

    return grid_column_by_vertex, panel_column_by_vertex
Пример #5
0
def polygons_to_mask(polygon_objects_grid_coords, num_grid_rows,
                     num_grid_columns, num_panel_rows, num_panel_columns,
                     panel_row_by_polygon, panel_column_by_polygon):
    """Converts list of polygons to one binary mask for each panel.

    M = number of rows in grid
    N = number of columns in grid
    J = number of panel rows in image
    K = number of panel columns in image

    :param polygon_objects_grid_coords: See doc for
        `polygons_from_pixel_to_grid_coords`.
    :param num_grid_rows: Same.
    :param num_grid_columns: Same.
    :param num_panel_rows: Same.
    :param num_panel_columns: Same.
    :param panel_row_by_polygon: Same.
    :param panel_column_by_polygon: Same.
    :return: mask_matrix: J-by-K-by-M-by-N numpy array of Boolean flags.  If
        mask_matrix[j, k, m, n] == True, grid point [m, n] in panel [j, k] is
        in/on at least one of the polygons.
    """

    error_checking.assert_is_integer(num_grid_rows)
    error_checking.assert_is_greater(num_grid_rows, 0)
    error_checking.assert_is_integer(num_grid_columns)
    error_checking.assert_is_greater(num_grid_columns, 0)

    _check_polygons(polygon_objects_grid_coords=polygon_objects_grid_coords,
                    num_panel_rows=num_panel_rows,
                    num_panel_columns=num_panel_columns,
                    panel_row_by_polygon=panel_row_by_polygon,
                    panel_column_by_polygon=panel_column_by_polygon)

    mask_matrix = numpy.full(
        (num_panel_rows, num_panel_columns, num_grid_rows, num_grid_columns),
        False,
        dtype=bool)

    num_polygons = len(polygon_objects_grid_coords)
    if num_polygons == 0:
        return mask_matrix

    panel_coord_matrix = numpy.hstack(
        (numpy.reshape(panel_row_by_polygon, (num_polygons, 1)),
         numpy.reshape(panel_column_by_polygon, (num_polygons, 1))))

    panel_coord_matrix = numpy.unique(panel_coord_matrix.astype(int), axis=0)

    for i in range(panel_coord_matrix.shape[0]):
        this_panel_row = panel_coord_matrix[i, 0]
        this_panel_column = panel_coord_matrix[i, 1]

        these_polygon_indices = numpy.where(
            numpy.logical_and(panel_row_by_polygon == this_panel_row,
                              panel_column_by_polygon == this_panel_column))[0]

        these_polygon_objects = [
            polygon_objects_grid_coords[k] for k in these_polygon_indices
        ]

        mask_matrix[this_panel_row, this_panel_column,
                    ...] = (_polygons_to_mask_one_panel(
                        polygon_objects_grid_coords=these_polygon_objects,
                        num_grid_rows=num_grid_rows,
                        num_grid_columns=num_grid_columns))

    return mask_matrix
    def test_assert_is_integer_none(self):
        """Checks assert_is_integer when input is None."""

        with self.assertRaises(TypeError):
            error_checking.assert_is_integer(None)
    def test_assert_is_integer_true(self):
        """Checks assert_is_integer when input is integer."""

        error_checking.assert_is_integer(SINGLE_INTEGER)
    def test_assert_is_integer_nan(self):
        """Checks assert_is_integer when input is NaN."""

        with self.assertRaises(TypeError):
            error_checking.assert_is_integer(numpy.nan)
    def test_assert_is_integer_complex(self):
        """Checks assert_is_integer when input is complex."""

        with self.assertRaises(TypeError):
            error_checking.assert_is_integer(SINGLE_COMPLEX_NUMBER)
    def test_assert_is_integer_boolean(self):
        """Checks assert_is_integer when input is Boolean."""

        with self.assertRaises(TypeError):
            error_checking.assert_is_integer(SINGLE_BOOLEAN)
    def test_assert_is_integer_float(self):
        """Checks assert_is_integer when input is float."""

        with self.assertRaises(TypeError):
            error_checking.assert_is_integer(SINGLE_FLOAT)
    def test_assert_is_integer_too_many_inputs(self):
        """Checks assert_is_integer when input is array of integers."""

        with self.assertRaises(TypeError):
            error_checking.assert_is_integer(INTEGER_NUMPY_ARRAY)