def simple_polygon_to_grid_points(vertex_row_indices, vertex_column_indices): """Finds grid points in simple polygon. V = number of vertices P = number of grid points in polygon :param vertex_row_indices: length-V numpy array with row numbers (half-integers) of vertices. :param vertex_column_indices: length-V numpy array with column numbers (half-integers) of vertices. :return: grid_point_row_indices: length-P numpy array with row numbers (integers) of grid points in polygon. :return: grid_point_column_indices: length-P numpy array with column numbers (integers) of grid points in polygon. """ polygon_object = vertex_arrays_to_polygon_object(vertex_column_indices, vertex_row_indices) min_grid_point_row = int(numpy.floor(numpy.min(vertex_row_indices))) max_grid_point_row = int(numpy.ceil(numpy.max(vertex_row_indices))) num_grid_point_rows = max_grid_point_row - min_grid_point_row + 1 grid_point_rows = numpy.linspace(min_grid_point_row, max_grid_point_row, num=num_grid_point_rows, dtype=int) min_grid_point_column = int(numpy.floor(numpy.min(vertex_column_indices))) max_grid_point_column = int(numpy.ceil(numpy.max(vertex_column_indices))) num_grid_point_columns = max_grid_point_column - min_grid_point_column + 1 grid_point_columns = numpy.linspace(min_grid_point_column, max_grid_point_column, num=num_grid_point_columns, dtype=int) grid_point_column_matrix, grid_point_row_matrix = ( grids.xy_vectors_to_matrices(grid_point_columns, grid_point_rows)) grid_point_row_vector = numpy.reshape(grid_point_row_matrix, grid_point_row_matrix.size) grid_point_column_vector = numpy.reshape(grid_point_column_matrix, grid_point_column_matrix.size) num_grid_points = len(grid_point_row_vector) in_polygon_flags = numpy.full(num_grid_points, False, dtype=bool) for i in range(num_grid_points): in_polygon_flags[i] = point_in_or_on_polygon( polygon_object, query_x_coordinate=grid_point_column_vector[i], query_y_coordinate=grid_point_row_vector[i]) in_polygon_indices = numpy.where(in_polygon_flags)[0] return (grid_point_row_vector[in_polygon_indices], grid_point_column_vector[in_polygon_indices])
def test_xy_vectors_to_matrices(self): """Ensures correct output from xy_vectors_to_matrices.""" (grid_point_x_matrix_metres, grid_point_y_matrix_metres) = grids.xy_vectors_to_matrices( EXPECTED_GRID_POINT_X_METRES, EXPECTED_GRID_POINT_Y_METRES) self.assertTrue( numpy.allclose(grid_point_x_matrix_metres, EXPECTED_GRID_POINT_X_MATRIX_METRES, atol=TOLERANCE)) self.assertTrue( numpy.allclose(grid_point_y_matrix_metres, EXPECTED_GRID_POINT_Y_MATRIX_METRES, atol=TOLERANCE))
def test_xy_vectors_to_matrices(self): """Ensures correct output from xy_vectors_to_matrices.""" this_x_matrix_metres, this_y_matrix_metres = ( grids.xy_vectors_to_matrices( x_unique_metres=POINT_X_COORDS_METRES, y_unique_metres=POINT_Y_COORDS_METRES)) self.assertTrue( numpy.allclose(this_x_matrix_metres, POINT_X_MATRIX_METRES, atol=TOLERANCE)) self.assertTrue( numpy.allclose(this_y_matrix_metres, POINT_Y_MATRIX_METRES, atol=TOLERANCE))
def get_xy_grid_point_matrices(model_name, grid_name=None): """Returns x- and y-coordinates of all grid points. M = number of rows (unique y-coordinates of grid points) N = number of columns (unique x-coordinates of grid points) :param model_name: See doc for `check_grid_name`. :param grid_name: Same. :return: grid_point_x_matrix_metres: M-by-N numpy array of x-coordinates. :return: grid_point_y_matrix_metres: M-by-N numpy array of y-coordinates. """ grid_points_x_metres, grid_points_y_metres = get_xy_grid_points( model_name=model_name, grid_name=grid_name) return grids.xy_vectors_to_matrices(x_unique_metres=grid_points_x_metres, y_unique_metres=grid_points_y_metres)
def _get_basemap(grid_metadata_dict): """Creates basemap. M = number of rows in grid M = number of columns in grid :param grid_metadata_dict: Dictionary returned by `grids.read_equidistant_metafile`. :return: basemap_object: Basemap handle (instance of `mpl_toolkits.basemap.Basemap`). :return: basemap_x_matrix_metres: M-by-N numpy array of x-coordinates under Basemap projection (different than pyproj projection). :return: basemap_y_matrix_metres: Same but for y-coordinates. """ x_matrix_metres, y_matrix_metres = grids.xy_vectors_to_matrices( x_unique_metres=grid_metadata_dict[grids.X_COORDS_KEY], y_unique_metres=grid_metadata_dict[grids.Y_COORDS_KEY]) projection_object = grid_metadata_dict[grids.PROJECTION_KEY] latitude_matrix_deg, longitude_matrix_deg = ( projections.project_xy_to_latlng(x_coords_metres=x_matrix_metres, y_coords_metres=y_matrix_metres, projection_object=projection_object)) standard_latitudes_deg, central_longitude_deg = _get_lcc_params( projection_object) basemap_object = Basemap(projection='lcc', lat_1=standard_latitudes_deg[0], lat_2=standard_latitudes_deg[1], lon_0=central_longitude_deg, rsphere=projections.DEFAULT_EARTH_RADIUS_METRES, ellps=projections.SPHERE_NAME, resolution=RESOLUTION_STRING, llcrnrx=x_matrix_metres[0, 0], llcrnry=y_matrix_metres[0, 0], urcrnrx=x_matrix_metres[-1, -1], urcrnry=y_matrix_metres[-1, -1]) basemap_x_matrix_metres, basemap_y_matrix_metres = basemap_object( longitude_matrix_deg, latitude_matrix_deg) return basemap_object, basemap_x_matrix_metres, basemap_y_matrix_metres
def get_xy_grid_cell_edge_matrices(model_name, grid_id=None): """Returns matrices with x- and y-coordinates of grid-cell edges. M = number of rows (unique grid-point y-coordinates) N = number of columns (unique grid-point x-coordinates) :param model_name: Name of model. :param grid_id: ID for model grid. :return: grid_cell_edge_x_matrix_metres: (M + 1)-by-(N + 1) numpy array with x-coordinates of grid-cell edges (increasing to the right). :return: grid_cell_edge_y_matrix_metres: (M + 1)-by-(N + 1) numpy array with y-coordinates of grid-cell edges (increasing downward). """ grid_cell_edge_x_metres, grid_cell_edge_y_metres = get_xy_grid_cell_edges( model_name, grid_id=grid_id) return grids.xy_vectors_to_matrices(grid_cell_edge_x_metres, grid_cell_edge_y_metres)
def _get_distances_from_center_point(grid_spacing_x, grid_spacing_y, cutoff_radius): """For each grid point in smoothing window, computes distance from center. This method makes two key assumptions: [1] The grid is equidistant. [2] All input args have the same units (e.g., metres). m = number of grid rows used for smoothing at each point n = number of grid columns used for smoothing at each point :param grid_spacing_x: Spacing between adjacent grid points in x-direction. :param grid_spacing_y: Spacing between adjacent grid points in y-direction. :param cutoff_radius: Cutoff radius for smoother. :return: distance_from_center_matrix: m-by-n numpy array of distances from center point. m and n are always odd, and the center element is always zero. """ error_checking.assert_is_greater(grid_spacing_x, 0.) error_checking.assert_is_greater(grid_spacing_y, 0.) error_checking.assert_is_geq(cutoff_radius, grid_spacing_x) error_checking.assert_is_geq(cutoff_radius, grid_spacing_y) half_width_x_pixels = int(numpy.floor(cutoff_radius / grid_spacing_x)) half_width_y_pixels = int(numpy.floor(cutoff_radius / grid_spacing_y)) width_x_pixels = 2 * half_width_x_pixels + 1 width_y_pixels = 2 * half_width_y_pixels + 1 unique_relative_x_coords = numpy.linspace( -half_width_x_pixels * grid_spacing_x, half_width_x_pixels * grid_spacing_x, num=width_x_pixels) unique_relative_y_coords = numpy.linspace( -half_width_y_pixels * grid_spacing_y, half_width_y_pixels * grid_spacing_y, num=width_y_pixels) relative_x_matrix, relative_y_matrix = grids.xy_vectors_to_matrices( unique_relative_x_coords, unique_relative_y_coords) return numpy.sqrt(relative_x_matrix**2 + relative_y_matrix**2)
def buffer_distance_to_narr_mask(buffer_distance_metres): """Converts buffer distance to mask over NARR grid. m = number of grid rows (unique y-coordinates at grid points) within buffer distance n = number of grid columns (unique x-coordinates at grid points) within buffer distance :param buffer_distance_metres: Buffer distance. :return: mask_matrix: m-by-n numpy array of Boolean flags. mask_matrix[floor(m/2), floor(n/2)] represents the center point, around which the buffer is defined. Element [i, j] indicates whether or not grid point [i, j] is in the distance buffer. """ error_checking.assert_is_greater(buffer_distance_metres, 0.) buffer_distance_metres = max([buffer_distance_metres, 1.]) grid_spacing_metres, _ = nwp_model_utils.get_xy_grid_spacing( model_name=nwp_model_utils.NARR_MODEL_NAME) max_row_or_column_offset = int( numpy.floor(float(buffer_distance_metres) / grid_spacing_metres)) row_or_column_offsets = numpy.linspace(-max_row_or_column_offset, max_row_or_column_offset, num=2 * max_row_or_column_offset + 1, dtype=int) column_offset_matrix, row_offset_matrix = grids.xy_vectors_to_matrices( x_unique_metres=row_or_column_offsets, y_unique_metres=row_or_column_offsets) row_offset_matrix = row_offset_matrix.astype(float) column_offset_matrix = column_offset_matrix.astype(float) distance_matrix_metres = grid_spacing_metres * numpy.sqrt( row_offset_matrix**2 + column_offset_matrix**2) return distance_matrix_metres <= buffer_distance_metres
def _run(top_gridrad_dir_name, first_spc_date_string, last_spc_date_string, colour_map_name, grid_spacing_metres, output_file_name): """Plots GridRad domains. This is effectively the main method. :param top_gridrad_dir_name: See documentation at top of file. :param first_spc_date_string: Same. :param last_spc_date_string: Same. :param colour_map_name: Same. :param grid_spacing_metres: Same. :param output_file_name: Same. """ colour_map_object = pyplot.get_cmap(colour_map_name) file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name) first_time_unix_sec = time_conversion.get_start_of_spc_date( first_spc_date_string) last_time_unix_sec = time_conversion.get_end_of_spc_date( last_spc_date_string) valid_times_unix_sec = time_periods.range_and_interval_to_list( start_time_unix_sec=first_time_unix_sec, end_time_unix_sec=last_time_unix_sec, time_interval_sec=TIME_INTERVAL_SEC, include_endpoint=True) valid_spc_date_strings = [ time_conversion.time_to_spc_date_string(t) for t in valid_times_unix_sec ] domain_min_latitudes_deg = [] domain_max_latitudes_deg = [] domain_min_longitudes_deg = [] domain_max_longitudes_deg = [] prev_domain_limits_deg = numpy.full(4, numpy.nan) prev_spc_date_string = 'foo' num_times = len(valid_times_unix_sec) for i in range(num_times): this_gridrad_file_name = gridrad_io.find_file( unix_time_sec=valid_times_unix_sec[i], top_directory_name=top_gridrad_dir_name, raise_error_if_missing=False) if not os.path.isfile(this_gridrad_file_name): continue these_domain_limits_deg = _get_domain_one_file(this_gridrad_file_name) same_domain = (valid_spc_date_strings[i] == prev_spc_date_string and numpy.allclose(these_domain_limits_deg, prev_domain_limits_deg, TOLERANCE)) if same_domain: continue prev_domain_limits_deg = these_domain_limits_deg + 0. prev_spc_date_string = valid_spc_date_strings[i] domain_min_latitudes_deg.append(these_domain_limits_deg[0]) domain_max_latitudes_deg.append(these_domain_limits_deg[1]) domain_min_longitudes_deg.append(these_domain_limits_deg[2]) domain_max_longitudes_deg.append(these_domain_limits_deg[3]) print(SEPARATOR_STRING) domain_min_latitudes_deg = numpy.array(domain_min_latitudes_deg) domain_max_latitudes_deg = numpy.array(domain_max_latitudes_deg) domain_min_longitudes_deg = numpy.array(domain_min_longitudes_deg) domain_max_longitudes_deg = numpy.array(domain_max_longitudes_deg) num_domains = len(domain_min_latitudes_deg) grid_metadata_dict = grids.create_equidistant_grid( min_latitude_deg=OVERALL_MIN_LATITUDE_DEG, max_latitude_deg=OVERALL_MAX_LATITUDE_DEG, min_longitude_deg=OVERALL_MIN_LONGITUDE_DEG, max_longitude_deg=OVERALL_MAX_LONGITUDE_DEG, x_spacing_metres=grid_spacing_metres, y_spacing_metres=grid_spacing_metres, azimuthal=False) unique_x_coords_metres = grid_metadata_dict[grids.X_COORDS_KEY] unique_y_coords_metres = grid_metadata_dict[grids.Y_COORDS_KEY] projection_object = grid_metadata_dict[grids.PROJECTION_KEY] x_coord_matrix_metres, y_coord_matrix_metres = grids.xy_vectors_to_matrices( x_unique_metres=unique_x_coords_metres, y_unique_metres=unique_y_coords_metres) latitude_matrix_deg, longitude_matrix_deg = ( projections.project_xy_to_latlng(x_coords_metres=x_coord_matrix_metres, y_coords_metres=y_coord_matrix_metres, projection_object=projection_object)) num_grid_rows = latitude_matrix_deg.shape[0] num_grid_columns = latitude_matrix_deg.shape[1] num_days_matrix = numpy.full((num_grid_rows, num_grid_columns), 0) for i in range(num_domains): if numpy.mod(i, 10) == 0: print('Have found grid points in {0:d} of {1:d} domains...'.format( i, num_domains)) this_lat_flag_matrix = numpy.logical_and( latitude_matrix_deg >= domain_min_latitudes_deg[i], latitude_matrix_deg <= domain_max_latitudes_deg[i]) this_lng_flag_matrix = numpy.logical_and( longitude_matrix_deg >= domain_min_longitudes_deg[i], longitude_matrix_deg <= domain_max_longitudes_deg[i]) num_days_matrix += numpy.logical_and(this_lat_flag_matrix, this_lng_flag_matrix).astype(int) print(SEPARATOR_STRING) figure_object, axes_object = _plot_data( num_days_matrix=num_days_matrix, grid_metadata_dict=grid_metadata_dict, colour_map_object=colour_map_object) plotting_utils.label_axes(axes_object=axes_object, label_string='(c)') print('Saving figure to: "{0:s}"...'.format(output_file_name)) figure_object.savefig(output_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object)
x_max_metres = number_rounding.ceiling_to_nearest(x_max_metres, X_SPACING_METRES) y_min_metres = number_rounding.floor_to_nearest(y_min_metres, Y_SPACING_METRES) y_max_metres = number_rounding.ceiling_to_nearest(y_max_metres, Y_SPACING_METRES) num_grid_rows = 1 + int(numpy.round((y_max_metres - y_min_metres) / Y_SPACING_METRES)) num_grid_columns = 1 + int(numpy.round((x_max_metres - x_min_metres) / X_SPACING_METRES)) (unique_grid_point_x_metres, unique_grid_point_y_metres) = grids.get_xy_grid_points( x_min_metres=x_min_metres, y_min_metres=y_min_metres, x_spacing_metres=X_SPACING_METRES, y_spacing_metres=Y_SPACING_METRES, num_rows=num_grid_rows, num_columns=num_grid_columns) (grid_point_x_matrix_metres, grid_point_y_matrix_metres) = grids.xy_vectors_to_matrices( x_unique_metres=unique_grid_point_x_metres, y_unique_metres=unique_grid_point_y_metres) storm_object_table_by_spc_date = [None] * num_spc_dates num_grid_rows = len(unique_grid_point_y_metres) num_grid_columns = len(unique_grid_point_x_metres) grid_cell_count_matrix = numpy.full((num_grid_rows, num_grid_columns), 0, dtype=int) for working_date_index in range(num_spc_dates): date_in_memory_indices = utils._get_dates_needed(working_date_index=working_date_index, num_dates=num_spc_dates, climatology_type=PASSAGE_CLIMATOLOGY_TYPE) for i in range(num_spc_dates): if i in date_in_memory_indices: if storm_object_table_by_spc_date[i] is None: # Find tracking files for [i]th date.