def test_assert_is_numpy_array_num_dim_not_integer(self):
        """Checks assert_is_numpy_array when `num_dimensions` is not integer."""

        with self.assertRaises(TypeError):
            error_checking.assert_is_numpy_array(REAL_NUMPY_ARRAY,
                                                 num_dimensions=float(
                                                     REAL_NUMPY_ARRAY.ndim))
    def test_assert_is_numpy_array_exact_dim_correct(self):
        """Checks assert_is_numpy_array when `exact_dimensions` is correct."""

        error_checking.assert_is_numpy_array(
            REAL_NUMPY_ARRAY,
            num_dimensions=REAL_NUMPY_ARRAY.ndim,
            exact_dimensions=numpy.asarray(REAL_NUMPY_ARRAY.shape,
                                           dtype=numpy.int64))
    def test_assert_is_numpy_array_exact_dim_list(self):
        """Checks assert_is_numpy_array when `exact_dimensions` is list."""

        with self.assertRaises(TypeError):
            error_checking.assert_is_numpy_array(
                REAL_NUMPY_ARRAY,
                num_dimensions=REAL_NUMPY_ARRAY.ndim,
                exact_dimensions=REAL_NUMPY_ARRAY.shape)
    def test_assert_is_numpy_array_exact_dim_not_integers(self):
        """Checks assert_is_numpy_array when `exact_dimensions` is not int."""

        with self.assertRaises(TypeError):
            error_checking.assert_is_numpy_array(
                REAL_NUMPY_ARRAY,
                num_dimensions=REAL_NUMPY_ARRAY.ndim,
                exact_dimensions=numpy.asarray(REAL_NUMPY_ARRAY.shape,
                                               dtype=numpy.float64))
    def test_assert_is_numpy_array_exact_dim_unexpected(self):
        """Checks assert_is_numpy_array when `exact_dimensions` is wrong."""

        these_dimensions = 1 + numpy.asarray(REAL_NUMPY_ARRAY.shape,
                                             dtype=numpy.int64)

        with self.assertRaises(TypeError):
            error_checking.assert_is_numpy_array(
                REAL_NUMPY_ARRAY,
                num_dimensions=REAL_NUMPY_ARRAY.ndim,
                exact_dimensions=these_dimensions)
    def test_assert_is_numpy_array_exact_dim_negative(self):
        """Checks assert_is_numpy_array when `exact_dimensions` has negative."""

        these_dimensions = -1 * numpy.asarray(REAL_NUMPY_ARRAY.shape,
                                              dtype=numpy.int64)

        with self.assertRaises(ValueError):
            error_checking.assert_is_numpy_array(
                REAL_NUMPY_ARRAY,
                num_dimensions=REAL_NUMPY_ARRAY.ndim,
                exact_dimensions=these_dimensions)
    def test_assert_is_numpy_array_exact_dim_too_long(self):
        """Checks assert_is_numpy_array when `exact_dimensions` is too long."""

        these_dimensions = numpy.concatenate(
            (numpy.asarray(REAL_NUMPY_ARRAY.shape,
                           dtype=numpy.int64), numpy.array([1])))

        with self.assertRaises(TypeError):
            error_checking.assert_is_numpy_array(
                REAL_NUMPY_ARRAY,
                num_dimensions=REAL_NUMPY_ARRAY.ndim,
                exact_dimensions=these_dimensions)
Esempio n. 8
0
def split_array_by_nan(input_array):
    """Splits numpy array into list of contiguous subarrays without NaN.

    :param input_array: 1-D numpy array.
    :return: list_of_arrays: 1-D list of 1-D numpy arrays.  Each numpy array is
        without NaN.
    """

    error_checking.assert_is_real_numpy_array(input_array)
    error_checking.assert_is_numpy_array(input_array, num_dimensions=1)

    return [
        input_array[i]
        for i in numpy.ma.clump_unmasked(numpy.ma.masked_invalid(input_array))
    ]
Esempio n. 9
0
def _polygon_list_to_vertex_list(polygon_objects_grid_coords):
    """Converts list of polygons to list of vertices.

    V = total number of vertices

    :param polygon_objects_grid_coords: List of polygons created by
        `polygons_from_pixel_to_grid_coords`.
    :return: vertex_rows: length-V numpy array of row coordinates.
    :return: vertex_columns: length-V numpy array of column coordinates.
    :return: vertex_to_polygon_indices: length-V numpy array of indices.
        If vertex_to_polygon_indices[i] = j, the [i]th vertex comes from the
        [j]th input polygon.
    """

    error_checking.assert_is_list(polygon_objects_grid_coords)
    num_polygons = len(polygon_objects_grid_coords)

    if num_polygons > 0:
        error_checking.assert_is_numpy_array(numpy.array(
            polygon_objects_grid_coords, dtype=object),
                                             num_dimensions=1)

    vertex_rows = []
    vertex_columns = []
    vertex_to_polygon_indices = []

    for i in range(num_polygons):
        this_num_vertices = len(polygon_objects_grid_coords[i].exterior.xy[1])

        vertex_rows += polygon_objects_grid_coords[i].exterior.xy[1]
        vertex_columns += polygon_objects_grid_coords[i].exterior.xy[0]
        vertex_to_polygon_indices += [i] * this_num_vertices

        if i == num_polygons - 1:
            continue

        vertex_rows += [numpy.nan]
        vertex_columns += [numpy.nan]
        vertex_to_polygon_indices += [-1]

    return (numpy.array(vertex_rows), numpy.array(vertex_columns),
            numpy.array(vertex_to_polygon_indices, dtype=int))
Esempio n. 10
0
def check_vertex_arrays(x_coordinates, y_coordinates, allow_nan=True):
    """Error-checks vertex arrays.

    V = number of vertices

    :param x_coordinates: length-V numpy array of x-coordinates.  May contain
        NaN's, where the first NaN separates the exterior from the first hole
        and the [k]th NaN separates the [k - 1]th hole from the [k]th hole.
        This method assumes that the first unbroken string of real values (not
        NaN) represents the exterior of the polygon.
    :param y_coordinates: Same but for y-coordinates.
    :param allow_nan: Boolean flag.  If True, this method allows NaN's in the
        coordinate arrays.
    :return: ValueError: if NaN's occur at different positions in the two
        arrays.
    """

    error_checking.assert_is_boolean(allow_nan)

    if allow_nan:
        error_checking.assert_is_real_numpy_array(x_coordinates)
        error_checking.assert_is_real_numpy_array(y_coordinates)
    else:
        error_checking.assert_is_numpy_array_without_nan(x_coordinates)
        error_checking.assert_is_numpy_array_without_nan(y_coordinates)

    error_checking.assert_is_numpy_array(x_coordinates, num_dimensions=1)

    these_expected_dim = numpy.array([len(x_coordinates)], dtype=int)
    error_checking.assert_is_numpy_array(y_coordinates,
                                         exact_dimensions=these_expected_dim)

    x_nan_indices = numpy.where(numpy.isnan(x_coordinates))[0]
    y_nan_indices = numpy.where(numpy.isnan(y_coordinates))[0]

    if not numpy.array_equal(x_nan_indices, y_nan_indices):
        error_string = ('x-coord ({0:s}) and y-coord ({1:s}) lists have NaN'
                        's at different'
                        ' locations.').format(str(x_nan_indices),
                                              str(y_nan_indices))

        raise ValueError(error_string)
Esempio n. 11
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)
Esempio n. 12
0
def polygons_from_pixel_to_grid_coords(polygon_objects_pixel_coords,
                                       num_grid_rows, num_grid_columns,
                                       num_pixel_rows, num_pixel_columns,
                                       num_panel_rows, num_panel_columns):
    """Converts polygons from pixel coordinates to grid coordinates.

    The input args `num_grid_rows` and `num_grid_columns` are the number of rows
    and columns in the data grid.  These are *not* the same as the number of
    pixel rows and columns in the image.

    This method assumes that the image contains one or more panels with gridded
    data.  Each panel may contain a different variable, but they must all
    contain the same grid, with the same aspect ratio and no whitespace border
    (between the panels or around the outside of the image).

    N = number of polygons

    :param polygon_objects_pixel_coords: length-N list of polygons (instances of
        `shapely.geometry.Polygon`) with vertices in pixel coordinates, where
        the top-left corner is x = y = 0.
    :param num_grid_rows: Number of rows in grid.
    :param num_grid_columns: Number of columns in grid.
    :param num_pixel_rows: Number of pixel rows in image.
    :param num_pixel_columns: Number of pixel columns in image.
    :param num_panel_rows: Number of panel rows in image.
    :param num_panel_columns: Number of panel columns in image.
    :return: polygon_objects_grid_coords: length-N list of polygons
        (instances of `shapely.geometry.Polygon`) with vertices in grid
        coordinates, where the bottom-left corner is x = y = 0.
    :return: panel_row_by_polygon: length-N numpy array of panel rows.  If
        panel_rows[k] = i, the [k]th polygon corresponds to a grid in the [i]th
        panel row, where the top row is the 0th.
    :return: panel_column_by_polygon: length-N numpy array of panel columns.  If
        panel_columns[k] = j, the [k]th polygon corresponds to a grid in the
        [j]th panel column, where the left column is the 0th.
    :raises: ValueError: if one polygon is in multiple panels.
    """

    error_checking.assert_is_list(polygon_objects_pixel_coords)

    num_polygons = len(polygon_objects_pixel_coords)
    if num_polygons == 0:
        empty_array = numpy.array([], dtype=int)
        return polygon_objects_pixel_coords, empty_array, empty_array

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

    polygon_objects_grid_coords = [None] * num_polygons
    panel_row_by_polygon = [None] * num_polygons
    panel_column_by_polygon = [None] * num_polygons

    for k in range(num_polygons):
        these_grid_columns, these_panel_columns = pixel_columns_to_grid_columns(
            pixel_column_by_vertex=numpy.array(
                polygon_objects_pixel_coords[k].exterior.xy[0]),
            num_pixel_columns=num_pixel_columns,
            num_panel_columns=num_panel_columns,
            num_grid_columns=num_grid_columns,
            assert_same_panel=True)

        panel_column_by_polygon[k] = these_panel_columns[0]

        these_grid_rows, these_panel_rows = pixel_rows_to_grid_rows(
            pixel_row_by_vertex=numpy.array(
                polygon_objects_pixel_coords[k].exterior.xy[1]),
            num_pixel_rows=num_pixel_rows,
            num_panel_rows=num_panel_rows,
            num_grid_rows=num_grid_rows,
            assert_same_panel=True)

        panel_row_by_polygon[k] = these_panel_rows[0]

        polygon_objects_grid_coords[k] = (polygons.vertex_arrays_to_polygon(
            x_coordinates=these_grid_columns, y_coordinates=these_grid_rows))

    panel_row_by_polygon = numpy.array(panel_row_by_polygon, dtype=int)
    panel_column_by_polygon = numpy.array(panel_column_by_polygon, dtype=int)

    return (polygon_objects_grid_coords, panel_row_by_polygon,
            panel_column_by_polygon)
Esempio n. 13
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
    def test_assert_is_numpy_array_true(self):
        """Checks assert_is_numpy_array when input is numpy array."""

        error_checking.assert_is_numpy_array(REAL_NUMPY_ARRAY)
    def test_assert_is_numpy_array_tuple(self):
        """Checks assert_is_numpy_array when input is tuple."""

        with self.assertRaises(TypeError):
            error_checking.assert_is_numpy_array(REAL_NUMBER_TUPLE)
    def test_assert_is_numpy_array_list(self):
        """Checks assert_is_numpy_array when input is list."""

        with self.assertRaises(TypeError):
            error_checking.assert_is_numpy_array(REAL_NUMBER_LIST)
Esempio n. 17
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()
    def test_assert_is_numpy_array_num_dim_negative(self):
        """Checks assert_is_numpy_array when `num_dimensions` is negative."""

        with self.assertRaises(ValueError):
            error_checking.assert_is_numpy_array(REAL_NUMPY_ARRAY,
                                                 num_dimensions=-1)
    def test_assert_is_numpy_array_num_dim_unexpected(self):
        """Checks assert_is_numpy_array when `num_dimensions` is unexpected."""

        with self.assertRaises(TypeError):
            error_checking.assert_is_numpy_array(
                REAL_NUMPY_ARRAY, num_dimensions=REAL_NUMPY_ARRAY.ndim + 1)
    def test_assert_is_numpy_array_num_dim_correct(self):
        """Checks assert_is_numpy_array when `num_dimensions` is correct."""

        error_checking.assert_is_numpy_array(
            REAL_NUMPY_ARRAY, num_dimensions=REAL_NUMPY_ARRAY.ndim)
Esempio n. 21
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()
    def test_assert_is_numpy_array_scalar(self):
        """Checks assert_is_numpy_array when input is scalar."""

        with self.assertRaises(TypeError):
            error_checking.assert_is_numpy_array(SINGLE_INTEGER)