def read_field_from_grib_file( grib_file_name, field_name_grib1, model_name, grid_id=None, temporary_dir_name=None, wgrib_exe_name=grib_io.WGRIB_EXE_NAME_DEFAULT, wgrib2_exe_name=grib_io.WGRIB2_EXE_NAME_DEFAULT, raise_error_if_fails=True): """Reads field from grib file. One field = one variable at one time step. :param grib_file_name: Path to input file. :param field_name_grib1: See doc for `grib_io.read_field_from_grib_file`. :param model_name: See doc for `nwp_model_utils.check_grid_name`. :param grid_id: Same. :param temporary_dir_name: See doc for `grib_io.read_field_from_grib_file`. :param wgrib_exe_name: Same. :param wgrib2_exe_name: Same. :param raise_error_if_fails: Same. :return: field_matrix: Same. """ num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=model_name, grid_name=grid_id) return grib_io.read_field_from_grib_file( grib_file_name=grib_file_name, field_name_grib1=field_name_grib1, num_grid_rows=num_grid_rows, num_grid_columns=num_grid_columns, sentinel_value=nwp_model_utils.SENTINEL_VALUE, temporary_dir_name=temporary_dir_name, wgrib_exe_name=wgrib_exe_name, wgrib2_exe_name=wgrib2_exe_name, raise_error_if_fails=raise_error_if_fails)
def _check_model_fields(field_matrix, field_name, pressure_level_pascals, valid_times_unix_sec): """Checks model fields for errors. M = number of rows (unique grid-point y-coordinates) N = number of columns (unique grid-point x-coordinates) T = number of time steps :param field_matrix: T-by-M-by-N numpy array with values of a single field (atmospheric variable). :param field_name: Field name in GewitterGefahr format. :param pressure_level_pascals: Pressure level (integer Pascals). :param valid_times_unix_sec: length-T numpy array of valid times. """ check_field_name(field_name, require_standard=False) error_checking.assert_is_integer(pressure_level_pascals) error_checking.assert_is_integer_numpy_array(valid_times_unix_sec) error_checking.assert_is_numpy_array(valid_times_unix_sec, num_dimensions=1) num_times = len(valid_times_unix_sec) num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME) error_checking.assert_is_real_numpy_array(field_matrix) error_checking.assert_is_numpy_array(field_matrix, num_dimensions=3) error_checking.assert_is_numpy_array(field_matrix, exact_dimensions=numpy.array([ num_times, num_grid_rows, num_grid_columns ]))
def test_dimensions_to_grid_id_252(self): """Ensures correct output from dimensions_to_grid_id for 252 grid.""" these_dimensions = numpy.array(nwp_model_utils.get_grid_dimensions( nwp_model_utils.RUC_MODEL_NAME, nwp_model_utils.ID_FOR_252GRID)) this_grid_id = nwp_model_utils.dimensions_to_grid_id(these_dimensions) self.assertTrue(this_grid_id == nwp_model_utils.ID_FOR_252GRID)
def test_dimensions_to_grid_252(self): """Ensures correct output from dimensions_to_grid for NCEP 252 grid.""" this_num_rows, this_num_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.RAP_MODEL_NAME, grid_name=nwp_model_utils.NAME_OF_252GRID) this_grid_name = nwp_model_utils.dimensions_to_grid( num_rows=this_num_rows, num_columns=this_num_columns) self.assertTrue(this_grid_name == nwp_model_utils.NAME_OF_252GRID)
def _get_random_sample_points( num_points, for_downsized_examples, narr_mask_matrix=None): """Samples random points from NARR grid. M = number of rows in NARR grid N = number of columns in NARR grid P = number of points sampled :param num_points: Number of points to sample. :param for_downsized_examples: Boolean flag. If True, this method will sample center points for downsized images. If False, will sample evaluation points from a full-size image. :param narr_mask_matrix: M-by-N numpy array of integers (0 or 1). If narr_mask_matrix[i, j] = 0, cell [i, j] in the full grid will never be sampled. If `narr_mask_matrix is None`, any grid cell can be sampled. :return: row_indices: length-P numpy array with row indices of sampled points. :return: column_indices: length-P numpy array with column indices of sampled points. """ if for_downsized_examples: num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME) else: num_grid_rows = ( ml_utils.LAST_NARR_ROW_FOR_FCN_INPUT - ml_utils.FIRST_NARR_ROW_FOR_FCN_INPUT + 1 ) num_grid_columns = ( ml_utils.LAST_NARR_COLUMN_FOR_FCN_INPUT - ml_utils.FIRST_NARR_COLUMN_FOR_FCN_INPUT + 1 ) narr_mask_matrix = None if narr_mask_matrix is None: num_grid_cells = num_grid_rows * num_grid_columns possible_linear_indices = numpy.linspace( 0, num_grid_cells - 1, num=num_grid_cells, dtype=int) else: error_checking.assert_is_integer_numpy_array(narr_mask_matrix) error_checking.assert_is_geq_numpy_array(narr_mask_matrix, 0) error_checking.assert_is_leq_numpy_array(narr_mask_matrix, 1) error_checking.assert_is_numpy_array( narr_mask_matrix, exact_dimensions=numpy.array([num_grid_rows, num_grid_columns])) possible_linear_indices = numpy.where( numpy.ravel(narr_mask_matrix) == 1)[0] linear_indices = numpy.random.choice( possible_linear_indices, size=num_points, replace=False) return numpy.unravel_index( linear_indices, (num_grid_rows, num_grid_columns))
def test_dimensions_to_grid_extended221(self): """Ensures correctness of dimensions_to_grid for extended 221 grid.""" this_num_rows, this_num_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME, grid_name=nwp_model_utils.NAME_OF_EXTENDED_221GRID) this_grid_name = nwp_model_utils.dimensions_to_grid( num_rows=this_num_rows, num_columns=this_num_columns) self.assertTrue( this_grid_name == nwp_model_utils.NAME_OF_EXTENDED_221GRID)
def _run(): """Plots dilation of WPC fronts. This is effectively the main method. """ print 'Reading data from: "{0:s}"...'.format(FRONT_LINE_FILE_NAME) front_line_table = fronts_io.read_polylines_from_file(FRONT_LINE_FILE_NAME) print 'Reading data from: "{0:s}"...'.format(FRONTAL_GRID_FILE_NAME) frontal_grid_table = fronts_io.read_narr_grids_from_file( FRONTAL_GRID_FILE_NAME) num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME) ternary_front_matrix = ml_utils.front_table_to_images( frontal_grid_table=frontal_grid_table, num_rows_per_image=num_grid_rows, num_columns_per_image=num_grid_columns) _plot_fronts(front_line_table=front_line_table, ternary_front_matrix=ternary_front_matrix, title_string='Observed fronts before dilation', annotation_string='(a)', output_file_name=BEFORE_FILE_NAME) ternary_front_matrix = ml_utils.dilate_ternary_target_images( target_matrix=ternary_front_matrix, dilation_distance_metres=DILATION_DISTANCE_METRES, verbose=False) _plot_fronts(front_line_table=front_line_table, ternary_front_matrix=ternary_front_matrix, title_string='Observed fronts after dilation', annotation_string='(b)', output_file_name=AFTER_FILE_NAME) print 'Concatenating figures to: "{0:s}"...'.format(CONCAT_FILE_NAME) imagemagick_utils.concatenate_images( input_file_names=[BEFORE_FILE_NAME, AFTER_FILE_NAME], output_file_name=CONCAT_FILE_NAME, num_panel_rows=1, num_panel_columns=2) imagemagick_utils.resize_image(input_file_name=CONCAT_FILE_NAME, output_file_name=CONCAT_FILE_NAME, output_size_pixels=CONCAT_SIZE_PIXELS)
def polyline_to_narr_grid(polyline_latitudes_deg, polyline_longitudes_deg, dilation_distance_metres): """Converts polyline to binary image over NARR grid. V = number of vertices in polyline :param polyline_latitudes_deg: length-V numpy array of latitudes (deg N). :param polyline_longitudes_deg: length-V numpy array of longitudes (deg E). :param dilation_distance_metres: Dilation distance. This gives fronts a non-infinitesimal width, which allows them to be more than one grid cell (pixel) wide. This accounts for spatial uncertainty in the placement of fronts. :return: binary_image_matrix: See documentation for `_check_frontal_image`. This will be a 277-by-349 matrix, to match the dimensions of the NARR grid. """ polyline_x_coords_metres, polyline_y_coords_metres = ( nwp_model_utils.project_latlng_to_xy( latitudes_deg=polyline_latitudes_deg, longitudes_deg=polyline_longitudes_deg, model_name=nwp_model_utils.NARR_MODEL_NAME)) grid_point_x_coords_metres, grid_point_y_coords_metres = ( nwp_model_utils.get_xy_grid_points( model_name=nwp_model_utils.NARR_MODEL_NAME)) rows_in_polyline, columns_in_polyline = _polyline_to_grid_points( polyline_x_coords_metres=polyline_x_coords_metres, polyline_y_coords_metres=polyline_y_coords_metres, grid_point_x_coords_metres=grid_point_x_coords_metres, grid_point_y_coords_metres=grid_point_y_coords_metres) num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME) binary_image_matrix = _grid_points_to_binary_image( rows_in_object=rows_in_polyline, columns_in_object=columns_in_polyline, num_grid_rows=num_grid_rows, num_grid_columns=num_grid_columns) return dilate_binary_narr_image( binary_image_matrix=binary_image_matrix.astype(int), dilation_distance_metres=dilation_distance_metres)
def test_projection_grid130(self): """Ensures approx correctness of Lambert projection for NCEP 130 grid. This method ensures that x-y coordinates for all grid points can be generated accurately from lat-long coordinates. Specifically, the mean and max distance errors must be <= 100 and 500 metres, respectively. NOTE: This test relies on several methods, so it is not a unit test. """ num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.RAP_MODEL_NAME, grid_id=nwp_model_utils.ID_FOR_130GRID) (grid_point_lng_vector_deg, grid_point_lat_vector_deg) = numpy.loadtxt( GRID130_LATLNG_FILE_NAME, unpack=True) grid_point_lat_matrix_deg = numpy.reshape( grid_point_lat_vector_deg, (num_grid_rows, num_grid_columns)) grid_point_lng_matrix_deg = numpy.reshape( grid_point_lng_vector_deg, (num_grid_rows, num_grid_columns)) grid_point_x_matrix_metres, grid_point_y_matrix_metres = ( nwp_model_utils.project_latlng_to_xy( grid_point_lat_matrix_deg, grid_point_lng_matrix_deg, model_name=nwp_model_utils.RAP_MODEL_NAME, grid_id=nwp_model_utils.ID_FOR_130GRID)) (expected_grid_point_x_matrix_metres, expected_grid_point_y_matrix_metres) = ( nwp_model_utils.get_xy_grid_point_matrices( model_name=nwp_model_utils.RAP_MODEL_NAME, grid_id=nwp_model_utils.ID_FOR_130GRID)) x_error_matrix_metres = ( grid_point_x_matrix_metres - expected_grid_point_x_matrix_metres) y_error_matrix_metres = ( grid_point_y_matrix_metres - expected_grid_point_y_matrix_metres) distance_error_matrix_metres = numpy.sqrt( x_error_matrix_metres ** 2 + y_error_matrix_metres ** 2) self.assertTrue(numpy.mean( distance_error_matrix_metres) <= MAX_MEAN_DISTANCE_ERROR_RAP_METRES) self.assertTrue(numpy.max( distance_error_matrix_metres) <= MAX_MAX_DISTANCE_ERROR_RAP_METRES)
def test_wind_rotation_angles_grid130(self): """Ensures approx correctness of wind-rotation angles on NCEP 130 grid. This method ensures that the wind-rotation angle for all grid points can be generated accurately from lat-long coordinates. Specifically, the mean sine and cosine error must be <= 10^-5 and max error must be <= 10^-4. NOTE: This test relies on methods other than get_wind_rotation_angles, so it is not a unit test. """ num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.RAP_MODEL_NAME, grid_id=nwp_model_utils.ID_FOR_130GRID) expected_cos_vector, expected_sin_vector = numpy.loadtxt( GRID130_WIND_ROTATION_FILE_NAME, unpack=True) expected_cos_matrix = numpy.reshape( expected_cos_vector, (num_grid_rows, num_grid_columns)) expected_sin_matrix = numpy.reshape( expected_sin_vector, (num_grid_rows, num_grid_columns)) grid_point_lat_matrix_deg, grid_point_lng_matrix_deg = ( nwp_model_utils.get_latlng_grid_point_matrices( model_name=nwp_model_utils.RAP_MODEL_NAME, grid_id=nwp_model_utils.ID_FOR_130GRID)) rotation_angle_cos_matrix, rotation_angle_sin_matrix = ( nwp_model_utils.get_wind_rotation_angles( grid_point_lat_matrix_deg, grid_point_lng_matrix_deg, model_name=nwp_model_utils.RAP_MODEL_NAME)) cos_error_matrix = numpy.absolute( rotation_angle_cos_matrix - expected_cos_matrix) sin_error_matrix = numpy.absolute( rotation_angle_sin_matrix - expected_sin_matrix) self.assertTrue( numpy.mean(cos_error_matrix) <= MAX_MEAN_SIN_OR_COS_ERROR) self.assertTrue(numpy.max(cos_error_matrix) <= MAX_MAX_SIN_OR_COS_ERROR) self.assertTrue( numpy.mean(sin_error_matrix) <= MAX_MEAN_SIN_OR_COS_ERROR) self.assertTrue(numpy.max(sin_error_matrix) <= MAX_MAX_SIN_OR_COS_ERROR)
def test_projection_extended221(self): """Ensures approx correctness of Lambert proj for extended 221 grid.""" num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME, grid_name=nwp_model_utils.NAME_OF_221GRID) unique_longitudes_deg, unique_latitudes_deg = numpy.loadtxt( NARR_LATLNG_FILE_NAME, unpack=True) latitude_matrix_deg = numpy.reshape(unique_latitudes_deg, (num_grid_rows, num_grid_columns)) longitude_matrix_deg = numpy.reshape(unique_longitudes_deg, (num_grid_rows, num_grid_columns)) x_matrix_metres, y_matrix_metres = nwp_model_utils.project_latlng_to_xy( latitudes_deg=latitude_matrix_deg, longitudes_deg=longitude_matrix_deg, model_name=nwp_model_utils.NARR_MODEL_NAME, grid_name=nwp_model_utils.NAME_OF_221GRID) expected_x_matrix_metres, expected_y_matrix_metres = ( nwp_model_utils.get_xy_grid_point_matrices( model_name=nwp_model_utils.NARR_MODEL_NAME, grid_name=nwp_model_utils.NAME_OF_EXTENDED_221GRID)) expected_x_matrix_metres = expected_x_matrix_metres[100:-100, 100:-100] expected_y_matrix_metres = expected_y_matrix_metres[100:-100, 100:-100] expected_x_matrix_metres -= expected_x_matrix_metres[0, 0] expected_y_matrix_metres -= expected_y_matrix_metres[0, 0] x_error_matrix_metres = x_matrix_metres - expected_x_matrix_metres y_error_matrix_metres = y_matrix_metres - expected_y_matrix_metres distance_error_matrix_metres = numpy.sqrt(x_error_matrix_metres**2 + y_error_matrix_metres**2) self.assertTrue( numpy.mean(distance_error_matrix_metres) <= MAX_MEAN_DISTANCE_ERROR_NARR_METRES) self.assertTrue( numpy.max(distance_error_matrix_metres) <= MAX_MAX_DISTANCE_ERROR_NARR_METRES)
def test_projection_grid252(self): """Ensures approx correctness of Lambert projection for NCEP 252 grid. See documentation for test_projection_grid130. """ num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.RAP_MODEL_NAME, grid_id=nwp_model_utils.ID_FOR_252GRID) (grid_point_lng_vector_deg, grid_point_lat_vector_deg) = numpy.loadtxt( GRID252_LATLNG_FILE_NAME, unpack=True) grid_point_lat_matrix_deg = numpy.reshape( grid_point_lat_vector_deg, (num_grid_rows, num_grid_columns)) grid_point_lng_matrix_deg = numpy.reshape( grid_point_lng_vector_deg, (num_grid_rows, num_grid_columns)) grid_point_x_matrix_metres, grid_point_y_matrix_metres = ( nwp_model_utils.project_latlng_to_xy( grid_point_lat_matrix_deg, grid_point_lng_matrix_deg, model_name=nwp_model_utils.RAP_MODEL_NAME, grid_id=nwp_model_utils.ID_FOR_252GRID)) (expected_grid_point_x_matrix_metres, expected_grid_point_y_matrix_metres) = ( nwp_model_utils.get_xy_grid_point_matrices( model_name=nwp_model_utils.RAP_MODEL_NAME, grid_id=nwp_model_utils.ID_FOR_252GRID)) x_error_matrix_metres = ( grid_point_x_matrix_metres - expected_grid_point_x_matrix_metres) y_error_matrix_metres = ( grid_point_y_matrix_metres - expected_grid_point_y_matrix_metres) distance_error_matrix_metres = numpy.sqrt( x_error_matrix_metres ** 2 + y_error_matrix_metres ** 2) self.assertTrue(numpy.mean( distance_error_matrix_metres) <= MAX_MEAN_DISTANCE_ERROR_RAP_METRES) self.assertTrue(numpy.max( distance_error_matrix_metres) <= MAX_MAX_DISTANCE_ERROR_RAP_METRES)
def test_wind_rotation_angles_grid252(self): """Ensures approx correctness of rotation angles for NCEP 252 grid.""" num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.RAP_MODEL_NAME, grid_name=nwp_model_utils.NAME_OF_252GRID) expected_cos_vector, expected_sin_vector = numpy.loadtxt( GRID252_WIND_ROTATION_FILE_NAME, unpack=True) expected_cos_matrix = numpy.reshape(expected_cos_vector, (num_grid_rows, num_grid_columns)) expected_sin_matrix = numpy.reshape(expected_sin_vector, (num_grid_rows, num_grid_columns)) latitude_matrix_deg, longitude_matrix_deg = ( nwp_model_utils.get_latlng_grid_point_matrices( model_name=nwp_model_utils.RAP_MODEL_NAME, grid_name=nwp_model_utils.NAME_OF_252GRID)) rotation_angle_cos_matrix, rotation_angle_sin_matrix = ( nwp_model_utils.get_wind_rotation_angles( latitudes_deg=latitude_matrix_deg, longitudes_deg=longitude_matrix_deg, model_name=nwp_model_utils.RAP_MODEL_NAME)) cos_error_matrix = numpy.absolute(rotation_angle_cos_matrix - expected_cos_matrix) sin_error_matrix = numpy.absolute(rotation_angle_sin_matrix - expected_sin_matrix) self.assertTrue( numpy.mean(cos_error_matrix) <= MAX_MEAN_SIN_OR_COS_ERROR) self.assertTrue( numpy.max(cos_error_matrix) <= MAX_MAX_SIN_OR_COS_ERROR) self.assertTrue( numpy.mean(sin_error_matrix) <= MAX_MEAN_SIN_OR_COS_ERROR) self.assertTrue( numpy.max(sin_error_matrix) <= MAX_MAX_SIN_OR_COS_ERROR)
def _get_grid_point_coords(model_name, first_row_in_full_grid, last_row_in_full_grid, first_column_in_full_grid, last_column_in_full_grid, grid_id=None, basemap_object=None): """Returns x-y and lat-long coords for a subgrid of the full model grid. This method generates different x-y coordinates than `nwp_model_utils.get_xy_grid_point_matrices`, because (like `mpl_toolkits.basemap.Basemap`) this method sets false easting = false northing = 0 metres. :param model_name: Name of NWP model (must be accepted by `nwp_model_utils.check_grid_name`). :param first_row_in_full_grid: Row 0 in the subgrid is row `first_row_in_full_grid` in the full grid. :param last_row_in_full_grid: Last row in the subgrid is row `last_row_in_full_grid` in the full grid. If you want last row in the subgrid to equal last row in the full grid, make this -1. :param first_column_in_full_grid: Column 0 in the subgrid is column `first_column_in_full_grid` in the full grid. :param last_column_in_full_grid: Last column in the subgrid is column `last_column_in_full_grid` in the full grid. If you want last column in the subgrid to equal last column in the full grid, make this -1. :param grid_id: Grid for NWP model (must be accepted by `nwp_model_utils.check_grid_name`). :param basemap_object: Instance of `mpl_toolkits.basemap.Basemap` for the given NWP model. If you don't have one, no big deal -- leave this argument empty. :return: coordinate_dict: Dictionary with the following keys. coordinate_dict['grid_point_x_matrix_metres']: M-by-N numpy array of x-coordinates. coordinate_dict['grid_point_y_matrix_metres']: M-by-N numpy array of y-coordinates. coordinate_dict['grid_point_lat_matrix_deg']: M-by-N numpy array of latitudes (deg N). coordinate_dict['grid_point_lng_matrix_deg']: M-by-N numpy array of longitudes (deg E). """ num_rows_in_full_grid, num_columns_in_full_grid = ( nwp_model_utils.get_grid_dimensions(model_name=model_name, grid_name=grid_id)) error_checking.assert_is_integer(first_row_in_full_grid) error_checking.assert_is_geq(first_row_in_full_grid, 0) error_checking.assert_is_integer(last_row_in_full_grid) if last_row_in_full_grid < 0: last_row_in_full_grid += num_rows_in_full_grid error_checking.assert_is_greater(last_row_in_full_grid, first_row_in_full_grid) error_checking.assert_is_less_than(last_row_in_full_grid, num_rows_in_full_grid) error_checking.assert_is_integer(first_column_in_full_grid) error_checking.assert_is_geq(first_column_in_full_grid, 0) error_checking.assert_is_integer(last_column_in_full_grid) if last_column_in_full_grid < 0: last_column_in_full_grid += num_columns_in_full_grid error_checking.assert_is_greater(last_column_in_full_grid, first_column_in_full_grid) error_checking.assert_is_less_than(last_column_in_full_grid, num_columns_in_full_grid) grid_point_lat_matrix_deg, grid_point_lng_matrix_deg = ( nwp_model_utils.get_latlng_grid_point_matrices(model_name=model_name, grid_name=grid_id)) grid_point_lat_matrix_deg = grid_point_lat_matrix_deg[ first_row_in_full_grid:(last_row_in_full_grid + 1), first_column_in_full_grid:(last_column_in_full_grid + 1)] grid_point_lng_matrix_deg = grid_point_lng_matrix_deg[ first_row_in_full_grid:(last_row_in_full_grid + 1), first_column_in_full_grid:(last_column_in_full_grid + 1)] if basemap_object is None: standard_latitudes_deg, central_longitude_deg = ( nwp_model_utils.get_projection_params(model_name)) projection_object = projections.init_lcc_projection( standard_latitudes_deg=standard_latitudes_deg, central_longitude_deg=central_longitude_deg) grid_point_x_matrix_metres, grid_point_y_matrix_metres = ( projections.project_latlng_to_xy( latitudes_deg=grid_point_lat_matrix_deg, longitudes_deg=grid_point_lng_matrix_deg, projection_object=projection_object, false_northing_metres=0., false_easting_metres=0.)) else: grid_point_x_matrix_metres, grid_point_y_matrix_metres = basemap_object( grid_point_lng_matrix_deg, grid_point_lat_matrix_deg) return { X_COORD_MATRIX_KEY: grid_point_x_matrix_metres, Y_COORD_MATRIX_KEY: grid_point_y_matrix_metres, LATITUDE_MATRIX_KEY: grid_point_lat_matrix_deg, LONGITUDE_MATRIX_KEY: grid_point_lng_matrix_deg, }
def _run(top_frontal_grid_dir_name, first_time_string, last_time_string, dilation_distance_metres, min_num_fronts, output_dir_name): """Creates mask, indicating where human forecasters usually draw fronts. This is effectively the main method. :param top_frontal_grid_dir_name: See documentation at top of file. :param first_time_string: Same. :param last_time_string: Same. :param dilation_distance_metres: Same. :param min_num_fronts: Same. :param output_dir_name: Same. """ file_system_utils.mkdir_recursive_if_necessary( directory_name=output_dir_name) error_checking.assert_is_greater(min_num_fronts, 0) first_time_unix_sec = time_conversion.string_to_unix_sec( first_time_string, INPUT_TIME_FORMAT) last_time_unix_sec = time_conversion.string_to_unix_sec( last_time_string, INPUT_TIME_FORMAT) 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_SECONDS) num_times = len(valid_times_unix_sec) num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME) num_cold_fronts_matrix = None num_warm_fronts_matrix = None for i in range(num_times): this_file_name = fronts_io.find_file_for_one_time( top_directory_name=top_frontal_grid_dir_name, file_type=fronts_io.GRIDDED_FILE_TYPE, valid_time_unix_sec=valid_times_unix_sec[i], raise_error_if_missing=False) if not os.path.isfile(this_file_name): warning_string = ('POTENTIAL PROBLEM. Cannot find file: "{0:s}"' ).format(this_file_name) warnings.warn(warning_string) continue print 'Reading data from: "{0:s}"...'.format(this_file_name) this_frontal_grid_table = fronts_io.read_narr_grids_from_file( this_file_name) this_frontal_grid_matrix = ml_utils.front_table_to_images( frontal_grid_table=this_frontal_grid_table, num_rows_per_image=num_grid_rows, num_columns_per_image=num_grid_columns) this_frontal_grid_matrix = ml_utils.dilate_ternary_target_images( target_matrix=this_frontal_grid_matrix, dilation_distance_metres=dilation_distance_metres, verbose=False) this_frontal_grid_matrix = this_frontal_grid_matrix[0, ...] this_num_cold_fronts_matrix = (this_frontal_grid_matrix == front_utils. COLD_FRONT_INTEGER_ID).astype(int) this_num_warm_fronts_matrix = (this_frontal_grid_matrix == front_utils. WARM_FRONT_INTEGER_ID).astype(int) if num_cold_fronts_matrix is None: num_cold_fronts_matrix = this_num_cold_fronts_matrix + 0 num_warm_fronts_matrix = this_num_warm_fronts_matrix + 0 else: num_cold_fronts_matrix = (num_cold_fronts_matrix + this_num_cold_fronts_matrix) num_warm_fronts_matrix = (num_warm_fronts_matrix + this_num_warm_fronts_matrix) print SEPARATOR_STRING print 'Masking out grid cells with < {0:d} fronts...'.format( min_num_fronts) num_both_fronts_matrix = num_warm_fronts_matrix + num_cold_fronts_matrix mask_matrix = (num_both_fronts_matrix >= min_num_fronts).astype(int) pickle_file_name = '{0:s}/narr_mask.p'.format(output_dir_name) print 'Writing mask to: "{0:s}"...'.format(pickle_file_name) ml_utils.write_narr_mask(mask_matrix=mask_matrix, pickle_file_name=pickle_file_name) warm_front_map_file_name = '{0:s}/num_warm_fronts.jpg'.format( output_dir_name) _plot_front_densities(num_fronts_matrix=num_warm_fronts_matrix, colour_map_object=WARM_FRONT_COLOUR_MAP_OBJECT, title_string='Number of warm fronts', annotation_string='(a)', output_file_name=warm_front_map_file_name, mask_matrix=None, add_colour_bar=True) cold_front_map_file_name = '{0:s}/num_cold_fronts.jpg'.format( output_dir_name) _plot_front_densities(num_fronts_matrix=num_cold_fronts_matrix, colour_map_object=COLD_FRONT_COLOUR_MAP_OBJECT, title_string='Number of cold fronts', annotation_string='(b)', output_file_name=cold_front_map_file_name, mask_matrix=None, add_colour_bar=True) both_fronts_title_string = 'Grid cells with at least {0:d} fronts'.format( min_num_fronts) both_fronts_map_file_name = '{0:s}/num_both_fronts.jpg'.format( output_dir_name) num_both_fronts_matrix[num_both_fronts_matrix > 1] = 1 _plot_front_densities(num_fronts_matrix=num_both_fronts_matrix, colour_map_object=BOTH_FRONTS_COLOUR_MAP_OBJECT, title_string=both_fronts_title_string, annotation_string='(c)', output_file_name=both_fronts_map_file_name, mask_matrix=mask_matrix, add_colour_bar=False)
def read_field_from_grib_file(grib_file_name, init_time_unix_sec=None, lead_time_hours=None, model_name=None, grid_id=None, top_single_field_dir_name=None, grib1_field_name=None, wgrib_exe_name=grib_io.WGRIB_EXE_NAME_DEFAULT, wgrib2_exe_name=grib_io.WGRIB2_EXE_NAME_DEFAULT, delete_single_field_file=True, raise_error_if_fails=True): """Reads single field from grib file. "Single field" = one variable at one time step and all grid cells. :param grib_file_name: Path to input file. :param init_time_unix_sec: Model-initialization time (Unix format). :param lead_time_hours: Lead time (valid time minus init time). If model is a reanalysis, you can leave this as None (always zero). :param model_name: Name of model. :param grid_id: String ID for model grid. :param top_single_field_dir_name: Name of top-level directory with single- field files for the given model/grib combo. :param grib1_field_name: Field name in grib1 format. :param wgrib_exe_name: Path to wgrib executable. :param wgrib2_exe_name: Path to wgrib2 executable. :param delete_single_field_file: Boolean flag. If True, single-field file will be a temp file (deleted immediately upon reading). :param raise_error_if_fails: Boolean flag. If True and field cannot be read, will raise an error. If False and field cannot be read, all return variables will be None. :return: field_matrix: See documentation for `grib_io.read_field_from_grib_file`. :return: single_field_file_name: Path to output file (containing single field). If delete_single_field_file = True, this will be None. """ error_checking.assert_is_boolean(delete_single_field_file) if delete_single_field_file: single_field_file_object = tempfile.NamedTemporaryFile(delete=False) single_field_file_name = single_field_file_object.name else: single_field_file_name = find_single_field_file( init_time_unix_sec, lead_time_hours=lead_time_hours, model_name=model_name, grid_id=grid_id, grib1_field_name=grib1_field_name, top_directory_name=top_single_field_dir_name, raise_error_if_missing=False) num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name, grid_id) sentinel_value = nwp_model_utils.SENTINEL_VALUE field_matrix = grib_io.read_field_from_grib_file( grib_file_name, grib1_field_name=grib1_field_name, single_field_file_name=single_field_file_name, wgrib_exe_name=wgrib_exe_name, wgrib2_exe_name=wgrib2_exe_name, num_grid_rows=num_grid_rows, num_grid_columns=num_grid_columns, sentinel_value=sentinel_value, delete_single_field_file=delete_single_field_file, raise_error_if_fails=raise_error_if_fails) if field_matrix is None: return None, None return field_matrix, single_field_file_name
def _run(first_time_string, last_time_string, randomize_times, num_times, thermal_field_name, smoothing_radius_pixels, warm_front_percentile, cold_front_percentile, num_closing_iters, pressure_level_mb, top_narr_directory_name, narr_mask_file_name, output_dir_name): """Uses NFA (numerical frontal analysis) to predict front type at each px. This is effectively the main method. :param first_time_string: See documentation at top of file. :param last_time_string: Same. :param randomize_times: Same. :param num_times: Same. :param thermal_field_name: Same. :param smoothing_radius_pixels: Same. :param warm_front_percentile: Same. :param cold_front_percentile: Same. :param num_closing_iters: Same. :param pressure_level_mb: Same. :param top_narr_directory_name: Same. :param narr_mask_file_name: Same. :param output_dir_name: Same. :raises: ValueError: if `thermal_field_name not in VALID_THERMAL_FIELD_NAMES`. """ if thermal_field_name not in VALID_THERMAL_FIELD_NAMES: error_string = ( '\n{0:s}\nValid thermal fields (listed above) do not include ' '"{1:s}".').format(str(VALID_THERMAL_FIELD_NAMES), thermal_field_name) raise ValueError(error_string) cutoff_radius_pixels = 4 * smoothing_radius_pixels first_time_unix_sec = time_conversion.string_to_unix_sec( first_time_string, INPUT_TIME_FORMAT) last_time_unix_sec = time_conversion.string_to_unix_sec( last_time_string, INPUT_TIME_FORMAT) 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=NARR_TIME_INTERVAL_SEC, include_endpoint=True) if randomize_times: error_checking.assert_is_leq(num_times, len(valid_times_unix_sec)) numpy.random.shuffle(valid_times_unix_sec) valid_times_unix_sec = valid_times_unix_sec[:num_times] if narr_mask_file_name == '': num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME) narr_mask_matrix = numpy.full((num_grid_rows, num_grid_columns), 1, dtype=int) else: print 'Reading mask from: "{0:s}"...\n'.format(narr_mask_file_name) narr_mask_matrix = ml_utils.read_narr_mask(narr_mask_file_name) x_spacing_metres, y_spacing_metres = nwp_model_utils.get_xy_grid_spacing( model_name=nwp_model_utils.NARR_MODEL_NAME) num_times = len(valid_times_unix_sec) for i in range(num_times): this_thermal_file_name = processed_narr_io.find_file_for_one_time( top_directory_name=top_narr_directory_name, field_name=thermal_field_name, pressure_level_mb=pressure_level_mb, valid_time_unix_sec=valid_times_unix_sec[i]) print 'Reading data from: "{0:s}"...'.format(this_thermal_file_name) this_thermal_matrix_kelvins = processed_narr_io.read_fields_from_file( this_thermal_file_name)[0][0, ...] this_thermal_matrix_kelvins = general_utils.fill_nans( this_thermal_matrix_kelvins) this_thermal_matrix_kelvins = nfa.gaussian_smooth_2d_field( field_matrix=this_thermal_matrix_kelvins, standard_deviation_pixels=smoothing_radius_pixels, cutoff_radius_pixels=cutoff_radius_pixels) this_u_wind_file_name = processed_narr_io.find_file_for_one_time( top_directory_name=top_narr_directory_name, field_name=processed_narr_io.U_WIND_GRID_RELATIVE_NAME, pressure_level_mb=pressure_level_mb, valid_time_unix_sec=valid_times_unix_sec[i]) print 'Reading data from: "{0:s}"...'.format(this_u_wind_file_name) this_u_wind_matrix_m_s01 = processed_narr_io.read_fields_from_file( this_u_wind_file_name)[0][0, ...] this_u_wind_matrix_m_s01 = general_utils.fill_nans( this_u_wind_matrix_m_s01) this_u_wind_matrix_m_s01 = nfa.gaussian_smooth_2d_field( field_matrix=this_u_wind_matrix_m_s01, standard_deviation_pixels=smoothing_radius_pixels, cutoff_radius_pixels=cutoff_radius_pixels) this_v_wind_file_name = processed_narr_io.find_file_for_one_time( top_directory_name=top_narr_directory_name, field_name=processed_narr_io.V_WIND_GRID_RELATIVE_NAME, pressure_level_mb=pressure_level_mb, valid_time_unix_sec=valid_times_unix_sec[i]) print 'Reading data from: "{0:s}"...'.format(this_v_wind_file_name) this_v_wind_matrix_m_s01 = processed_narr_io.read_fields_from_file( this_v_wind_file_name)[0][0, ...] this_v_wind_matrix_m_s01 = general_utils.fill_nans( this_v_wind_matrix_m_s01) this_v_wind_matrix_m_s01 = nfa.gaussian_smooth_2d_field( field_matrix=this_v_wind_matrix_m_s01, standard_deviation_pixels=smoothing_radius_pixels, cutoff_radius_pixels=cutoff_radius_pixels) this_tfp_matrix_kelvins_m02 = nfa.get_thermal_front_param( thermal_field_matrix_kelvins=this_thermal_matrix_kelvins, x_spacing_metres=x_spacing_metres, y_spacing_metres=y_spacing_metres) this_tfp_matrix_kelvins_m02[narr_mask_matrix == 0] = 0. this_proj_velocity_matrix_m_s01 = nfa.project_wind_to_thermal_gradient( u_matrix_grid_relative_m_s01=this_u_wind_matrix_m_s01, v_matrix_grid_relative_m_s01=this_v_wind_matrix_m_s01, thermal_field_matrix_kelvins=this_thermal_matrix_kelvins, x_spacing_metres=x_spacing_metres, y_spacing_metres=y_spacing_metres) this_locating_var_matrix_m01_s01 = nfa.get_locating_variable( tfp_matrix_kelvins_m02=this_tfp_matrix_kelvins_m02, projected_velocity_matrix_m_s01=this_proj_velocity_matrix_m_s01) this_predicted_label_matrix = nfa.get_front_types( locating_var_matrix_m01_s01=this_locating_var_matrix_m01_s01, warm_front_percentile=warm_front_percentile, cold_front_percentile=cold_front_percentile) this_predicted_label_matrix = front_utils.close_frontal_image( ternary_image_matrix=this_predicted_label_matrix, num_iterations=num_closing_iters) this_prediction_file_name = nfa.find_prediction_file( directory_name=output_dir_name, first_valid_time_unix_sec=valid_times_unix_sec[i], last_valid_time_unix_sec=valid_times_unix_sec[i], ensembled=False, raise_error_if_missing=False) print 'Writing gridded predictions to file: "{0:s}"...\n'.format( this_prediction_file_name) nfa.write_gridded_predictions( pickle_file_name=this_prediction_file_name, predicted_label_matrix=numpy.expand_dims( this_predicted_label_matrix, axis=0), valid_times_unix_sec=valid_times_unix_sec[[i]], narr_mask_matrix=narr_mask_matrix, pressure_level_mb=pressure_level_mb, smoothing_radius_pixels=smoothing_radius_pixels, cutoff_radius_pixels=cutoff_radius_pixels, warm_front_percentile=warm_front_percentile, cold_front_percentile=cold_front_percentile, num_closing_iters=num_closing_iters)
def _run(input_prediction_dir_name, first_time_string, last_time_string, num_times, binarization_threshold, min_object_area_metres2, min_endpoint_length_metres, top_front_line_dir_name, output_file_name): """Converts gridded CNN predictions to objects. This is effectively the main method. :param input_prediction_dir_name: See documentation at top of file. :param first_time_string: Same. :param last_time_string: Same. :param num_times: Same. :param binarization_threshold: Same. :param min_object_area_metres2: Same. :param min_endpoint_length_metres: Same. :param top_front_line_dir_name: Same. :param output_file_name: Same. """ grid_spacing_metres = nwp_model_utils.get_xy_grid_spacing( model_name=nwp_model_utils.NARR_MODEL_NAME)[0] num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME) first_time_unix_sec = time_conversion.string_to_unix_sec( first_time_string, INPUT_TIME_FORMAT) last_time_unix_sec = time_conversion.string_to_unix_sec( last_time_string, INPUT_TIME_FORMAT) possible_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=NARR_TIME_INTERVAL_SECONDS, include_endpoint=True) numpy.random.shuffle(possible_times_unix_sec) unix_times_sec = [] list_of_predicted_region_tables = [] num_times_done = 0 narr_mask_matrix = None for i in range(len(possible_times_unix_sec)): if num_times_done == num_times: break this_prediction_file_name = ml_utils.find_gridded_prediction_file( directory_name=input_prediction_dir_name, first_target_time_unix_sec=possible_times_unix_sec[i], last_target_time_unix_sec=possible_times_unix_sec[i], raise_error_if_missing=False) if not os.path.isfile(this_prediction_file_name): continue num_times_done += 1 unix_times_sec.append(possible_times_unix_sec[i]) print 'Reading data from: "{0:s}"...'.format(this_prediction_file_name) this_prediction_dict = ml_utils.read_gridded_predictions( this_prediction_file_name) class_probability_matrix = this_prediction_dict[ ml_utils.PROBABILITY_MATRIX_KEY] if narr_mask_matrix is None: narr_mask_matrix = numpy.invert( numpy.isnan(class_probability_matrix[0, ..., 0])).astype(int) # TODO(thunderhoser): This should be a separate method. class_probability_matrix[..., front_utils.NO_FRONT_INTEGER_ID][ numpy.isnan(class_probability_matrix[ ..., front_utils.NO_FRONT_INTEGER_ID])] = 1. class_probability_matrix[numpy.isnan(class_probability_matrix)] = 0. print 'Determinizing probabilities...' this_predicted_label_matrix = object_eval.determinize_probabilities( class_probability_matrix=this_prediction_dict[ ml_utils.PROBABILITY_MATRIX_KEY], binarization_threshold=binarization_threshold) print 'Converting image to frontal regions...' list_of_predicted_region_tables.append( object_eval.images_to_regions( predicted_label_matrix=this_predicted_label_matrix, image_times_unix_sec=possible_times_unix_sec[[i]])) print 'Throwing out frontal regions with area < {0:f} km^2...'.format( METRES2_TO_KM2 * min_object_area_metres2) list_of_predicted_region_tables[ -1] = object_eval.discard_regions_with_small_area( predicted_region_table=list_of_predicted_region_tables[-1], x_grid_spacing_metres=grid_spacing_metres, y_grid_spacing_metres=grid_spacing_metres, min_area_metres2=min_object_area_metres2) print 'Skeletonizing frontal regions...' list_of_predicted_region_tables[ -1] = object_eval.skeletonize_frontal_regions( predicted_region_table=list_of_predicted_region_tables[-1], num_grid_rows=num_grid_rows, num_grid_columns=num_grid_columns) list_of_predicted_region_tables[-1] = object_eval.find_main_skeletons( predicted_region_table=list_of_predicted_region_tables[-1], image_times_unix_sec=possible_times_unix_sec[[i]], num_grid_rows=num_grid_rows, num_grid_columns=num_grid_columns, x_grid_spacing_metres=grid_spacing_metres, y_grid_spacing_metres=grid_spacing_metres, min_endpoint_length_metres=min_endpoint_length_metres) if num_times_done != num_times: print '\n' if len(list_of_predicted_region_tables) == 1: continue list_of_predicted_region_tables[-1] = ( list_of_predicted_region_tables[-1].align( list_of_predicted_region_tables[0], axis=1)[0]) print SEPARATOR_STRING unix_times_sec = numpy.array(unix_times_sec, dtype=int) predicted_region_table = pandas.concat(list_of_predicted_region_tables, axis=0, ignore_index=True) predicted_region_table = object_eval.convert_regions_rowcol_to_narr_xy( predicted_region_table=predicted_region_table, are_predictions_from_fcn=False) actual_polyline_table = _read_actual_polylines( top_input_dir_name=top_front_line_dir_name, unix_times_sec=unix_times_sec, narr_mask_matrix=narr_mask_matrix) print SEPARATOR_STRING actual_polyline_table = object_eval.project_polylines_latlng_to_narr( actual_polyline_table) print 'Writing predicted and observed objects to: "{0:s}"...'.format( output_file_name) object_eval.write_predictions_and_obs( predicted_region_table=predicted_region_table, actual_polyline_table=actual_polyline_table, pickle_file_name=output_file_name)
def _run(): """Plots example of double penalty. This is effectively the main method. """ print 'Reading data from: "{0:s}"...'.format(INPUT_FILE_NAME) actual_grid_point_table = fronts_io.read_narr_grids_from_file( INPUT_FILE_NAME) predicted_grid_point_table = copy.deepcopy(actual_grid_point_table) predicted_grid_point_table[ front_utils.WARM_FRONT_COLUMN_INDICES_COLUMN] += 1 predicted_grid_point_table[ front_utils.COLD_FRONT_COLUMN_INDICES_COLUMN] += 1 predicted_grid_point_table[front_utils.WARM_FRONT_ROW_INDICES_COLUMN] += 1 predicted_grid_point_table[front_utils.COLD_FRONT_ROW_INDICES_COLUMN] += 1 num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME) actual_binary_matrix = ml_utils.front_table_to_images( frontal_grid_table=actual_grid_point_table, num_rows_per_image=num_grid_rows, num_columns_per_image=num_grid_columns) actual_binary_matrix = ml_utils.binarize_front_images(actual_binary_matrix) predicted_binary_matrix = ml_utils.front_table_to_images( frontal_grid_table=predicted_grid_point_table, num_rows_per_image=num_grid_rows, num_columns_per_image=num_grid_columns) predicted_binary_matrix = ml_utils.binarize_front_images( predicted_binary_matrix) _plot_fronts(actual_binary_matrix=actual_binary_matrix, predicted_binary_matrix=predicted_binary_matrix, title_string='Observed and predicted front\nwithout dilation', annotation_string='(c)', output_file_name=NO_DILATION_FILE_NAME) actual_binary_matrix = ml_utils.dilate_binary_target_images( target_matrix=actual_binary_matrix, dilation_distance_metres=DILATION_DISTANCE_METRES, verbose=False) predicted_binary_matrix = ml_utils.dilate_binary_target_images( target_matrix=predicted_binary_matrix, dilation_distance_metres=DILATION_DISTANCE_METRES, verbose=False) _plot_fronts(actual_binary_matrix=actual_binary_matrix, predicted_binary_matrix=predicted_binary_matrix, title_string='Observed and predicted front\nwith dilation', annotation_string='(d)', output_file_name=WITH_DILATION_FILE_NAME) print 'Concatenating figures to: "{0:s}"...'.format(CONCAT_FILE_NAME) imagemagick_utils.concatenate_images( input_file_names=[NO_DILATION_FILE_NAME, WITH_DILATION_FILE_NAME], output_file_name=CONCAT_FILE_NAME, num_panel_rows=1, num_panel_columns=2) imagemagick_utils.resize_image(input_file_name=CONCAT_FILE_NAME, output_file_name=CONCAT_FILE_NAME, output_size_pixels=CONCAT_SIZE_PIXELS)
def _run(valid_time_string, smoothing_radius_pixels, front_percentile, num_closing_iters, pressure_level_mb, top_narr_directory_name, narr_mask_file_name, output_dir_name): """Plots NFA (numerical frontal analysis) procedure. This is effectively the main method. :param valid_time_string: See documentation at top of file. :param smoothing_radius_pixels: Same. :param front_percentile: Same. :param num_closing_iters: Same. :param pressure_level_mb: Same. :param top_narr_directory_name: Same. :param narr_mask_file_name: Same. :param output_dir_name: Same. """ cutoff_radius_pixels = 4 * smoothing_radius_pixels valid_time_unix_sec = time_conversion.string_to_unix_sec( valid_time_string, INPUT_TIME_FORMAT) file_system_utils.mkdir_recursive_if_necessary( directory_name=output_dir_name) if narr_mask_file_name == '': num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME) narr_mask_matrix = numpy.full( (num_grid_rows, num_grid_columns), 1, dtype=int) else: print 'Reading mask from: "{0:s}"...\n'.format(narr_mask_file_name) narr_mask_matrix = ml_utils.read_narr_mask(narr_mask_file_name) wet_bulb_theta_file_name = processed_narr_io.find_file_for_one_time( top_directory_name=top_narr_directory_name, field_name=processed_narr_io.WET_BULB_THETA_NAME, pressure_level_mb=pressure_level_mb, valid_time_unix_sec=valid_time_unix_sec) print 'Reading data from: "{0:s}"...'.format(wet_bulb_theta_file_name) wet_bulb_theta_matrix_kelvins = processed_narr_io.read_fields_from_file( wet_bulb_theta_file_name)[0][0, ...] wet_bulb_theta_matrix_kelvins = general_utils.fill_nans( wet_bulb_theta_matrix_kelvins) u_wind_file_name = processed_narr_io.find_file_for_one_time( top_directory_name=top_narr_directory_name, field_name=processed_narr_io.U_WIND_GRID_RELATIVE_NAME, pressure_level_mb=pressure_level_mb, valid_time_unix_sec=valid_time_unix_sec) print 'Reading data from: "{0:s}"...'.format(u_wind_file_name) u_wind_matrix_m_s01 = processed_narr_io.read_fields_from_file( u_wind_file_name)[0][0, ...] u_wind_matrix_m_s01 = general_utils.fill_nans(u_wind_matrix_m_s01) v_wind_file_name = processed_narr_io.find_file_for_one_time( top_directory_name=top_narr_directory_name, field_name=processed_narr_io.V_WIND_GRID_RELATIVE_NAME, pressure_level_mb=pressure_level_mb, valid_time_unix_sec=valid_time_unix_sec) print 'Reading data from: "{0:s}"...'.format(v_wind_file_name) v_wind_matrix_m_s01 = processed_narr_io.read_fields_from_file( v_wind_file_name)[0][0, ...] v_wind_matrix_m_s01 = general_utils.fill_nans(v_wind_matrix_m_s01) unsmoothed_narr_file_name = '{0:s}/unsmoothed_narr_fields.jpg'.format( output_dir_name) _plot_narr_fields( wet_bulb_theta_matrix_kelvins=wet_bulb_theta_matrix_kelvins, u_wind_matrix_m_s01=u_wind_matrix_m_s01, v_wind_matrix_m_s01=v_wind_matrix_m_s01, title_string='Predictors before smoothing', annotation_string='(a)', output_file_name=unsmoothed_narr_file_name) wet_bulb_theta_matrix_kelvins = nfa.gaussian_smooth_2d_field( field_matrix=wet_bulb_theta_matrix_kelvins, standard_deviation_pixels=smoothing_radius_pixels, cutoff_radius_pixels=cutoff_radius_pixels) u_wind_matrix_m_s01 = nfa.gaussian_smooth_2d_field( field_matrix=u_wind_matrix_m_s01, standard_deviation_pixels=smoothing_radius_pixels, cutoff_radius_pixels=cutoff_radius_pixels) v_wind_matrix_m_s01 = nfa.gaussian_smooth_2d_field( field_matrix=v_wind_matrix_m_s01, standard_deviation_pixels=smoothing_radius_pixels, cutoff_radius_pixels=cutoff_radius_pixels) smoothed_narr_file_name = '{0:s}/smoothed_narr_fields.jpg'.format( output_dir_name) _plot_narr_fields( wet_bulb_theta_matrix_kelvins=wet_bulb_theta_matrix_kelvins, u_wind_matrix_m_s01=u_wind_matrix_m_s01, v_wind_matrix_m_s01=v_wind_matrix_m_s01, title_string='Predictors after smoothing', annotation_string='(b)', output_file_name=smoothed_narr_file_name) x_spacing_metres, y_spacing_metres = nwp_model_utils.get_xy_grid_spacing( model_name=nwp_model_utils.NARR_MODEL_NAME) tfp_matrix_kelvins_m02 = nfa.get_thermal_front_param( thermal_field_matrix_kelvins=wet_bulb_theta_matrix_kelvins, x_spacing_metres=x_spacing_metres, y_spacing_metres=y_spacing_metres) tfp_matrix_kelvins_m02[narr_mask_matrix == 0] = 0. tfp_file_name = '{0:s}/tfp.jpg'.format(output_dir_name) tfp_title_string = ( r'Thermal front parameter ($\times$ 10$^{-10}$ K m$^{-2}$)') _plot_tfp(tfp_matrix_kelvins_m02=tfp_matrix_kelvins_m02, title_string=tfp_title_string, annotation_string='(c)', output_file_name=tfp_file_name) proj_velocity_matrix_m_s01 = nfa.project_wind_to_thermal_gradient( u_matrix_grid_relative_m_s01=u_wind_matrix_m_s01, v_matrix_grid_relative_m_s01=v_wind_matrix_m_s01, thermal_field_matrix_kelvins=wet_bulb_theta_matrix_kelvins, x_spacing_metres=x_spacing_metres, y_spacing_metres=y_spacing_metres) locating_var_matrix_m01_s01 = nfa.get_locating_variable( tfp_matrix_kelvins_m02=tfp_matrix_kelvins_m02, projected_velocity_matrix_m_s01=proj_velocity_matrix_m_s01) locating_var_file_name = '{0:s}/locating_variable.jpg'.format( output_dir_name) locating_var_title_string = ( r'Locating variable ($\times$ 10$^{-9}$ K m$^{-1}$ s$^{-1}$)') _plot_locating_variable( locating_var_matrix_m01_s01=locating_var_matrix_m01_s01, title_string=locating_var_title_string, annotation_string='(d)', output_file_name=locating_var_file_name) predicted_label_matrix = nfa.get_front_types( locating_var_matrix_m01_s01=locating_var_matrix_m01_s01, warm_front_percentile=front_percentile, cold_front_percentile=front_percentile) unclosed_fronts_file_name = '{0:s}/unclosed_fronts.jpg'.format( output_dir_name) _plot_front_types( predicted_label_matrix=predicted_label_matrix, title_string='Frontal regions before closing', annotation_string='(e)', output_file_name=unclosed_fronts_file_name) predicted_label_matrix = front_utils.close_frontal_image( ternary_image_matrix=predicted_label_matrix, num_iterations=num_closing_iters) closed_fronts_file_name = '{0:s}/closed_fronts.jpg'.format(output_dir_name) _plot_front_types( predicted_label_matrix=predicted_label_matrix, title_string='Frontal regions after closing', annotation_string='(f)', output_file_name=closed_fronts_file_name) concat_file_name = '{0:s}/nfa_procedure.jpg'.format(output_dir_name) print 'Concatenating figures to: "{0:s}"...'.format(concat_file_name) panel_file_names = [ unsmoothed_narr_file_name, smoothed_narr_file_name, tfp_file_name, locating_var_file_name, unclosed_fronts_file_name, closed_fronts_file_name ] imagemagick_utils.concatenate_images( input_file_names=panel_file_names, output_file_name=concat_file_name, num_panel_rows=3, num_panel_columns=2) imagemagick_utils.resize_image( input_file_name=concat_file_name, output_file_name=concat_file_name, output_size_pixels=CONCAT_SIZE_PIXELS)
def remove_polylines_in_masked_area(polyline_table, narr_mask_matrix, verbose=True): """Removes any polyline that touches only masked grid cells. M = number of rows in NARR grid N = number of columns in NARR grid :param polyline_table: See documentation for `fronts_io.write_polylines_to_file`. Each row is one front. :param narr_mask_matrix: M-by-N numpy array of integers (0 or 1). If narr_mask_matrix[i, j] = 0, grid cell [i, j] is masked. :param verbose: Boolean flag. If True, will print progress messages. :return: polyline_table: Same as input, except that some rows may have been removed. """ error_checking.assert_is_integer_numpy_array(narr_mask_matrix) error_checking.assert_is_geq_numpy_array(narr_mask_matrix, 0) error_checking.assert_is_leq_numpy_array(narr_mask_matrix, 1) error_checking.assert_is_boolean(verbose) num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME) expected_dimensions = numpy.array([num_grid_rows, num_grid_columns], dtype=int) error_checking.assert_is_numpy_array(narr_mask_matrix, exact_dimensions=expected_dimensions) num_fronts = len(polyline_table.index) indices_to_drop = [] for i in range(num_fronts): if numpy.mod(i, 25) == 0 and verbose: print( 'Have checked {0:d} of {1:d} polylines; have removed {2:d} of ' '{0:d} because they exist only in masked area...').format( i, num_fronts, len(indices_to_drop)) skip_this_front = _is_polyline_closed( latitudes_deg=polyline_table[LATITUDES_COLUMN].values[i], longitudes_deg=polyline_table[LONGITUDES_COLUMN].values[i]) if skip_this_front: indices_to_drop.append(i) continue this_binary_matrix = polyline_to_narr_grid( polyline_latitudes_deg=polyline_table[LATITUDES_COLUMN].values[i], polyline_longitudes_deg=polyline_table[LONGITUDES_COLUMN]. values[i], dilation_distance_metres=1.) if not numpy.any( numpy.logical_and(this_binary_matrix == 1, narr_mask_matrix == 1)): indices_to_drop.append(i) if len(indices_to_drop) == 0: return polyline_table indices_to_drop = numpy.array(indices_to_drop, dtype=int) return polyline_table.drop(polyline_table.index[indices_to_drop], axis=0, inplace=False)
def _run(valid_time_strings): """Plots predicted and observed fronts for one time step. This is effectively the main method. :param valid_time_strings: See documentation at top of file. """ num_times = 2 error_checking.assert_is_numpy_array( numpy.array(valid_time_strings), exact_dimensions=numpy.array([num_times])) valid_times_unix_sec = numpy.array( [time_conversion.string_to_unix_sec(s, INPUT_TIME_FORMAT) for s in valid_time_strings], dtype=int) num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME) print 'Reading data from: "{0:s}"...'.format(OBJECT_PREDICTION_FILE_NAME) predicted_region_table = object_eval.read_predictions_and_obs( OBJECT_PREDICTION_FILE_NAME)[0] figure_file_names = numpy.full((3, num_times), '', dtype=object) for i in range(num_times): this_prediction_file_name = ml_utils.find_gridded_prediction_file( directory_name=TOP_PREDICTION_DIR_NAME, first_target_time_unix_sec=valid_times_unix_sec[i], last_target_time_unix_sec=valid_times_unix_sec[i]) print 'Reading data from: "{0:s}"...'.format(this_prediction_file_name) this_prediction_dict = ml_utils.read_gridded_predictions( this_prediction_file_name) this_probability_matrix = this_prediction_dict[ ml_utils.PROBABILITY_MATRIX_KEY] this_probability_matrix[numpy.isnan(this_probability_matrix)] = 0. figure_file_names[0, i] = '{0:s}/gridded_predictions_{1:s}.jpg'.format( OUTPUT_DIR_NAME, valid_time_strings[i]) this_title_string = 'Gridded predictions at {0:s}'.format( time_conversion.unix_sec_to_string( valid_times_unix_sec[i], OUTPUT_TIME_FORMAT) ) _plot_predictions_one_time( output_file_name=figure_file_names[0, i], title_string=this_title_string, annotation_string=GRIDDED_PREDICTION_PANEL_LABELS[i], class_probability_matrix=this_probability_matrix, plot_warm_colour_bar=i == 0, plot_cold_colour_bar=i == num_times - 1) this_predicted_region_table = predicted_region_table.loc[ predicted_region_table[front_utils.TIME_COLUMN] == valid_times_unix_sec[i] ] this_predicted_label_matrix = object_eval.regions_to_images( predicted_region_table=this_predicted_region_table, num_grid_rows=num_grid_rows, num_grid_columns=num_grid_columns) figure_file_names[1, i] = '{0:s}/object_predictions_{1:s}.jpg'.format( OUTPUT_DIR_NAME, valid_time_strings[i]) this_title_string = 'Object-based predictions at {0:s}'.format( time_conversion.unix_sec_to_string( valid_times_unix_sec[i], OUTPUT_TIME_FORMAT) ) _plot_predictions_one_time( output_file_name=figure_file_names[1, i], title_string=this_title_string, annotation_string=OBJECT_PREDICTION_PANEL_LABELS[i], predicted_label_matrix=this_predicted_label_matrix) figure_file_names[2, i] = '{0:s}/observations_{1:s}.jpg'.format( OUTPUT_DIR_NAME, valid_time_strings[i]) this_title_string = 'Observations at {0:s}'.format( time_conversion.unix_sec_to_string( valid_times_unix_sec[i], OUTPUT_TIME_FORMAT) ) _plot_observations_one_time( valid_time_string=valid_time_strings[i], title_string=this_title_string, annotation_string=OBSERVATION_PANEL_LABELS[i], output_file_name=figure_file_names[2, i]) print '\n' print 'Concatenating figures to: "{0:s}"...'.format(CONCAT_FILE_NAME) imagemagick_utils.concatenate_images( input_file_names=numpy.ravel(figure_file_names).tolist(), output_file_name=CONCAT_FILE_NAME, num_panel_rows=NUM_PANEL_ROWS, num_panel_columns=NUM_PANEL_COLUMNS, output_size_pixels=FIGURE_SIZE_PIXELS)
def _run(): """Plots conversion of gridded probabilities into objects. This is effectively the main method. """ prediction_dict = ml_utils.read_gridded_predictions(PREDICTION_FILE_NAME) class_probability_matrix = prediction_dict[ml_utils.PROBABILITY_MATRIX_KEY] for this_id in front_utils.VALID_INTEGER_IDS: if this_id == front_utils.NO_FRONT_INTEGER_ID: class_probability_matrix[..., this_id][numpy.isnan( class_probability_matrix[..., this_id])] = 1. else: class_probability_matrix[..., this_id][numpy.isnan( class_probability_matrix[..., this_id])] = 0. predicted_label_matrix = object_eval.determinize_probabilities( class_probability_matrix=class_probability_matrix, binarization_threshold=BINARIZATION_THRESHOLD) _plot_predictions(predicted_label_matrix=predicted_label_matrix, title_string='All frontal regions', annotation_string='(b)', output_file_name=ALL_REGIONS_FILE_NAME) valid_time_unix_sec = time_conversion.string_to_unix_sec( VALID_TIME_STRING, TIME_FORMAT) valid_times_unix_sec = numpy.array([valid_time_unix_sec], dtype=int) predicted_region_table = object_eval.images_to_regions( predicted_label_matrix=predicted_label_matrix, image_times_unix_sec=valid_times_unix_sec) num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME) grid_spacing_metres = nwp_model_utils.get_xy_grid_spacing( model_name=nwp_model_utils.NARR_MODEL_NAME)[0] predicted_region_table = object_eval.discard_regions_with_small_area( predicted_region_table=predicted_region_table, x_grid_spacing_metres=grid_spacing_metres, y_grid_spacing_metres=grid_spacing_metres, min_area_metres2=MIN_REGION_AREA_METRES2) predicted_label_matrix = object_eval.regions_to_images( predicted_region_table=predicted_region_table, num_grid_rows=num_grid_rows, num_grid_columns=num_grid_columns) _plot_predictions(predicted_label_matrix=predicted_label_matrix, title_string='Large frontal regions', annotation_string='(c)', output_file_name=LARGE_REGIONS_FILE_NAME) predicted_region_table = object_eval.skeletonize_frontal_regions( predicted_region_table=predicted_region_table, num_grid_rows=num_grid_rows, num_grid_columns=num_grid_columns) predicted_label_matrix = object_eval.regions_to_images( predicted_region_table=predicted_region_table, num_grid_rows=num_grid_rows, num_grid_columns=num_grid_columns) _plot_predictions(predicted_label_matrix=predicted_label_matrix, title_string='All skeleton lines', annotation_string='(d)', output_file_name=ALL_SKELETONS_FILE_NAME) predicted_region_table = object_eval.find_main_skeletons( predicted_region_table=predicted_region_table, image_times_unix_sec=valid_times_unix_sec, num_grid_rows=num_grid_rows, num_grid_columns=num_grid_columns, x_grid_spacing_metres=grid_spacing_metres, y_grid_spacing_metres=grid_spacing_metres, min_endpoint_length_metres=MIN_ENDPOINT_LENGTH_METRES) predicted_label_matrix = object_eval.regions_to_images( predicted_region_table=predicted_region_table, num_grid_rows=num_grid_rows, num_grid_columns=num_grid_columns) _plot_predictions(predicted_label_matrix=predicted_label_matrix, title_string='Main skeleton lines', annotation_string='(e)', output_file_name=MAIN_SKELETONS_FILE_NAME) print 'Concatenating figures to: "{0:s}"...'.format(CONCAT_FILE_NAME) panel_file_names = [ PROBABILITY_FILE_NAME, ALL_REGIONS_FILE_NAME, LARGE_REGIONS_FILE_NAME, ALL_SKELETONS_FILE_NAME, MAIN_SKELETONS_FILE_NAME ] imagemagick_utils.concatenate_images(input_file_names=panel_file_names, output_file_name=CONCAT_FILE_NAME, num_panel_rows=2, num_panel_columns=3) imagemagick_utils.resize_image(input_file_name=CONCAT_FILE_NAME, output_file_name=CONCAT_FILE_NAME, output_size_pixels=CONCAT_SIZE_PIXELS)
def many_polylines_to_narr_grid(polyline_table, dilation_distance_metres): """For each time step, converts polylines to list of NARR grid points. W = number of grid cells intersected by any warm front at a given time C = number of grid cells intersected by any cold front at a given time :param polyline_table: See documentation for `fronts_io.write_polylines_to_file`. :param dilation_distance_metres: Dilation distance. :return: frontal_grid_point_table: pandas DataFrame with the following columns (and one row for each valid time). frontal_grid_point_table.unix_time_sec: Valid time. frontal_grid_point_table.warm_front_row_indices: length-W numpy array with row indices (integers) of grid cells intersected by a warm front. frontal_grid_point_table.warm_front_column_indices: Same but for columns. frontal_grid_point_table.cold_front_row_indices: length-C numpy array with row indices (integers) of grid cells intersected by a cold front. frontal_grid_point_table.cold_front_column_indices: Same but for columns. """ num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME) valid_times_unix_sec = numpy.unique(polyline_table[TIME_COLUMN].values) valid_time_strings = [ time_conversion.unix_sec_to_string(t, TIME_FORMAT_FOR_LOG_MESSAGES) for t in valid_times_unix_sec ] num_valid_times = len(valid_times_unix_sec) warm_front_row_indices_by_time = [[]] * num_valid_times warm_front_column_indices_by_time = [[]] * num_valid_times cold_front_row_indices_by_time = [[]] * num_valid_times cold_front_column_indices_by_time = [[]] * num_valid_times for i in range(num_valid_times): print 'Converting polylines to NARR grid for {0:s}...'.format( valid_time_strings[i]) these_polyline_indices = numpy.where( polyline_table[TIME_COLUMN].values == valid_times_unix_sec[i])[0] this_ternary_image_matrix = numpy.full( (num_grid_rows, num_grid_columns), NO_FRONT_INTEGER_ID, dtype=int) for j in these_polyline_indices: skip_this_front = _is_polyline_closed( latitudes_deg=polyline_table[LATITUDES_COLUMN].values[j], longitudes_deg=polyline_table[LONGITUDES_COLUMN].values[j]) if skip_this_front: this_num_points = len( polyline_table[LATITUDES_COLUMN].values[j]) print('SKIPPING front with {0:d} points (closed polyline).' ).format(this_num_points) continue this_binary_image_matrix = polyline_to_narr_grid( polyline_latitudes_deg=polyline_table[LATITUDES_COLUMN]. values[j], polyline_longitudes_deg=polyline_table[LONGITUDES_COLUMN]. values[j], dilation_distance_metres=dilation_distance_metres) this_binary_image_matrix = this_binary_image_matrix.astype(bool) if (polyline_table[FRONT_TYPE_COLUMN].values[j] == WARM_FRONT_STRING_ID): this_ternary_image_matrix[numpy.where( this_binary_image_matrix)] = WARM_FRONT_INTEGER_ID else: this_ternary_image_matrix[numpy.where( this_binary_image_matrix)] = COLD_FRONT_INTEGER_ID this_grid_point_dict = frontal_image_to_grid_points( this_ternary_image_matrix) warm_front_row_indices_by_time[i] = this_grid_point_dict[ WARM_FRONT_ROW_INDICES_COLUMN] warm_front_column_indices_by_time[i] = this_grid_point_dict[ WARM_FRONT_COLUMN_INDICES_COLUMN] cold_front_row_indices_by_time[i] = this_grid_point_dict[ COLD_FRONT_ROW_INDICES_COLUMN] cold_front_column_indices_by_time[i] = this_grid_point_dict[ COLD_FRONT_COLUMN_INDICES_COLUMN] frontal_grid_dict = { TIME_COLUMN: valid_times_unix_sec, WARM_FRONT_ROW_INDICES_COLUMN: warm_front_row_indices_by_time, WARM_FRONT_COLUMN_INDICES_COLUMN: warm_front_column_indices_by_time, COLD_FRONT_ROW_INDICES_COLUMN: cold_front_row_indices_by_time, COLD_FRONT_COLUMN_INDICES_COLUMN: cold_front_column_indices_by_time } return pandas.DataFrame.from_dict(frontal_grid_dict)
import matplotlib.pyplot as pyplot from mpl_toolkits.basemap import Basemap from gewittergefahr.gg_utils import grids from gewittergefahr.gg_utils import projections from gewittergefahr.gg_utils import nwp_model_utils from gewittergefahr.gg_utils import error_checking DEFAULT_FIG_WIDTH_INCHES = 15. DEFAULT_FIG_HEIGHT_INCHES = 15. DEFAULT_BOUNDARY_RESOLUTION_STRING = 'l' ELLIPSOID = 'sphere' EARTH_RADIUS_METRES = 6370997. NUM_ROWS_IN_NARR_GRID, NUM_COLUMNS_IN_NARR_GRID = ( nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME)) def get_xy_grid_point_matrices(first_row_in_narr_grid, last_row_in_narr_grid, first_column_in_narr_grid, last_column_in_narr_grid, basemap_object=None): """Returns coordinate matrices for a contiguous subset of the NARR grid. However, this subset need not be *strictly* a subset. In other words, the "subset" could be the full NARR grid. This method generates different x- and y-coordinates than `nwp_model_utils.get_xy_grid_point_matrices`, because (like `mpl_toolkits.basemap.Basemap`) this method assumes that false easting and
from gewittergefahr.gg_utils import nwp_model_utils from gewittergefahr.gg_utils import error_checking from generalexam.machine_learning import machine_learning_utils as ml_utils from generalexam.machine_learning import evaluation_utils TOLERANCE = 1e-6 TOLERANCE_FOR_GERRITY_SCORE = 1e-4 # The following constants are used to test _get_random_sample_points. NUM_POINTS_TO_SAMPLE = 10000 NUM_ROWS_FOR_FCN_INPUT = (ml_utils.LAST_NARR_ROW_FOR_FCN_INPUT - ml_utils.FIRST_NARR_ROW_FOR_FCN_INPUT + 1) NUM_COLUMNS_FOR_FCN_INPUT = (ml_utils.LAST_NARR_COLUMN_FOR_FCN_INPUT - ml_utils.FIRST_NARR_COLUMN_FOR_FCN_INPUT + 1) NARR_MASK_MATRIX = numpy.full(nwp_model_utils.get_grid_dimensions( nwp_model_utils.NARR_MODEL_NAME), 0, dtype=int) FIRST_UNMASKED_ROW = 20 LAST_UNMASKED_ROW = 200 FIRST_UNMASKED_COLUMN = 10 LAST_UNMASKED_COLUMN = 100 NARR_MASK_MATRIX[FIRST_UNMASKED_ROW:(LAST_UNMASKED_ROW + 1), FIRST_UNMASKED_COLUMN:(LAST_UNMASKED_COLUMN + 1)] = 1 # The following constants are used to test determinize_probabilities. CLASS_PROBABILITY_MATRIX = numpy.array([[0.5, 0.3, 0.2], [0.3, 0.6, 0.1], [0.7, 0.2, 0.1], [0.0, 0.4, 0.6], [0.3, 0.4, 0.3], [0.8, 0.2, 0.0],
'binary_pod': keras_metrics.binary_pod, 'binary_pofd': keras_metrics.binary_pofd, 'binary_peirce_score': keras_metrics.binary_peirce_score, 'binary_success_ratio': keras_metrics.binary_success_ratio, 'binary_focn': keras_metrics.binary_focn } LIST_OF_METRIC_FUNCTIONS = [ keras_metrics.accuracy, keras_metrics.binary_accuracy, keras_metrics.binary_csi, keras_metrics.binary_frequency_bias, keras_metrics.binary_pod, keras_metrics.binary_pofd, keras_metrics.binary_peirce_score, keras_metrics.binary_success_ratio, keras_metrics.binary_focn ] NUM_ROWS_IN_NARR, NUM_COLUMNS_IN_NARR = nwp_model_utils.get_grid_dimensions( model_name=nwp_model_utils.NARR_MODEL_NAME) def get_flattening_layer(model_object): """Finds flattening layer in CNN. This method assumes that there is only one flattening layer. If there are several, this method will return the first (shallowest). :param model_object: Instance of `keras.models.Model`. :return: layer_name: Name of flattening layer. :raises: TypeError: if flattening layer cannot be found. """ layer_names = [str(lyr.name) for lyr in model_object.layers]