def _plot_storm_outlines_one_time(storm_object_table, valid_time_unix_sec, warning_table, axes_object, basemap_object, storm_outline_colour, storm_outline_opacity, include_secondary_ids, output_dir_name, primary_id_to_track_colour=None, radar_matrix=None, radar_field_name=None, radar_latitudes_deg=None, radar_longitudes_deg=None, radar_colour_map_object=None): """Plots storm outlines (and may underlay radar data) at one time step. M = number of rows in radar grid N = number of columns in radar grid K = number of storm objects If `primary_id_to_track_colour is None`, all storm tracks will be the same colour. :param storm_object_table: See doc for `storm_plotting.plot_storm_outlines`. :param valid_time_unix_sec: Will plot storm outlines only at this time. Will plot tracks up to and including this time. :param warning_table: None or a pandas table with the following columns. warning_table.start_time_unix_sec: Start time. warning_table.end_time_unix_sec: End time. warning_table.polygon_object_latlng: Polygon (instance of `shapely.geometry.Polygon`) with lat-long coordinates of warning boundary. :param axes_object: See doc for `storm_plotting.plot_storm_outlines`. :param basemap_object: Same. :param storm_outline_colour: Same. :param storm_outline_opacity: Same. :param include_secondary_ids: Same. :param output_dir_name: See documentation at top of file. :param primary_id_to_track_colour: Dictionary created by `_assign_colours_to_storms`. If this is None, all storm tracks will be the same colour. :param radar_matrix: M-by-N numpy array of radar values. If `radar_matrix is None`, radar data will simply not be plotted. :param radar_field_name: [used only if `radar_matrix is not None`] See documentation at top of file. :param radar_latitudes_deg: [used only if `radar_matrix is not None`] length-M numpy array of grid-point latitudes (deg N). :param radar_longitudes_deg: [used only if `radar_matrix is not None`] length-N numpy array of grid-point longitudes (deg E). :param radar_colour_map_object: [used only if `radar_matrix is not None`] Colour map (instance of `matplotlib.pyplot.cm`). If None, will use default for the given field. """ # plot_storm_ids = radar_matrix is None or radar_colour_map_object is None plot_storm_ids = False min_plot_latitude_deg = basemap_object.llcrnrlat max_plot_latitude_deg = basemap_object.urcrnrlat min_plot_longitude_deg = basemap_object.llcrnrlon max_plot_longitude_deg = basemap_object.urcrnrlon 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, num_parallels=NUM_PARALLELS) plotting_utils.plot_meridians(basemap_object=basemap_object, axes_object=axes_object, num_meridians=NUM_MERIDIANS) if radar_matrix is not None: custom_colour_map = radar_colour_map_object is not None good_indices = numpy.where( numpy.logical_and(radar_latitudes_deg >= min_plot_latitude_deg, radar_latitudes_deg <= max_plot_latitude_deg))[0] radar_latitudes_deg = radar_latitudes_deg[good_indices] radar_matrix = radar_matrix[good_indices, :] good_indices = numpy.where( numpy.logical_and( radar_longitudes_deg >= min_plot_longitude_deg, radar_longitudes_deg <= max_plot_longitude_deg))[0] radar_longitudes_deg = radar_longitudes_deg[good_indices] radar_matrix = radar_matrix[:, good_indices] latitude_spacing_deg = radar_latitudes_deg[1] - radar_latitudes_deg[0] longitude_spacing_deg = (radar_longitudes_deg[1] - radar_longitudes_deg[0]) if radar_colour_map_object is None: colour_map_object, colour_norm_object = ( radar_plotting.get_default_colour_scheme(radar_field_name)) else: colour_map_object = radar_colour_map_object colour_norm_object = radar_plotting.get_default_colour_scheme( radar_field_name)[-1] this_ratio = radar_plotting._field_to_plotting_units( field_matrix=1., field_name=radar_field_name) colour_norm_object = pyplot.Normalize( colour_norm_object.vmin / this_ratio, colour_norm_object.vmax / this_ratio) radar_plotting.plot_latlng_grid( field_matrix=radar_matrix, field_name=radar_field_name, axes_object=axes_object, min_grid_point_latitude_deg=numpy.min(radar_latitudes_deg), min_grid_point_longitude_deg=numpy.min(radar_longitudes_deg), latitude_spacing_deg=latitude_spacing_deg, longitude_spacing_deg=longitude_spacing_deg, colour_map_object=colour_map_object, colour_norm_object=colour_norm_object) latitude_range_deg = max_plot_latitude_deg - min_plot_latitude_deg longitude_range_deg = max_plot_longitude_deg - min_plot_longitude_deg if latitude_range_deg > longitude_range_deg: orientation_string = 'vertical' else: orientation_string = 'horizontal' colour_bar_object = plotting_utils.plot_colour_bar( axes_object_or_matrix=axes_object, data_matrix=radar_matrix, colour_map_object=colour_map_object, colour_norm_object=colour_norm_object, orientation_string=orientation_string, padding=0.05, extend_min=radar_field_name in radar_plotting.SHEAR_VORT_DIV_NAMES, extend_max=True, fraction_of_axis_length=1.) radar_field_name_verbose = radar_utils.field_name_to_verbose( field_name=radar_field_name, include_units=True) radar_field_name_verbose = radar_field_name_verbose.replace( 'm ASL', 'kft ASL') colour_bar_object.set_label(radar_field_name_verbose) if custom_colour_map: tick_values = colour_bar_object.get_ticks() tick_label_strings = ['{0:.1f}'.format(v) for v in tick_values] colour_bar_object.set_ticks(tick_values) colour_bar_object.set_ticklabels(tick_label_strings) valid_time_rows = numpy.where(storm_object_table[ tracking_utils.VALID_TIME_COLUMN].values == valid_time_unix_sec)[0] this_colour = matplotlib.colors.to_rgba(storm_outline_colour, storm_outline_opacity) storm_plotting.plot_storm_outlines( storm_object_table=storm_object_table.iloc[valid_time_rows], axes_object=axes_object, basemap_object=basemap_object, line_colour=this_colour) if plot_storm_ids: storm_plotting.plot_storm_ids( storm_object_table=storm_object_table.iloc[valid_time_rows], axes_object=axes_object, basemap_object=basemap_object, plot_near_centroids=False, include_secondary_ids=include_secondary_ids, font_colour=storm_plotting.DEFAULT_FONT_COLOUR) if warning_table is not None: warning_indices = numpy.where( numpy.logical_and( warning_table[WARNING_START_TIME_KEY].values <= valid_time_unix_sec, warning_table[WARNING_END_TIME_KEY].values >= valid_time_unix_sec))[0] for k in warning_indices: this_vertex_dict = polygons.polygon_object_to_vertex_arrays( warning_table[WARNING_LATLNG_POLYGON_KEY].values[k]) these_latitudes_deg = this_vertex_dict[polygons.EXTERIOR_Y_COLUMN] these_longitudes_deg = this_vertex_dict[polygons.EXTERIOR_X_COLUMN] these_latitude_flags = numpy.logical_and( these_latitudes_deg >= min_plot_latitude_deg, these_latitudes_deg <= max_plot_latitude_deg) these_longitude_flags = numpy.logical_and( these_longitudes_deg >= min_plot_longitude_deg, these_longitudes_deg <= max_plot_longitude_deg) these_coord_flags = numpy.logical_and(these_latitude_flags, these_longitude_flags) if not numpy.any(these_coord_flags): continue these_x_metres, these_y_metres = basemap_object( these_longitudes_deg, these_latitudes_deg) axes_object.plot(these_x_metres, these_y_metres, color=this_colour, linestyle='dashed', linewidth=storm_plotting.DEFAULT_POLYGON_WIDTH) axes_object.text(numpy.mean(these_x_metres), numpy.mean(these_y_metres), 'W{0:d}'.format(k), fontsize=storm_plotting.DEFAULT_FONT_SIZE, fontweight='bold', color=this_colour, horizontalalignment='center', verticalalignment='center') these_sec_id_strings = ( warning_table[LINKED_SECONDARY_IDS_KEY].values[k]) if len(these_sec_id_strings) == 0: continue these_object_indices = numpy.array([], dtype=int) for this_sec_id_string in these_sec_id_strings: these_subindices = numpy.where( storm_object_table[tracking_utils.SECONDARY_ID_COLUMN]. values[valid_time_rows] == this_sec_id_string)[0] these_object_indices = numpy.concatenate( (these_object_indices, valid_time_rows[these_subindices])) for i in these_object_indices: this_vertex_dict = polygons.polygon_object_to_vertex_arrays( storm_object_table[ tracking_utils.LATLNG_POLYGON_COLUMN].values[i]) these_x_metres, these_y_metres = basemap_object( this_vertex_dict[polygons.EXTERIOR_X_COLUMN], this_vertex_dict[polygons.EXTERIOR_Y_COLUMN]) axes_object.text(numpy.mean(these_x_metres), numpy.mean(these_y_metres), 'W{0:d}'.format(k), fontsize=storm_plotting.DEFAULT_FONT_SIZE, fontweight='bold', color=this_colour, horizontalalignment='center', verticalalignment='center') if primary_id_to_track_colour is None: storm_plotting.plot_storm_tracks(storm_object_table=storm_object_table, axes_object=axes_object, basemap_object=basemap_object, colour_map_object=None, constant_colour=DEFAULT_TRACK_COLOUR) else: for this_primary_id_string in primary_id_to_track_colour: this_storm_object_table = storm_object_table.loc[ storm_object_table[tracking_utils.PRIMARY_ID_COLUMN] == this_primary_id_string] if len(this_storm_object_table.index) == 0: continue storm_plotting.plot_storm_tracks( storm_object_table=this_storm_object_table, axes_object=axes_object, basemap_object=basemap_object, colour_map_object=None, constant_colour=primary_id_to_track_colour[ this_primary_id_string]) nice_time_string = time_conversion.unix_sec_to_string( valid_time_unix_sec, NICE_TIME_FORMAT) abbrev_time_string = time_conversion.unix_sec_to_string( valid_time_unix_sec, FILE_NAME_TIME_FORMAT) pyplot.title('Storm objects at {0:s}'.format(nice_time_string)) output_file_name = '{0:s}/storm_outlines_{1:s}.jpg'.format( output_dir_name, abbrev_time_string) print('Saving figure to: "{0:s}"...'.format(output_file_name)) pyplot.savefig(output_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close()
def _plot_storm_outlines_one_time(storm_object_table, valid_time_unix_sec, axes_object, basemap_object, storm_colour, storm_opacity, include_secondary_ids, output_dir_name, radar_matrix=None, radar_field_name=None, radar_latitudes_deg=None, radar_longitudes_deg=None): """Plots storm outlines (and may underlay radar data) at one time step. M = number of rows in radar grid N = number of columns in radar grid K = number of storm objects :param storm_object_table: See doc for `storm_plotting.plot_storm_outlines`. :param valid_time_unix_sec: Will plot storm outlines only at this time. Will plot tracks up to and including this time. :param axes_object: Same. :param basemap_object: Same. :param storm_colour: Same. :param storm_opacity: Same. :param include_secondary_ids: Same. :param output_dir_name: See documentation at top of file. :param radar_matrix: M-by-N numpy array of radar values. If `radar_matrix is None`, radar data will simply not be plotted. :param radar_field_name: [used only if `radar_matrix is not None`] See documentation at top of file. :param radar_latitudes_deg: [used only if `radar_matrix is not None`] length-M numpy array of grid-point latitudes (deg N). :param radar_longitudes_deg: [used only if `radar_matrix is not None`] length-N numpy array of grid-point longitudes (deg E). """ min_plot_latitude_deg = basemap_object.llcrnrlat max_plot_latitude_deg = basemap_object.urcrnrlat min_plot_longitude_deg = basemap_object.llcrnrlon max_plot_longitude_deg = basemap_object.urcrnrlon 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, num_parallels=NUM_PARALLELS) plotting_utils.plot_meridians(basemap_object=basemap_object, axes_object=axes_object, num_meridians=NUM_MERIDIANS) if radar_matrix is not None: good_indices = numpy.where( numpy.logical_and(radar_latitudes_deg >= min_plot_latitude_deg, radar_latitudes_deg <= max_plot_latitude_deg))[0] radar_latitudes_deg = radar_latitudes_deg[good_indices] radar_matrix = radar_matrix[good_indices, :] good_indices = numpy.where( numpy.logical_and( radar_longitudes_deg >= min_plot_longitude_deg, radar_longitudes_deg <= max_plot_longitude_deg))[0] radar_longitudes_deg = radar_longitudes_deg[good_indices] radar_matrix = radar_matrix[:, good_indices] latitude_spacing_deg = radar_latitudes_deg[1] - radar_latitudes_deg[0] longitude_spacing_deg = (radar_longitudes_deg[1] - radar_longitudes_deg[0]) radar_plotting.plot_latlng_grid( field_matrix=radar_matrix, field_name=radar_field_name, axes_object=axes_object, min_grid_point_latitude_deg=numpy.min(radar_latitudes_deg), min_grid_point_longitude_deg=numpy.min(radar_longitudes_deg), latitude_spacing_deg=latitude_spacing_deg, longitude_spacing_deg=longitude_spacing_deg) colour_map_object, colour_norm_object = ( radar_plotting.get_default_colour_scheme(radar_field_name)) latitude_range_deg = max_plot_latitude_deg - min_plot_latitude_deg longitude_range_deg = max_plot_longitude_deg - min_plot_longitude_deg if latitude_range_deg > longitude_range_deg: orientation_string = 'vertical' else: orientation_string = 'horizontal' colour_bar_object = plotting_utils.plot_colour_bar( axes_object_or_matrix=axes_object, data_matrix=radar_matrix, colour_map_object=colour_map_object, colour_norm_object=colour_norm_object, orientation_string=orientation_string, extend_min=radar_field_name in radar_plotting.SHEAR_VORT_DIV_NAMES, extend_max=True, fraction_of_axis_length=0.9) colour_bar_object.set_label( radar_plotting.FIELD_NAME_TO_VERBOSE_DICT[radar_field_name]) valid_time_rows = numpy.where(storm_object_table[ tracking_utils.VALID_TIME_COLUMN].values == valid_time_unix_sec)[0] line_colour = matplotlib.colors.to_rgba(storm_colour, storm_opacity) storm_plotting.plot_storm_outlines( storm_object_table=storm_object_table.iloc[valid_time_rows], axes_object=axes_object, basemap_object=basemap_object, line_colour=line_colour) storm_plotting.plot_storm_ids( storm_object_table=storm_object_table.iloc[valid_time_rows], axes_object=axes_object, basemap_object=basemap_object, plot_near_centroids=False, include_secondary_ids=include_secondary_ids, font_colour=storm_plotting.DEFAULT_FONT_COLOUR) storm_plotting.plot_storm_tracks(storm_object_table=storm_object_table, axes_object=axes_object, basemap_object=basemap_object, colour_map_object=None, line_colour=TRACK_COLOUR) nice_time_string = time_conversion.unix_sec_to_string( valid_time_unix_sec, NICE_TIME_FORMAT) abbrev_time_string = time_conversion.unix_sec_to_string( valid_time_unix_sec, FILE_NAME_TIME_FORMAT) pyplot.title('Storm objects at {0:s}'.format(nice_time_string)) output_file_name = '{0:s}/storm_outlines_{1:s}.jpg'.format( output_dir_name, abbrev_time_string) print('Saving figure to: "{0:s}"...'.format(output_file_name)) pyplot.savefig(output_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close() imagemagick_utils.trim_whitespace(input_file_name=output_file_name, output_file_name=output_file_name)
def _plot_tornado_and_radar(top_myrorss_dir_name, radar_field_name, radar_height_m_asl, spc_date_string, tornado_table, tornado_row, output_file_name): """Plots one unlinked tornado with radar field. :param top_myrorss_dir_name: See documentation at top of file. :param radar_field_name: Same. :param radar_height_m_asl: Same. :param spc_date_string: SPC date for linkage file (format "yyyymmdd"). :param tornado_table: pandas DataFrame created by `linkage._read_input_tornado_reports`. :param tornado_row: Will plot only tornado in [j]th row of table, where j = `tornado_row`. :param output_file_name: Path to output file. Figure will be saved here. """ tornado_time_unix_sec = tornado_table[ linkage.EVENT_TIME_COLUMN].values[tornado_row] radar_time_unix_sec = number_rounding.round_to_nearest( tornado_time_unix_sec, RADAR_TIME_INTERVAL_SEC) radar_spc_date_string = time_conversion.time_to_spc_date_string( radar_time_unix_sec) radar_file_name = myrorss_and_mrms_io.find_raw_file( top_directory_name=top_myrorss_dir_name, spc_date_string=radar_spc_date_string, unix_time_sec=radar_time_unix_sec, data_source=radar_utils.MYRORSS_SOURCE_ID, field_name=radar_field_name, height_m_asl=radar_height_m_asl, raise_error_if_missing=spc_date_string == radar_spc_date_string) if not os.path.isfile(radar_file_name): first_radar_time_unix_sec = number_rounding.ceiling_to_nearest( time_conversion.get_start_of_spc_date(spc_date_string), RADAR_TIME_INTERVAL_SEC) last_radar_time_unix_sec = number_rounding.floor_to_nearest( time_conversion.get_end_of_spc_date(spc_date_string), RADAR_TIME_INTERVAL_SEC) radar_time_unix_sec = max( [radar_time_unix_sec, first_radar_time_unix_sec]) radar_time_unix_sec = min( [radar_time_unix_sec, last_radar_time_unix_sec]) radar_file_name = myrorss_and_mrms_io.find_raw_file( top_directory_name=top_myrorss_dir_name, spc_date_string=spc_date_string, unix_time_sec=radar_time_unix_sec, data_source=radar_utils.MYRORSS_SOURCE_ID, field_name=radar_field_name, height_m_asl=radar_height_m_asl, raise_error_if_missing=True) radar_metadata_dict = myrorss_and_mrms_io.read_metadata_from_raw_file( netcdf_file_name=radar_file_name, data_source=radar_utils.MYRORSS_SOURCE_ID) sparse_grid_table = (myrorss_and_mrms_io.read_data_from_sparse_grid_file( netcdf_file_name=radar_file_name, field_name_orig=radar_metadata_dict[ myrorss_and_mrms_io.FIELD_NAME_COLUMN_ORIG], data_source=radar_utils.MYRORSS_SOURCE_ID, sentinel_values=radar_metadata_dict[radar_utils.SENTINEL_VALUE_COLUMN]) ) radar_matrix, grid_point_latitudes_deg, grid_point_longitudes_deg = ( radar_s2f.sparse_to_full_grid(sparse_grid_table=sparse_grid_table, metadata_dict=radar_metadata_dict)) radar_matrix = numpy.flip(radar_matrix, axis=0) grid_point_latitudes_deg = grid_point_latitudes_deg[::-1] axes_object, basemap_object = ( plotting_utils.create_equidist_cylindrical_map( min_latitude_deg=numpy.min(grid_point_latitudes_deg), max_latitude_deg=numpy.max(grid_point_latitudes_deg), min_longitude_deg=numpy.min(grid_point_longitudes_deg), max_longitude_deg=numpy.max(grid_point_longitudes_deg), resolution_string='i')[1:]) 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, num_parallels=NUM_PARALLELS) plotting_utils.plot_meridians(basemap_object=basemap_object, axes_object=axes_object, num_meridians=NUM_MERIDIANS) radar_plotting.plot_latlng_grid( field_matrix=radar_matrix, field_name=radar_field_name, axes_object=axes_object, min_grid_point_latitude_deg=numpy.min(grid_point_latitudes_deg), min_grid_point_longitude_deg=numpy.min(grid_point_longitudes_deg), latitude_spacing_deg=numpy.diff(grid_point_latitudes_deg[:2])[0], longitude_spacing_deg=numpy.diff(grid_point_longitudes_deg[:2])[0]) tornado_latitude_deg = tornado_table[ linkage.EVENT_LATITUDE_COLUMN].values[tornado_row] tornado_longitude_deg = tornado_table[ linkage.EVENT_LONGITUDE_COLUMN].values[tornado_row] axes_object.plot(tornado_longitude_deg, tornado_latitude_deg, linestyle='None', marker=TORNADO_MARKER_TYPE, markersize=TORNADO_MARKER_SIZE, markeredgewidth=TORNADO_MARKER_EDGE_WIDTH, markerfacecolor=plotting_utils.colour_from_numpy_to_tuple( TORNADO_MARKER_COLOUR), markeredgecolor=plotting_utils.colour_from_numpy_to_tuple( TORNADO_MARKER_COLOUR)) tornado_time_string = time_conversion.unix_sec_to_string( tornado_time_unix_sec, TIME_FORMAT) title_string = ( 'Unlinked tornado at {0:s}, {1:.2f} deg N, {2:.2f} deg E').format( tornado_time_string, tornado_latitude_deg, tornado_longitude_deg) pyplot.title(title_string, fontsize=TITLE_FONT_SIZE) print('Saving figure to: "{0:s}"...'.format(output_file_name)) pyplot.savefig(output_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close() imagemagick_utils.trim_whitespace(input_file_name=output_file_name, output_file_name=output_file_name)
def _plot_one_example_one_time(storm_object_table, full_id_string, valid_time_unix_sec, tornado_table, top_myrorss_dir_name, radar_field_name, radar_height_m_asl, latitude_limits_deg, longitude_limits_deg): """Plots one example with surrounding context at one time. :param storm_object_table: pandas DataFrame, containing only storm objects at one time with the relevant primary ID. Columns are documented in `storm_tracking_io.write_file`. :param full_id_string: Full ID of storm of interest. :param valid_time_unix_sec: Valid time. :param tornado_table: pandas DataFrame created by `linkage._read_input_tornado_reports`. :param top_myrorss_dir_name: See documentation at top of file. :param radar_field_name: Same. :param radar_height_m_asl: Same. :param latitude_limits_deg: See doc for `_get_plotting_limits`. :param longitude_limits_deg: Same. """ min_plot_latitude_deg = latitude_limits_deg[0] max_plot_latitude_deg = latitude_limits_deg[1] min_plot_longitude_deg = longitude_limits_deg[0] max_plot_longitude_deg = longitude_limits_deg[1] radar_file_name = myrorss_and_mrms_io.find_raw_file( top_directory_name=top_myrorss_dir_name, spc_date_string=time_conversion.time_to_spc_date_string( valid_time_unix_sec), unix_time_sec=valid_time_unix_sec, data_source=radar_utils.MYRORSS_SOURCE_ID, field_name=radar_field_name, height_m_asl=radar_height_m_asl, raise_error_if_missing=True) print('Reading data from: "{0:s}"...'.format(radar_file_name)) radar_metadata_dict = myrorss_and_mrms_io.read_metadata_from_raw_file( netcdf_file_name=radar_file_name, data_source=radar_utils.MYRORSS_SOURCE_ID) sparse_grid_table = (myrorss_and_mrms_io.read_data_from_sparse_grid_file( netcdf_file_name=radar_file_name, field_name_orig=radar_metadata_dict[ myrorss_and_mrms_io.FIELD_NAME_COLUMN_ORIG], data_source=radar_utils.MYRORSS_SOURCE_ID, sentinel_values=radar_metadata_dict[radar_utils.SENTINEL_VALUE_COLUMN]) ) radar_matrix, grid_point_latitudes_deg, grid_point_longitudes_deg = ( radar_s2f.sparse_to_full_grid(sparse_grid_table=sparse_grid_table, metadata_dict=radar_metadata_dict)) radar_matrix = numpy.flip(radar_matrix, axis=0) grid_point_latitudes_deg = grid_point_latitudes_deg[::-1] axes_object, basemap_object = ( plotting_utils.create_equidist_cylindrical_map( min_latitude_deg=min_plot_latitude_deg, max_latitude_deg=max_plot_latitude_deg, min_longitude_deg=min_plot_longitude_deg, max_longitude_deg=max_plot_longitude_deg, resolution_string='i')[1:]) 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, num_parallels=NUM_PARALLELS) plotting_utils.plot_meridians(basemap_object=basemap_object, axes_object=axes_object, num_meridians=NUM_MERIDIANS) radar_plotting.plot_latlng_grid( field_matrix=radar_matrix, field_name=radar_field_name, axes_object=axes_object, min_grid_point_latitude_deg=numpy.min(grid_point_latitudes_deg), min_grid_point_longitude_deg=numpy.min(grid_point_longitudes_deg), latitude_spacing_deg=numpy.diff(grid_point_latitudes_deg[:2])[0], longitude_spacing_deg=numpy.diff(grid_point_longitudes_deg[:2])[0]) colour_map_object, colour_norm_object = ( radar_plotting.get_default_colour_scheme(radar_field_name)) plotting_utils.plot_colour_bar(axes_object_or_matrix=axes_object, data_matrix=radar_matrix, colour_map_object=colour_map_object, colour_norm_object=colour_norm_object, orientation_string='horizontal', extend_min=False, extend_max=True, fraction_of_axis_length=0.8) first_list, second_list = temporal_tracking.full_to_partial_ids( [full_id_string]) primary_id_string = first_list[0] secondary_id_string = second_list[0] # Plot outlines of unrelated storms (with different primary IDs). this_storm_object_table = storm_object_table.loc[storm_object_table[ tracking_utils.PRIMARY_ID_COLUMN] != primary_id_string] storm_plotting.plot_storm_outlines( storm_object_table=this_storm_object_table, axes_object=axes_object, basemap_object=basemap_object, line_width=2, line_colour='k', line_style='dashed') # Plot outlines of related storms (with the same primary ID). this_storm_object_table = storm_object_table.loc[ (storm_object_table[tracking_utils.PRIMARY_ID_COLUMN] == primary_id_string) & (storm_object_table[ tracking_utils.SECONDARY_ID_COLUMN] != secondary_id_string)] this_num_storm_objects = len(this_storm_object_table.index) if this_num_storm_objects > 0: storm_plotting.plot_storm_outlines( storm_object_table=this_storm_object_table, axes_object=axes_object, basemap_object=basemap_object, line_width=2, line_colour='k', line_style='solid') for j in range(len(this_storm_object_table)): axes_object.text( this_storm_object_table[ tracking_utils.CENTROID_LONGITUDE_COLUMN].values[j], this_storm_object_table[ tracking_utils.CENTROID_LATITUDE_COLUMN].values[j], 'P', fontsize=FONT_SIZE, color=FONT_COLOUR, fontweight='bold', horizontalalignment='center', verticalalignment='center') # Plot outline of storm of interest (same secondary ID). this_storm_object_table = storm_object_table.loc[storm_object_table[ tracking_utils.SECONDARY_ID_COLUMN] == secondary_id_string] storm_plotting.plot_storm_outlines( storm_object_table=this_storm_object_table, axes_object=axes_object, basemap_object=basemap_object, line_width=4, line_colour='k', line_style='solid') this_num_storm_objects = len(this_storm_object_table.index) plot_forecast = (this_num_storm_objects > 0 and FORECAST_PROBABILITY_COLUMN in list(this_storm_object_table)) if plot_forecast: this_polygon_object_latlng = this_storm_object_table[ tracking_utils.LATLNG_POLYGON_COLUMN].values[0] this_latitude_deg = numpy.min( numpy.array(this_polygon_object_latlng.exterior.xy[1])) this_longitude_deg = this_storm_object_table[ tracking_utils.CENTROID_LONGITUDE_COLUMN].values[0] label_string = 'Prob = {0:.3f}\nat {1:s}'.format( this_storm_object_table[FORECAST_PROBABILITY_COLUMN].values[0], time_conversion.unix_sec_to_string(valid_time_unix_sec, TORNADO_TIME_FORMAT)) bounding_box_dict = { 'facecolor': plotting_utils.colour_from_numpy_to_tuple( PROBABILITY_BACKGROUND_COLOUR), 'alpha': PROBABILITY_BACKGROUND_OPACITY, 'edgecolor': 'k', 'linewidth': 1 } axes_object.text(this_longitude_deg, this_latitude_deg, label_string, fontsize=FONT_SIZE, color=plotting_utils.colour_from_numpy_to_tuple( PROBABILITY_FONT_COLOUR), fontweight='bold', bbox=bounding_box_dict, horizontalalignment='center', verticalalignment='top', zorder=1e10) tornado_latitudes_deg = tornado_table[linkage.EVENT_LATITUDE_COLUMN].values tornado_longitudes_deg = tornado_table[ linkage.EVENT_LONGITUDE_COLUMN].values tornado_times_unix_sec = tornado_table[linkage.EVENT_TIME_COLUMN].values tornado_time_strings = [ time_conversion.unix_sec_to_string(t, TORNADO_TIME_FORMAT) for t in tornado_times_unix_sec ] axes_object.plot(tornado_longitudes_deg, tornado_latitudes_deg, linestyle='None', marker=TORNADO_MARKER_TYPE, markersize=TORNADO_MARKER_SIZE, markeredgewidth=TORNADO_MARKER_EDGE_WIDTH, markerfacecolor=plotting_utils.colour_from_numpy_to_tuple( TORNADO_MARKER_COLOUR), markeredgecolor=plotting_utils.colour_from_numpy_to_tuple( TORNADO_MARKER_COLOUR)) num_tornadoes = len(tornado_latitudes_deg) for j in range(num_tornadoes): axes_object.text(tornado_longitudes_deg[j] + 0.02, tornado_latitudes_deg[j] - 0.02, tornado_time_strings[j], fontsize=FONT_SIZE, color=FONT_COLOUR, fontweight='bold', horizontalalignment='left', verticalalignment='top')
def _plot_one_field(reflectivity_matrix_dbz, latitudes_deg, longitudes_deg, add_colour_bar, panel_letter, output_file_name): """Plots reflectivity field from one dataset. :param reflectivity_matrix_dbz: See doc for `_read_file`. :param latitudes_deg: Same. :param longitudes_deg: Same. :param add_colour_bar: Boolean flag. :param panel_letter: Panel letter (will be printed at top left of figure). :param output_file_name: Path to output file (figure will be saved here). """ (figure_object, axes_object, basemap_object) = plotting_utils.create_equidist_cylindrical_map( min_latitude_deg=numpy.min(latitudes_deg), max_latitude_deg=numpy.max(latitudes_deg), min_longitude_deg=numpy.min(longitudes_deg), max_longitude_deg=numpy.max(longitudes_deg), 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, num_parallels=NUM_PARALLELS) plotting_utils.plot_meridians(basemap_object=basemap_object, axes_object=axes_object, num_meridians=NUM_MERIDIANS) radar_plotting.plot_latlng_grid( field_matrix=reflectivity_matrix_dbz, field_name=RADAR_FIELD_NAME, axes_object=axes_object, min_grid_point_latitude_deg=numpy.min(latitudes_deg), min_grid_point_longitude_deg=numpy.min(longitudes_deg), latitude_spacing_deg=latitudes_deg[1] - latitudes_deg[0], longitude_spacing_deg=longitudes_deg[1] - longitudes_deg[0]) if add_colour_bar: colour_map_object, colour_norm_object = ( radar_plotting.get_default_colour_scheme(RADAR_FIELD_NAME)) plotting_utils.plot_colour_bar(axes_object_or_matrix=axes_object, data_matrix=reflectivity_matrix_dbz, colour_map_object=colour_map_object, colour_norm_object=colour_norm_object, orientation_string='horizontal', padding=0.05, extend_min=False, extend_max=True, fraction_of_axis_length=1.) plotting_utils.label_axes(axes_object=axes_object, label_string='({0:s})'.format(panel_letter), y_coord_normalized=1.03) 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)
def _plot_one_example_one_time( storm_object_table, full_id_string, valid_time_unix_sec, tornado_table, top_myrorss_dir_name, radar_field_name, radar_height_m_asl, latitude_limits_deg, longitude_limits_deg): """Plots one example with surrounding context at one time. :param storm_object_table: pandas DataFrame, containing only storm objects at one time with the relevant primary ID. Columns are documented in `storm_tracking_io.write_file`. :param full_id_string: Full ID of storm of interest. :param valid_time_unix_sec: Valid time. :param tornado_table: pandas DataFrame created by `linkage._read_input_tornado_reports`. :param top_myrorss_dir_name: See documentation at top of file. :param radar_field_name: Same. :param radar_height_m_asl: Same. :param latitude_limits_deg: See doc for `_get_plotting_limits`. :param longitude_limits_deg: Same. """ min_plot_latitude_deg = latitude_limits_deg[0] max_plot_latitude_deg = latitude_limits_deg[1] min_plot_longitude_deg = longitude_limits_deg[0] max_plot_longitude_deg = longitude_limits_deg[1] radar_file_name = myrorss_and_mrms_io.find_raw_file_inexact_time( top_directory_name=top_myrorss_dir_name, desired_time_unix_sec=valid_time_unix_sec, spc_date_string=time_conversion.time_to_spc_date_string( valid_time_unix_sec), data_source=radar_utils.MYRORSS_SOURCE_ID, field_name=radar_field_name, height_m_asl=radar_height_m_asl, max_time_offset_sec= myrorss_and_mrms_io.DEFAULT_MAX_TIME_OFFSET_FOR_NON_SHEAR_SEC, raise_error_if_missing=True) print('Reading data from: "{0:s}"...'.format(radar_file_name)) radar_metadata_dict = myrorss_and_mrms_io.read_metadata_from_raw_file( netcdf_file_name=radar_file_name, data_source=radar_utils.MYRORSS_SOURCE_ID) sparse_grid_table = ( myrorss_and_mrms_io.read_data_from_sparse_grid_file( netcdf_file_name=radar_file_name, field_name_orig=radar_metadata_dict[ myrorss_and_mrms_io.FIELD_NAME_COLUMN_ORIG], data_source=radar_utils.MYRORSS_SOURCE_ID, sentinel_values=radar_metadata_dict[ radar_utils.SENTINEL_VALUE_COLUMN] ) ) radar_matrix, grid_point_latitudes_deg, grid_point_longitudes_deg = ( radar_s2f.sparse_to_full_grid( sparse_grid_table=sparse_grid_table, metadata_dict=radar_metadata_dict) ) radar_matrix = numpy.flip(radar_matrix, axis=0) grid_point_latitudes_deg = grid_point_latitudes_deg[::-1] axes_object, basemap_object = ( plotting_utils.create_equidist_cylindrical_map( min_latitude_deg=min_plot_latitude_deg, max_latitude_deg=max_plot_latitude_deg, min_longitude_deg=min_plot_longitude_deg, max_longitude_deg=max_plot_longitude_deg, resolution_string='h' )[1:] ) plotting_utils.plot_coastlines( basemap_object=basemap_object, axes_object=axes_object, line_colour=plotting_utils.DEFAULT_COUNTRY_COLOUR) plotting_utils.plot_countries( basemap_object=basemap_object, axes_object=axes_object) plotting_utils.plot_states_and_provinces( basemap_object=basemap_object, axes_object=axes_object) plotting_utils.plot_parallels( basemap_object=basemap_object, axes_object=axes_object, num_parallels=NUM_PARALLELS, line_width=0) plotting_utils.plot_meridians( basemap_object=basemap_object, axes_object=axes_object, num_meridians=NUM_MERIDIANS, line_width=0) radar_plotting.plot_latlng_grid( field_matrix=radar_matrix, field_name=radar_field_name, axes_object=axes_object, min_grid_point_latitude_deg=numpy.min(grid_point_latitudes_deg), min_grid_point_longitude_deg=numpy.min(grid_point_longitudes_deg), latitude_spacing_deg=numpy.diff(grid_point_latitudes_deg[:2])[0], longitude_spacing_deg=numpy.diff(grid_point_longitudes_deg[:2])[0] ) colour_map_object, colour_norm_object = ( radar_plotting.get_default_colour_scheme(radar_field_name) ) plotting_utils.plot_colour_bar( axes_object_or_matrix=axes_object, data_matrix=radar_matrix, colour_map_object=colour_map_object, colour_norm_object=colour_norm_object, orientation_string='horizontal', padding=0.05, extend_min=False, extend_max=True, fraction_of_axis_length=0.8) first_list, second_list = temporal_tracking.full_to_partial_ids( [full_id_string] ) primary_id_string = first_list[0] secondary_id_string = second_list[0] # Plot outlines of unrelated storms (with different primary IDs). this_storm_object_table = storm_object_table.loc[ storm_object_table[tracking_utils.PRIMARY_ID_COLUMN] != primary_id_string ] storm_plotting.plot_storm_outlines( storm_object_table=this_storm_object_table, axes_object=axes_object, basemap_object=basemap_object, line_width=AUXILIARY_STORM_WIDTH, line_colour='k', line_style='dashed') # Plot outlines of related storms (with the same primary ID). this_storm_object_table = storm_object_table.loc[ (storm_object_table[tracking_utils.PRIMARY_ID_COLUMN] == primary_id_string) & (storm_object_table[tracking_utils.SECONDARY_ID_COLUMN] != secondary_id_string) ] this_num_storm_objects = len(this_storm_object_table.index) if this_num_storm_objects > 0: storm_plotting.plot_storm_outlines( storm_object_table=this_storm_object_table, axes_object=axes_object, basemap_object=basemap_object, line_width=AUXILIARY_STORM_WIDTH, line_colour='k', line_style='solid' ) for j in range(len(this_storm_object_table)): axes_object.text( this_storm_object_table[ tracking_utils.CENTROID_LONGITUDE_COLUMN ].values[j], this_storm_object_table[ tracking_utils.CENTROID_LATITUDE_COLUMN ].values[j], 'P', fontsize=MAIN_FONT_SIZE, color=FONT_COLOUR, fontweight='bold', horizontalalignment='center', verticalalignment='center' ) # Plot outline of storm of interest (same secondary ID). this_storm_object_table = storm_object_table.loc[ storm_object_table[tracking_utils.SECONDARY_ID_COLUMN] == secondary_id_string ] storm_plotting.plot_storm_outlines( storm_object_table=this_storm_object_table, axes_object=axes_object, basemap_object=basemap_object, line_width=MAIN_STORM_WIDTH, line_colour='k', line_style='solid') this_num_storm_objects = len(this_storm_object_table.index) plot_forecast = ( this_num_storm_objects > 0 and FORECAST_PROBABILITY_COLUMN in list(this_storm_object_table) ) if plot_forecast: label_string = 'Prob = {0:.3f}\nat {1:s}'.format( this_storm_object_table[FORECAST_PROBABILITY_COLUMN].values[0], time_conversion.unix_sec_to_string( valid_time_unix_sec, TORNADO_TIME_FORMAT) ) axes_object.set_title( label_string.replace('\n', ' '), fontsize=TITLE_FONT_SIZE ) tornado_id_strings = tornado_table[tornado_io.TORNADO_ID_COLUMN].values for this_tornado_id_string in numpy.unique(tornado_id_strings): these_rows = numpy.where( tornado_id_strings == this_tornado_id_string )[0] this_tornado_table = tornado_table.iloc[these_rows].sort_values( linkage.EVENT_TIME_COLUMN, axis=0, ascending=True, inplace=False ) _plot_one_tornado( tornado_table=this_tornado_table, axes_object=axes_object )
def _plot_echo_tops(echo_top_matrix_km_asl, latitudes_deg, longitudes_deg, plot_colour_bar, convective_flag_matrix=None): """Plots grid of 40-dBZ echo tops. M = number of rows in grid N = number of columns in grid :param echo_top_matrix_km_asl: M-by-N numpy array of echo tops (km above sea level). :param latitudes_deg: length-M numpy array of latitudes (deg N). :param longitudes_deg: length-N numpy array of longitudes (deg E). :param plot_colour_bar: Boolean flag. :param convective_flag_matrix: M-by-N numpy array of Boolean flags, indicating which grid cells are convective. If `convective_flag_matrix is None`, all grid cells will be plotted. If `convective_flag_matrix is not None`, only convective grid cells will be plotted. :return: figure_object: Figure handle (instance of `matplotlib.figure.Figure`). :return: axes_object: Axes handle (instance of `matplotlib.axes._subplots.AxesSubplot`). :return: basemap_object: Basemap handle (instance of `mpl_toolkits.basemap.Basemap`). """ figure_object, axes_object, basemap_object = ( plotting_utils.create_equidist_cylindrical_map( min_latitude_deg=numpy.min(latitudes_deg), max_latitude_deg=numpy.max(latitudes_deg), min_longitude_deg=numpy.min(longitudes_deg), max_longitude_deg=numpy.max(longitudes_deg), resolution_string='h' ) ) # plotting_utils.plot_coastlines( # basemap_object=basemap_object, axes_object=axes_object, # line_colour=plotting_utils.DEFAULT_COUNTRY_COLOUR # ) plotting_utils.plot_countries( basemap_object=basemap_object, axes_object=axes_object ) plotting_utils.plot_states_and_provinces( basemap_object=basemap_object, axes_object=axes_object ) plotting_utils.plot_parallels( basemap_object=basemap_object, axes_object=axes_object, num_parallels=NUM_PARALLELS, line_width=0 ) plotting_utils.plot_meridians( basemap_object=basemap_object, axes_object=axes_object, num_meridians=NUM_MERIDIANS, line_width=0 ) matrix_to_plot = echo_top_matrix_km_asl + 0. if convective_flag_matrix is not None: matrix_to_plot[convective_flag_matrix == False] = numpy.nan radar_plotting.plot_latlng_grid( field_matrix=matrix_to_plot, field_name=radar_utils.ECHO_TOP_40DBZ_NAME, axes_object=axes_object, min_grid_point_latitude_deg=numpy.min(latitudes_deg), min_grid_point_longitude_deg=numpy.min(longitudes_deg), latitude_spacing_deg=numpy.diff(latitudes_deg[:2])[0], longitude_spacing_deg=numpy.diff(longitudes_deg[:2])[0] ) if not plot_colour_bar: return figure_object, axes_object, basemap_object colour_map_object, colour_norm_object = ( radar_plotting.get_default_colour_scheme( radar_utils.ECHO_TOP_40DBZ_NAME) ) colour_bar_object = plotting_utils.plot_colour_bar( axes_object_or_matrix=axes_object, data_matrix=matrix_to_plot, colour_map_object=colour_map_object, colour_norm_object=colour_norm_object, orientation_string='horizontal', extend_min=False, extend_max=True, fraction_of_axis_length=1. ) colour_bar_object.set_label('40-dBZ echo top (kft ASL)') return figure_object, axes_object, basemap_object