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_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 _project_fronts_latlng_to_narr(front_line_table): """Projects fronts from lat-long to NARR (x-y) coordinates. P = number of points in a given front :param front_line_table: See doc for `fronts_io.write_polylines_to_file`. :return: front_line_table: Same as input, but with the following extra columns. front_line_table.x_coords_metres: length-P numpy array of x-coordinates. front_line_table.y_coords_metres: length-P numpy array of y-coordinates. """ num_fronts = len(front_line_table.index) projection_object = nwp_model_utils.init_model_projection( nwp_model_utils.NARR_MODEL_NAME) x_coords_by_front_metres = [numpy.array([])] * num_fronts y_coords_by_front_metres = [numpy.array([])] * num_fronts for i in range(num_fronts): if numpy.mod(i, 1000) == 0: print('Have projected {0:d} of {1:d} fronts to NARR coordinates...' ).format(i, num_fronts) (x_coords_by_front_metres[i], y_coords_by_front_metres[i]) = nwp_model_utils.project_latlng_to_xy( latitudes_deg=front_line_table[ front_utils.LATITUDES_COLUMN].values[i], longitudes_deg=front_line_table[ front_utils.LONGITUDES_COLUMN].values[i], projection_object=projection_object, model_name=nwp_model_utils.NARR_MODEL_NAME) print 'Projected all {0:d} fronts to NARR coordinates!'.format(num_fronts) return front_line_table.assign( **{ X_COORDS_COLUMN: x_coords_by_front_metres, Y_COORDS_COLUMN: y_coords_by_front_metres })
def _run(): """Plots input example. This is effectively the main method. :return: figure_file_name: Path to output file (where the figure was saved). """ valid_time_unix_sec = time_conversion.string_to_unix_sec( VALID_TIME_STRING, TIME_FORMAT) front_file_name = fronts_io.find_file_for_one_time( top_directory_name=TOP_FRONT_DIR_NAME, file_type=fronts_io.POLYLINE_FILE_TYPE, valid_time_unix_sec=valid_time_unix_sec) print 'Reading data from: "{0:s}"...'.format(front_file_name) front_line_table = fronts_io.read_polylines_from_file(front_file_name) num_narr_fields = len(NARR_FIELD_NAMES) narr_matrix_by_field = [numpy.array([])] * num_narr_fields for j in range(num_narr_fields): if NARR_FIELD_NAMES[j] in WIND_FIELD_NAMES: this_directory_name = '{0:s}/earth_relative_wind'.format( TOP_NARR_DIRECTORY_NAME) else: this_directory_name = TOP_NARR_DIRECTORY_NAME + '' this_file_name = processed_narr_io.find_file_for_one_time( top_directory_name=this_directory_name, field_name=NARR_FIELD_NAMES[j], pressure_level_mb=PRESSURE_LEVEL_MB, valid_time_unix_sec=valid_time_unix_sec) print 'Reading data from: "{0:s}"...'.format(this_file_name) narr_matrix_by_field[j] = processed_narr_io.read_fields_from_file( this_file_name)[0][0, ...] narr_matrix_by_field[j] = utils.fill_nans(narr_matrix_by_field[j]) if NARR_FIELD_NAMES[j] == processed_narr_io.WET_BULB_THETA_NAME: narr_matrix_by_field[j] = (narr_matrix_by_field[j] - ZERO_CELSIUS_IN_KELVINS) # (_, front_centroid_latitude_deg, front_centroid_longitude_deg # ) = _find_nearest_front( # front_line_table=front_line_table, # query_latitude_deg=APPROX_FRONT_LATITUDE_DEG, # query_longitude_deg=APPROX_FRONT_LONGITUDE_DEG) front_centroid_latitude_deg = APPROX_FRONT_LATITUDE_DEG + 0. front_centroid_longitude_deg = APPROX_FRONT_LONGITUDE_DEG + 0. projection_object = nwp_model_utils.init_model_projection( nwp_model_utils.NARR_MODEL_NAME) these_x_metres, these_y_metres = nwp_model_utils.project_latlng_to_xy( latitudes_deg=numpy.array([front_centroid_latitude_deg]), longitudes_deg=numpy.array([front_centroid_longitude_deg]), projection_object=projection_object, model_name=nwp_model_utils.NARR_MODEL_NAME) front_centroid_x_metres = these_x_metres[0] front_centroid_y_metres = these_y_metres[0] grid_spacing_metres, _ = nwp_model_utils.get_xy_grid_spacing( model_name=nwp_model_utils.NARR_MODEL_NAME) center_narr_row_index = int( numpy.round(front_centroid_y_metres / grid_spacing_metres)) center_narr_column_index = int( numpy.round(front_centroid_x_metres / grid_spacing_metres)) first_narr_row_index = center_narr_row_index - NUM_ROWS_IN_HALF_GRID last_narr_row_index = center_narr_row_index + NUM_ROWS_IN_HALF_GRID first_narr_column_index = (center_narr_column_index - NUM_COLUMNS_IN_HALF_GRID) last_narr_column_index = center_narr_column_index + NUM_COLUMNS_IN_HALF_GRID for j in range(num_narr_fields): narr_matrix_by_field[j] = narr_matrix_by_field[j][ first_narr_row_index:(last_narr_row_index + 1), first_narr_column_index:(last_narr_column_index + 1)] _, axes_object, basemap_object = nwp_plotting.init_basemap( model_name=nwp_model_utils.NARR_MODEL_NAME, first_row_in_full_grid=first_narr_row_index, last_row_in_full_grid=last_narr_row_index, first_column_in_full_grid=first_narr_column_index, last_column_in_full_grid=last_narr_column_index, resolution_string='i') plotting_utils.plot_coastlines(basemap_object=basemap_object, axes_object=axes_object, line_colour=BORDER_COLOUR) plotting_utils.plot_countries(basemap_object=basemap_object, axes_object=axes_object, line_colour=BORDER_COLOUR) plotting_utils.plot_states_and_provinces(basemap_object=basemap_object, axes_object=axes_object, line_colour=BORDER_COLOUR) plotting_utils.plot_parallels(basemap_object=basemap_object, axes_object=axes_object, bottom_left_lat_deg=-90., upper_right_lat_deg=90., parallel_spacing_deg=PARALLEL_SPACING_DEG) plotting_utils.plot_meridians(basemap_object=basemap_object, axes_object=axes_object, bottom_left_lng_deg=0., upper_right_lng_deg=360., meridian_spacing_deg=MERIDIAN_SPACING_DEG) for j in range(num_narr_fields): if NARR_FIELD_NAMES[j] in WIND_FIELD_NAMES: continue min_colour_value = numpy.percentile(narr_matrix_by_field[j], MIN_COLOUR_PERCENTILE) max_colour_value = numpy.percentile(narr_matrix_by_field[j], MAX_COLOUR_PERCENTILE) nwp_plotting.plot_subgrid( field_matrix=narr_matrix_by_field[j], model_name=nwp_model_utils.NARR_MODEL_NAME, axes_object=axes_object, basemap_object=basemap_object, colour_map=THERMAL_COLOUR_MAP_OBJECT, min_value_in_colour_map=min_colour_value, max_value_in_colour_map=max_colour_value, first_row_in_full_grid=first_narr_row_index, first_column_in_full_grid=first_narr_column_index) plotting_utils.add_linear_colour_bar( axes_object_or_list=axes_object, values_to_colour=narr_matrix_by_field[j], colour_map=THERMAL_COLOUR_MAP_OBJECT, colour_min=min_colour_value, colour_max=max_colour_value, orientation='horizontal', extend_min=True, extend_max=True) u_wind_index = NARR_FIELD_NAMES.index( processed_narr_io.U_WIND_EARTH_RELATIVE_NAME) v_wind_index = NARR_FIELD_NAMES.index( processed_narr_io.V_WIND_EARTH_RELATIVE_NAME) nwp_plotting.plot_wind_barbs_on_subgrid( u_wind_matrix_m_s01=narr_matrix_by_field[u_wind_index], v_wind_matrix_m_s01=narr_matrix_by_field[v_wind_index], model_name=nwp_model_utils.NARR_MODEL_NAME, axes_object=axes_object, basemap_object=basemap_object, first_row_in_full_grid=first_narr_row_index, first_column_in_full_grid=first_narr_column_index, plot_every_k_rows=PLOT_EVERY_KTH_WIND_BARB, plot_every_k_columns=PLOT_EVERY_KTH_WIND_BARB, barb_length=WIND_BARB_LENGTH, empty_barb_radius=EMPTY_WIND_BARB_RADIUS, colour_map=WIND_COLOUR_MAP_OBJECT, colour_minimum_kt=MIN_COLOUR_WIND_SPEED_KT, colour_maximum_kt=MAX_COLOUR_WIND_SPEED_KT) num_fronts = len(front_line_table.index) for i in range(num_fronts): this_front_type_string = front_line_table[ front_utils.FRONT_TYPE_COLUMN].values[i] if this_front_type_string == front_utils.WARM_FRONT_STRING_ID: this_colour = WARM_FRONT_COLOUR else: this_colour = COLD_FRONT_COLOUR # front_plotting.plot_polyline( # latitudes_deg=front_line_table[ # front_utils.LATITUDES_COLUMN].values[i], # longitudes_deg=front_line_table[ # front_utils.LONGITUDES_COLUMN].values[i], # basemap_object=basemap_object, axes_object=axes_object, # front_type=front_line_table[ # front_utils.FRONT_TYPE_COLUMN].values[i], # line_width=FRONT_LINE_WIDTH, line_colour=this_colour) print 'Saving figure to: "{0:s}"...'.format(OUTPUT_FILE_NAME) file_system_utils.mkdir_recursive_if_necessary(file_name=OUTPUT_FILE_NAME) pyplot.savefig(OUTPUT_FILE_NAME, dpi=OUTPUT_RESOLUTION_DPI) pyplot.close() imagemagick_utils.trim_whitespace(input_file_name=OUTPUT_FILE_NAME, output_file_name=OUTPUT_FILE_NAME)