def _run(top_tracking_dir_name, first_spc_date_string, last_spc_date_string, colour_map_name, min_plot_latitude_deg, max_plot_latitude_deg, min_plot_longitude_deg, max_plot_longitude_deg, output_file_name): """Plots storm tracks for a continuous time period. This is effectively the main method. :param top_tracking_dir_name: See documentation at top of file. :param first_spc_date_string: Same. :param last_spc_date_string: Same. :param colour_map_name: Same. :param min_plot_latitude_deg: Same. :param max_plot_latitude_deg: Same. :param min_plot_longitude_deg: Same. :param max_plot_longitude_deg: Same. :param output_file_name: Same. """ if colour_map_name in ['', 'None']: colour_map_object = 'random' else: colour_map_object = pyplot.cm.get_cmap(colour_map_name) if min_plot_latitude_deg <= SENTINEL_VALUE: min_plot_latitude_deg = None if max_plot_latitude_deg <= SENTINEL_VALUE: max_plot_latitude_deg = None if min_plot_longitude_deg <= SENTINEL_VALUE: min_plot_longitude_deg = None if max_plot_longitude_deg <= SENTINEL_VALUE: max_plot_longitude_deg = None file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name) spc_date_strings = time_conversion.get_spc_dates_in_range( first_spc_date_string=first_spc_date_string, last_spc_date_string=last_spc_date_string) list_of_storm_object_tables = [] for this_spc_date_string in spc_date_strings: these_file_names = tracking_io.find_files_one_spc_date( top_tracking_dir_name=top_tracking_dir_name, tracking_scale_metres2=echo_top_tracking. DUMMY_TRACKING_SCALE_METRES2, source_name=tracking_utils.SEGMOTION_NAME, spc_date_string=this_spc_date_string, raise_error_if_missing=False)[0] if len(these_file_names) == 0: continue this_storm_object_table = tracking_io.read_many_files( these_file_names)[REQUIRED_COLUMNS] list_of_storm_object_tables.append(this_storm_object_table) if this_spc_date_string != spc_date_strings[-1]: print(MINOR_SEPARATOR_STRING) if len(list_of_storm_object_tables) == 1: continue list_of_storm_object_tables[-1] = list_of_storm_object_tables[ -1].align(list_of_storm_object_tables[0], axis=1)[0] print(SEPARATOR_STRING) storm_object_table = pandas.concat(list_of_storm_object_tables, axis=0, ignore_index=True) # TODO(thunderhoser): HACK first_time_unix_sec = time_conversion.string_to_unix_sec( '2011-04-27-20', '%Y-%m-%d-%H') storm_object_table = storm_object_table.loc[storm_object_table[ tracking_utils.VALID_TIME_COLUMN] >= first_time_unix_sec] if min_plot_latitude_deg is None: min_plot_latitude_deg = numpy.min( storm_object_table[tracking_utils.CENTROID_LATITUDE_COLUMN].values ) - LATLNG_BUFFER_DEG if max_plot_latitude_deg is None: max_plot_latitude_deg = numpy.max( storm_object_table[tracking_utils.CENTROID_LATITUDE_COLUMN].values ) + LATLNG_BUFFER_DEG if min_plot_longitude_deg is None: min_plot_longitude_deg = numpy.min( storm_object_table[tracking_utils.CENTROID_LONGITUDE_COLUMN].values ) - LATLNG_BUFFER_DEG if max_plot_longitude_deg is None: max_plot_longitude_deg = numpy.max( storm_object_table[tracking_utils.CENTROID_LONGITUDE_COLUMN].values ) + LATLNG_BUFFER_DEG _, 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')) # 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, line_colour=numpy.full(3, 1.)) plotting_utils.plot_meridians(basemap_object=basemap_object, axes_object=axes_object, num_meridians=NUM_MERIDIANS, line_colour=numpy.full(3, 1.)) colour_bar_object = storm_plotting.plot_storm_tracks( storm_object_table=storm_object_table, axes_object=axes_object, basemap_object=basemap_object, colour_map_object=colour_map_object) valid_times_unix_sec = ( storm_object_table[tracking_utils.VALID_TIME_COLUMN].values) # TODO(thunderhoser): HACK tick_times_unix_sec = time_periods.range_and_interval_to_list( start_time_unix_sec=numpy.min(valid_times_unix_sec), end_time_unix_sec=numpy.max(valid_times_unix_sec), time_interval_sec=1800, include_endpoint=True) tick_time_strings = [ time_conversion.unix_sec_to_string(t, COLOUR_BAR_TIME_FORMAT) for t in tick_times_unix_sec ] colour_bar_object.set_ticks(tick_times_unix_sec) colour_bar_object.set_ticklabels(tick_time_strings) 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 _run(top_tracking_dir_name, first_spc_date_string, last_spc_date_string, colour_map_name, min_plot_latitude_deg, max_plot_latitude_deg, min_plot_longitude_deg, max_plot_longitude_deg, output_file_name): """Plots storm tracks for a continuous time period. This is effectively the main method. :param top_tracking_dir_name: See documentation at top of file. :param first_spc_date_string: Same. :param last_spc_date_string: Same. :param colour_map_name: Same. :param min_plot_latitude_deg: Same. :param max_plot_latitude_deg: Same. :param min_plot_longitude_deg: Same. :param max_plot_longitude_deg: Same. :param output_file_name: Same. """ if colour_map_name in ['', 'None']: colour_map_object = 'random' else: colour_map_object = pyplot.cm.get_cmap(colour_map_name) if min_plot_latitude_deg <= SENTINEL_VALUE: min_plot_latitude_deg = None if max_plot_latitude_deg <= SENTINEL_VALUE: max_plot_latitude_deg = None if min_plot_longitude_deg <= SENTINEL_VALUE: min_plot_longitude_deg = None if max_plot_longitude_deg <= SENTINEL_VALUE: max_plot_longitude_deg = None file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name) spc_date_strings = time_conversion.get_spc_dates_in_range( first_spc_date_string=first_spc_date_string, last_spc_date_string=last_spc_date_string) list_of_storm_object_tables = [] for this_spc_date_string in spc_date_strings: these_file_names = tracking_io.find_files_one_spc_date( top_tracking_dir_name=top_tracking_dir_name, tracking_scale_metres2=echo_top_tracking. DUMMY_TRACKING_SCALE_METRES2, source_name=tracking_utils.SEGMOTION_NAME, spc_date_string=this_spc_date_string, raise_error_if_missing=False)[0] if len(these_file_names) == 0: continue this_storm_object_table = tracking_io.read_many_files( these_file_names)[REQUIRED_COLUMNS] list_of_storm_object_tables.append(this_storm_object_table) if this_spc_date_string != spc_date_strings[-1]: print(MINOR_SEPARATOR_STRING) if len(list_of_storm_object_tables) == 1: continue list_of_storm_object_tables[-1] = list_of_storm_object_tables[ -1].align(list_of_storm_object_tables[0], axis=1)[0] print(SEPARATOR_STRING) storm_object_table = pandas.concat(list_of_storm_object_tables, axis=0, ignore_index=True) if min_plot_latitude_deg is None: min_plot_latitude_deg = numpy.min( storm_object_table[tracking_utils.CENTROID_LATITUDE_COLUMN].values ) - LATLNG_BUFFER_DEG if max_plot_latitude_deg is None: max_plot_latitude_deg = numpy.max( storm_object_table[tracking_utils.CENTROID_LATITUDE_COLUMN].values ) + LATLNG_BUFFER_DEG if min_plot_longitude_deg is None: min_plot_longitude_deg = numpy.min( storm_object_table[tracking_utils.CENTROID_LONGITUDE_COLUMN].values ) - LATLNG_BUFFER_DEG if max_plot_longitude_deg is None: max_plot_longitude_deg = numpy.max( storm_object_table[tracking_utils.CENTROID_LONGITUDE_COLUMN].values ) + LATLNG_BUFFER_DEG _, 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')) 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) storm_plotting.plot_storm_tracks(storm_object_table=storm_object_table, axes_object=axes_object, basemap_object=basemap_object, colour_map_object=colour_map_object) print('Saving figure to: "{0:s}"...'.format(output_file_name)) pyplot.savefig(output_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close()
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 _run(top_tracking_dir_name, first_spc_date_string, last_spc_date_string, storm_colour, storm_opacity, include_secondary_ids, min_plot_latitude_deg, max_plot_latitude_deg, min_plot_longitude_deg, max_plot_longitude_deg, top_myrorss_dir_name, radar_field_name, radar_height_m_asl, output_dir_name): """Plots storm outlines (along with IDs) at each time step. This is effectively the main method. :param top_tracking_dir_name: See documentation at top of file. :param first_spc_date_string: Same. :param last_spc_date_string: Same. :param storm_colour: Same. :param storm_opacity: Same. :param include_secondary_ids: Same. :param min_plot_latitude_deg: Same. :param max_plot_latitude_deg: Same. :param min_plot_longitude_deg: Same. :param max_plot_longitude_deg: Same. :param top_myrorss_dir_name: Same. :param radar_field_name: Same. :param radar_height_m_asl: Same. :param output_dir_name: Same. """ if top_myrorss_dir_name in ['', 'None']: top_myrorss_dir_name = None if radar_field_name != radar_utils.REFL_NAME: radar_height_m_asl = None file_system_utils.mkdir_recursive_if_necessary( directory_name=output_dir_name) spc_date_strings = time_conversion.get_spc_dates_in_range( first_spc_date_string=first_spc_date_string, last_spc_date_string=last_spc_date_string) tracking_file_names = [] for this_spc_date_string in spc_date_strings: tracking_file_names += (tracking_io.find_files_one_spc_date( top_tracking_dir_name=top_tracking_dir_name, tracking_scale_metres2=DUMMY_TRACKING_SCALE_METRES2, source_name=DUMMY_SOURCE_NAME, spc_date_string=this_spc_date_string, raise_error_if_missing=False)[0]) storm_object_table = tracking_io.read_many_files(tracking_file_names) print(SEPARATOR_STRING) latitude_limits_deg, longitude_limits_deg = _get_plotting_limits( min_plot_latitude_deg=min_plot_latitude_deg, max_plot_latitude_deg=max_plot_latitude_deg, min_plot_longitude_deg=min_plot_longitude_deg, max_plot_longitude_deg=max_plot_longitude_deg, storm_object_table=storm_object_table) 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] valid_times_unix_sec = numpy.unique( storm_object_table[tracking_utils.VALID_TIME_COLUMN].values) num_times = len(valid_times_unix_sec) for i in range(num_times): these_current_rows = numpy.where( storm_object_table[tracking_utils.VALID_TIME_COLUMN].values == valid_times_unix_sec[i])[0] these_current_subrows = _filter_storm_objects_latlng( storm_object_table=storm_object_table.iloc[these_current_rows], 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) if len(these_current_subrows) == 0: continue these_current_rows = these_current_rows[these_current_subrows] this_storm_object_table = _find_relevant_storm_objects( storm_object_table=storm_object_table, current_rows=these_current_rows) these_latlng_rows = _filter_storm_objects_latlng( storm_object_table=this_storm_object_table, 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) if top_myrorss_dir_name is None: this_radar_matrix = None these_radar_latitudes_deg = None these_radar_longitudes_deg = None else: this_myrorss_file_name = myrorss_and_mrms_io.find_raw_file( top_directory_name=top_myrorss_dir_name, unix_time_sec=valid_times_unix_sec[i], spc_date_string=time_conversion.time_to_spc_date_string( valid_times_unix_sec[i]), field_name=radar_field_name, data_source=radar_utils.MYRORSS_SOURCE_ID, height_m_asl=radar_height_m_asl, raise_error_if_missing=True) print( 'Reading data from: "{0:s}"...'.format(this_myrorss_file_name)) this_metadata_dict = ( myrorss_and_mrms_io.read_metadata_from_raw_file( netcdf_file_name=this_myrorss_file_name, data_source=radar_utils.MYRORSS_SOURCE_ID)) this_sparse_grid_table = ( myrorss_and_mrms_io.read_data_from_sparse_grid_file( netcdf_file_name=this_myrorss_file_name, field_name_orig=this_metadata_dict[ myrorss_and_mrms_io.FIELD_NAME_COLUMN_ORIG], data_source=radar_utils.MYRORSS_SOURCE_ID, sentinel_values=this_metadata_dict[ radar_utils.SENTINEL_VALUE_COLUMN])) (this_radar_matrix, these_radar_latitudes_deg, these_radar_longitudes_deg) = radar_s2f.sparse_to_full_grid( sparse_grid_table=this_sparse_grid_table, metadata_dict=this_metadata_dict) this_radar_matrix = numpy.flipud(this_radar_matrix) these_radar_latitudes_deg = these_radar_latitudes_deg[::-1] _, this_axes_object, this_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')) _plot_storm_outlines_one_time( storm_object_table=this_storm_object_table.iloc[these_latlng_rows], valid_time_unix_sec=valid_times_unix_sec[i], axes_object=this_axes_object, basemap_object=this_basemap_object, storm_colour=storm_colour, storm_opacity=storm_opacity, include_secondary_ids=include_secondary_ids, output_dir_name=output_dir_name, radar_matrix=this_radar_matrix, radar_field_name=radar_field_name, radar_latitudes_deg=these_radar_latitudes_deg, radar_longitudes_deg=these_radar_longitudes_deg)
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
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_attribution_one_track(storm_object_table, plot_legend, plot_x_ticks, legend_font_size=None, legend_location=None): """Plots tornado attribution for one storm track. :param storm_object_table: pandas DataFrame created by `_get_track1_for_simple_pred`, `_get_track2_for_simple_pred`, or `_get_track_for_simple_succ`. :param plot_legend: Boolean flag. :param plot_x_ticks: Boolean flag. :param legend_font_size: Font size in legend (used only if `plot_legend == True`). :param legend_location: Legend location (used only if `plot_legend == True`). :return: figure_object: See doc for `_plot_interp_two_times`. :return: axes_object: Same. """ centroid_x_coords = storm_object_table[ tracking_utils.CENTROID_X_COLUMN].values centroid_y_coords = storm_object_table[ tracking_utils.CENTROID_Y_COLUMN].values secondary_id_strings = storm_object_table[ tracking_utils.SECONDARY_ID_COLUMN].values storm_object_table = storm_object_table.assign(**{ tracking_utils.CENTROID_LONGITUDE_COLUMN: centroid_x_coords, tracking_utils.CENTROID_LATITUDE_COLUMN: centroid_y_coords }) figure_object, axes_object, basemap_object = ( plotting_utils.create_equidist_cylindrical_map( min_latitude_deg=numpy.min(centroid_y_coords), max_latitude_deg=numpy.max(centroid_y_coords), min_longitude_deg=numpy.min(centroid_x_coords), max_longitude_deg=numpy.max(centroid_x_coords) ) ) 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=TRACK_COLOUR, line_width=TRACK_WIDTH, start_marker_type=None, end_marker_type=None) tornadic_flags = storm_object_table[TORNADIC_FLAG_COLUMN].values main_tornadic_flags = storm_object_table[SPECIAL_FLAG_COLUMN].values legend_handles = [None] * 3 legend_strings = [None] * 3 for i in range(len(centroid_x_coords)): if main_tornadic_flags[i]: this_handle = axes_object.plot( centroid_x_coords[i], centroid_y_coords[i], linestyle='None', marker=TORNADIC_STORM_MARKER_TYPE, markersize=TORNADIC_STORM_MARKER_SIZE, markerfacecolor=TORNADIC_STORM_COLOUR, markeredgecolor=TORNADIC_STORM_COLOUR, markeredgewidth=TORNADIC_STORM_MARKER_EDGE_WIDTH )[0] legend_handles[0] = this_handle legend_strings[0] = 'Object initially linked\nto tornado' axes_object.text( centroid_x_coords[i], centroid_y_coords[i] - TEXT_OFFSET, secondary_id_strings[i], color=TORNADIC_STORM_COLOUR, fontsize=DEFAULT_FONT_SIZE, fontweight='bold', horizontalalignment='center', verticalalignment='top') else: if tornadic_flags[i]: this_edge_colour = TORNADIC_STORM_COLOUR this_face_colour = TORNADIC_STORM_COLOUR else: this_edge_colour = NON_TORNADIC_STORM_COLOUR this_face_colour = 'white' this_handle = axes_object.plot( centroid_x_coords[i], centroid_y_coords[i], linestyle='None', marker=DEFAULT_MARKER_TYPE, markersize=DEFAULT_MARKER_SIZE, markerfacecolor=this_face_colour, markeredgecolor=this_edge_colour, markeredgewidth=DEFAULT_MARKER_EDGE_WIDTH )[0] if tornadic_flags[i] and legend_handles[1] is None: legend_handles[1] = this_handle legend_strings[1] = 'Also linked to tornado' if not tornadic_flags[i] and legend_handles[2] is None: legend_handles[2] = this_handle legend_strings[2] = 'Not linked to tornado' axes_object.text( centroid_x_coords[i], centroid_y_coords[i] - TEXT_OFFSET, secondary_id_strings[i], color=this_edge_colour, fontsize=DEFAULT_FONT_SIZE, fontweight='bold', horizontalalignment='center', verticalalignment='top') if plot_x_ticks: storm_times_minutes = storm_object_table[ tracking_utils.VALID_TIME_COLUMN].values x_tick_values, unique_indices = numpy.unique( centroid_x_coords, return_index=True) x_tick_labels = [ '{0:d}'.format(int(numpy.round(storm_times_minutes[i]))) for i in unique_indices ] axes_object.set_xticks(x_tick_values) axes_object.set_xticklabels(x_tick_labels) axes_object.set_xlabel('Storm time (minutes)') else: axes_object.set_xticks([], []) axes_object.set_xlabel(r'Time $\longrightarrow$') axes_object.set_yticks([], []) y_min, y_max = axes_object.get_ylim() axes_object.set_ylim([y_min - 0.25, y_max]) if plot_legend: axes_object.legend( legend_handles, legend_strings, fontsize=legend_font_size, loc=legend_location) return figure_object, axes_object
def _plot_tropical_sites(output_file_name): """Plots tropical sites. :param output_file_name: Path to output file. Figure will be saved here. """ site_names = list(TROPICAL_SITE_TO_LATLNG.keys()) latitudes_deg_n = numpy.array([ TROPICAL_SITE_TO_LATLNG[n][0] for n in site_names ]) longitudes_deg_e = numpy.array([ TROPICAL_SITE_TO_LATLNG[n][1] for n in site_names ]) min_latitude_deg_n = numpy.floor(numpy.min(latitudes_deg_n) - 1.) max_latitude_deg_n = numpy.ceil(numpy.max(latitudes_deg_n) + 1.) min_longitude_deg_e = numpy.floor(numpy.min(longitudes_deg_e) - 1.) max_longitude_deg_e = numpy.ceil(numpy.max(longitudes_deg_e) + 1.) min_latitude_deg_n = max([min_latitude_deg_n, 10.]) max_latitude_deg_n = min([max_latitude_deg_n, 90.]) min_longitude_deg_e = max([min_longitude_deg_e, 0.]) max_longitude_deg_e = min([max_longitude_deg_e, 359.9999]) figure_object, axes_object, basemap_object = ( plotting_utils.create_equidist_cylindrical_map( min_latitude_deg=min_latitude_deg_n, max_latitude_deg=max_latitude_deg_n, min_longitude_deg=min_longitude_deg_e, max_longitude_deg=max_longitude_deg_e, resolution_string='l' ) ) plotting_utils.plot_coastlines( basemap_object=basemap_object, axes_object=axes_object, line_colour=BORDER_COLOUR, line_width=BORDER_WIDTH ) plotting_utils.plot_countries( basemap_object=basemap_object, axes_object=axes_object, line_colour=BORDER_COLOUR, line_width=BORDER_WIDTH ) plotting_utils.plot_parallels( basemap_object=basemap_object, axes_object=axes_object, num_parallels=NUM_PARALLELS, line_colour=GRID_LINE_COLOUR, line_width=GRID_LINE_WIDTH, font_size=FONT_SIZE ) plotting_utils.plot_meridians( basemap_object=basemap_object, axes_object=axes_object, num_meridians=NUM_MERIDIANS, line_colour=GRID_LINE_COLOUR, line_width=GRID_LINE_WIDTH, font_size=FONT_SIZE ) x_coords, y_coords = basemap_object(longitudes_deg_e, latitudes_deg_n) axes_object.plot( x_coords, y_coords, linestyle='None', marker=MARKER_TYPE, markersize=MARKER_SIZE, markeredgewidth=0, markerfacecolor=TROPICAL_COLOUR, markeredgecolor=TROPICAL_COLOUR ) for i in range(len(site_names)): horiz_align_string = TROPICAL_SITE_TO_ALIGNMENT[site_names[i]][0] vertical_align_string = TROPICAL_SITE_TO_ALIGNMENT[site_names[i]][1] if horiz_align_string == 'left': this_x_coord = x_coords[i] + 0.75 elif horiz_align_string == 'right': this_x_coord = x_coords[i] - 0.75 else: this_x_coord = x_coords[i] + 0. if vertical_align_string == 'bottom': this_y_coord = y_coords[i] + 0.75 elif vertical_align_string == 'top': this_y_coord = y_coords[i] - 0.75 else: this_y_coord = y_coords[i] + 0. axes_object.text( this_x_coord, this_y_coord, site_names[i], fontsize=FONT_SIZE, color=TROPICAL_COLOUR, horizontalalignment=horiz_align_string, verticalalignment=vertical_align_string ) 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_assorted2_sites(output_file_name): """Plots sites in the "Assorted2" set. :param output_file_name: Path to output file. Figure will be saved here. """ site_names = list(ASSORTED2_SITE_TO_LATLNG.keys()) latitudes_deg_n = numpy.array([ ASSORTED2_SITE_TO_LATLNG[n][0] for n in site_names ]) longitudes_deg_e = numpy.array([ ASSORTED2_SITE_TO_LATLNG[n][1] for n in site_names ]) figure_object, axes_object, basemap_object = ( plotting_utils.create_equidist_cylindrical_map( min_latitude_deg=10., max_latitude_deg=90., min_longitude_deg=0., max_longitude_deg=359.9999, resolution_string='l' ) ) plotting_utils.plot_coastlines( basemap_object=basemap_object, axes_object=axes_object, line_colour=BORDER_COLOUR, line_width=BORDER_WIDTH ) plotting_utils.plot_countries( basemap_object=basemap_object, axes_object=axes_object, line_colour=BORDER_COLOUR, line_width=BORDER_WIDTH ) plotting_utils.plot_parallels( basemap_object=basemap_object, axes_object=axes_object, num_parallels=NUM_PARALLELS, line_colour=GRID_LINE_COLOUR, line_width=GRID_LINE_WIDTH, font_size=FONT_SIZE ) plotting_utils.plot_meridians( basemap_object=basemap_object, axes_object=axes_object, num_meridians=NUM_MERIDIANS, line_colour=GRID_LINE_COLOUR, line_width=GRID_LINE_WIDTH, font_size=FONT_SIZE ) arctic_indices = numpy.where(latitudes_deg_n >= 66.5)[0] arctic_site_names = [site_names[i] for i in arctic_indices] arctic_x_coords, arctic_y_coords = basemap_object( longitudes_deg_e[arctic_indices], latitudes_deg_n[arctic_indices] ) axes_object.plot( arctic_x_coords, arctic_y_coords, linestyle='None', marker=MARKER_TYPE, markersize=MARKER_SIZE, markeredgewidth=0, markerfacecolor=ARCTIC_COLOUR, markeredgecolor=ARCTIC_COLOUR ) for i in range(len(arctic_site_names)): axes_object.text( arctic_x_coords[i], arctic_y_coords[i] - 2., arctic_site_names[i], fontsize=FONT_SIZE, color=ARCTIC_COLOUR, horizontalalignment='center', verticalalignment='top' ) mid_latitude_indices = numpy.where(numpy.logical_and( latitudes_deg_n >= 30., latitudes_deg_n < 66.5 ))[0] mid_latitude_site_names = [site_names[i] for i in mid_latitude_indices] mid_latitude_x_coords, mid_latitude_y_coords = basemap_object( longitudes_deg_e[mid_latitude_indices], latitudes_deg_n[mid_latitude_indices] ) axes_object.plot( mid_latitude_x_coords, mid_latitude_y_coords, linestyle='None', marker=MARKER_TYPE, markersize=MARKER_SIZE, markeredgewidth=0, markerfacecolor=MID_LATITUDE_COLOUR, markeredgecolor=MID_LATITUDE_COLOUR ) for i in range(len(mid_latitude_site_names)): axes_object.text( mid_latitude_x_coords[i], mid_latitude_y_coords[i] + 2., mid_latitude_site_names[i], fontsize=FONT_SIZE, color=MID_LATITUDE_COLOUR, horizontalalignment='center', verticalalignment='bottom' ) tropical_indices = numpy.where(latitudes_deg_n < 30.)[0] tropical_site_names = [site_names[i] for i in tropical_indices] tropical_x_coords, tropical_y_coords = basemap_object( longitudes_deg_e[tropical_indices], latitudes_deg_n[tropical_indices] ) axes_object.plot( tropical_x_coords, tropical_y_coords, linestyle='None', marker=MARKER_TYPE, markersize=MARKER_SIZE, markeredgewidth=0, markerfacecolor=TROPICAL_COLOUR, markeredgecolor=TROPICAL_COLOUR ) for i in range(len(tropical_site_names)): axes_object.text( tropical_x_coords[i], tropical_y_coords[i] + 2., tropical_site_names[i], fontsize=FONT_SIZE, color=TROPICAL_COLOUR, horizontalalignment='center', verticalalignment='bottom' ) 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 _run(storm_metafile_name, top_tracking_dir_name, lead_time_seconds, output_file_name): """Plots spatial distribution of examples (storm objects) in file. This is effectively the main method. :param storm_metafile_name: See documentation at top of file. :param top_tracking_dir_name: Same. :param lead_time_seconds: Same. :param output_file_name: Same. """ file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name) # Read storm metadata. print( 'Reading storm metadata from: "{0:s}"...'.format(storm_metafile_name)) orig_full_id_strings, orig_times_unix_sec = ( tracking_io.read_ids_and_times(storm_metafile_name)) orig_primary_id_strings = temporal_tracking.full_to_partial_ids( orig_full_id_strings)[0] # Find relevant tracking files. spc_date_strings = [ time_conversion.time_to_spc_date_string(t) for t in orig_times_unix_sec ] spc_date_strings += [ time_conversion.time_to_spc_date_string(t + lead_time_seconds) for t in orig_times_unix_sec ] spc_date_strings = list(set(spc_date_strings)) tracking_file_names = [] for this_spc_date_string in spc_date_strings: tracking_file_names += tracking_io.find_files_one_spc_date( top_tracking_dir_name=top_tracking_dir_name, tracking_scale_metres2=DUMMY_TRACKING_SCALE_METRES2, source_name=tracking_utils.SEGMOTION_NAME, spc_date_string=this_spc_date_string, raise_error_if_missing=False)[0] file_times_unix_sec = numpy.array( [tracking_io.file_name_to_time(f) for f in tracking_file_names], dtype=int) num_orig_storm_objects = len(orig_full_id_strings) num_files = len(file_times_unix_sec) keep_file_flags = numpy.full(num_files, 0, dtype=bool) for i in range(num_orig_storm_objects): these_flags = numpy.logical_and( file_times_unix_sec >= orig_times_unix_sec[i], file_times_unix_sec <= orig_times_unix_sec[i] + lead_time_seconds) keep_file_flags = numpy.logical_or(keep_file_flags, these_flags) del file_times_unix_sec keep_file_indices = numpy.where(keep_file_flags)[0] tracking_file_names = [tracking_file_names[k] for k in keep_file_indices] # Read relevant tracking files. num_files = len(tracking_file_names) storm_object_tables = [None] * num_files print(SEPARATOR_STRING) for i in range(num_files): print('Reading data from: "{0:s}"...'.format(tracking_file_names[i])) this_table = tracking_io.read_file(tracking_file_names[i]) storm_object_tables[i] = this_table.loc[this_table[ tracking_utils.PRIMARY_ID_COLUMN].isin( numpy.array(orig_primary_id_strings))] if i == 0: continue storm_object_tables[i] = storm_object_tables[i].align( storm_object_tables[0], axis=1)[0] storm_object_table = pandas.concat(storm_object_tables, axis=0, ignore_index=True) print(SEPARATOR_STRING) # Find relevant storm objects. orig_object_rows = tracking_utils.find_storm_objects( all_id_strings=storm_object_table[ tracking_utils.FULL_ID_COLUMN].values.tolist(), all_times_unix_sec=storm_object_table[ tracking_utils.VALID_TIME_COLUMN].values, id_strings_to_keep=orig_full_id_strings, times_to_keep_unix_sec=orig_times_unix_sec) good_object_rows = numpy.array([], dtype=int) for i in range(num_orig_storm_objects): # Non-merging successors only! first_rows = temporal_tracking.find_successors( storm_object_table=storm_object_table, target_row=orig_object_rows[i], num_seconds_forward=lead_time_seconds, max_num_sec_id_changes=1, change_type_string=temporal_tracking.SPLIT_STRING, return_all_on_path=True) second_rows = temporal_tracking.find_successors( storm_object_table=storm_object_table, target_row=orig_object_rows[i], num_seconds_forward=lead_time_seconds, max_num_sec_id_changes=0, change_type_string=temporal_tracking.MERGER_STRING, return_all_on_path=True) first_rows = first_rows.tolist() second_rows = second_rows.tolist() these_rows = set(first_rows) & set(second_rows) these_rows = numpy.array(list(these_rows), dtype=int) good_object_rows = numpy.concatenate((good_object_rows, these_rows)) good_object_rows = numpy.unique(good_object_rows) storm_object_table = storm_object_table.iloc[good_object_rows] times_of_day_sec = numpy.mod( storm_object_table[tracking_utils.VALID_TIME_COLUMN].values, NUM_SECONDS_IN_DAY) storm_object_table = storm_object_table.assign( **{tracking_utils.VALID_TIME_COLUMN: times_of_day_sec}) min_plot_latitude_deg = -LATLNG_BUFFER_DEG + numpy.min( storm_object_table[tracking_utils.CENTROID_LATITUDE_COLUMN].values) max_plot_latitude_deg = LATLNG_BUFFER_DEG + numpy.max( storm_object_table[tracking_utils.CENTROID_LATITUDE_COLUMN].values) min_plot_longitude_deg = -LATLNG_BUFFER_DEG + numpy.min( storm_object_table[tracking_utils.CENTROID_LONGITUDE_COLUMN].values) max_plot_longitude_deg = LATLNG_BUFFER_DEG + numpy.max( storm_object_table[tracking_utils.CENTROID_LONGITUDE_COLUMN].values) _, 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')) plotting_utils.plot_coastlines(basemap_object=basemap_object, axes_object=axes_object, line_colour=BORDER_COLOUR, line_width=BORDER_WIDTH * 2) plotting_utils.plot_countries(basemap_object=basemap_object, axes_object=axes_object, line_colour=BORDER_COLOUR, line_width=BORDER_WIDTH) plotting_utils.plot_states_and_provinces(basemap_object=basemap_object, axes_object=axes_object, line_colour=BORDER_COLOUR, line_width=BORDER_WIDTH) plotting_utils.plot_parallels(basemap_object=basemap_object, axes_object=axes_object, num_parallels=NUM_PARALLELS, line_width=BORDER_WIDTH) plotting_utils.plot_meridians(basemap_object=basemap_object, axes_object=axes_object, num_meridians=NUM_MERIDIANS, line_width=BORDER_WIDTH) # colour_bar_object = storm_plotting.plot_storm_tracks( # storm_object_table=storm_object_table, axes_object=axes_object, # basemap_object=basemap_object, colour_map_object=COLOUR_MAP_OBJECT, # colour_min_unix_sec=0, colour_max_unix_sec=NUM_SECONDS_IN_DAY - 1, # line_width=TRACK_LINE_WIDTH, # start_marker_type=None, end_marker_type=None # ) colour_bar_object = storm_plotting.plot_storm_centroids( storm_object_table=storm_object_table, axes_object=axes_object, basemap_object=basemap_object, colour_map_object=COLOUR_MAP_OBJECT, colour_min_unix_sec=0, colour_max_unix_sec=NUM_SECONDS_IN_DAY - 1) tick_times_unix_sec = numpy.linspace(0, NUM_SECONDS_IN_DAY, num=NUM_HOURS_IN_DAY + 1, dtype=int) tick_times_unix_sec = tick_times_unix_sec[:-1] tick_times_unix_sec = tick_times_unix_sec[::2] tick_time_strings = [ time_conversion.unix_sec_to_string(t, COLOUR_BAR_TIME_FORMAT) for t in tick_times_unix_sec ] colour_bar_object.set_ticks(tick_times_unix_sec) colour_bar_object.set_ticklabels(tick_time_strings) 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_schema(storm_object_table, output_file_name): """Plots schema for storm-velocity estimation. :param storm_object_table: pandas DataFrame created by `_create_tracking_data`. :param output_file_name: Path to output file (figure will be saved here). """ centroid_x_coords = storm_object_table[ tracking_utils.CENTROID_X_COLUMN].values centroid_y_coords = storm_object_table[ tracking_utils.CENTROID_Y_COLUMN].values secondary_id_strings = storm_object_table[ tracking_utils.SECONDARY_ID_COLUMN].values storm_object_table = storm_object_table.assign( **{ tracking_utils.CENTROID_LONGITUDE_COLUMN: centroid_x_coords, tracking_utils.CENTROID_LATITUDE_COLUMN: centroid_y_coords }) figure_object, axes_object, basemap_object = ( plotting_utils.create_equidist_cylindrical_map( min_latitude_deg=numpy.min(centroid_y_coords), max_latitude_deg=numpy.max(centroid_y_coords), min_longitude_deg=numpy.min(centroid_x_coords), max_longitude_deg=numpy.max(centroid_x_coords))) 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=TRACK_COLOUR, line_width=TRACK_WIDTH, start_marker_type=None, end_marker_type=None) num_storm_objects = len(storm_object_table.index) predecessor_rows = temporal_tracking.find_predecessors( storm_object_table=storm_object_table, target_row=num_storm_objects - 1, num_seconds_back=100, return_all_on_path=False) legend_handles = [None] * 3 legend_strings = [None] * 3 this_handle = axes_object.plot(centroid_x_coords[[0, 0]], centroid_y_coords[[0, 0]], color=TRACK_COLOUR, linestyle='solid', linewidth=TRACK_WIDTH)[0] legend_handles[-1] = this_handle legend_strings[-1] = 'Storm track' for i in range(num_storm_objects): if i in predecessor_rows or i == num_storm_objects - 1: this_colour = SPECIAL_STORM_COLOUR else: this_colour = DEFAULT_STORM_COLOUR this_handle = axes_object.plot(centroid_x_coords[i], centroid_y_coords[i], linestyle='None', marker=MARKER_TYPE, markersize=MARKER_SIZE, markerfacecolor=this_colour, markeredgecolor=this_colour, markeredgewidth=MARKER_EDGE_WIDTH)[0] if i in predecessor_rows or i == num_storm_objects - 1: legend_handles[0] = this_handle legend_strings[0] = 'Object used in\nvelocity estimate' else: legend_handles[1] = this_handle legend_strings[1] = 'Object not used' axes_object.text(centroid_x_coords[i], centroid_y_coords[i] - TEXT_OFFSET, secondary_id_strings[i], color=this_colour, fontsize=FONT_SIZE, fontweight='bold', horizontalalignment='center', verticalalignment='top') axes_object.set_yticks([], []) storm_times_minutes = storm_object_table[ tracking_utils.VALID_TIME_COLUMN].values x_tick_values, unique_indices = numpy.unique(centroid_x_coords, return_index=True) x_tick_labels = [ '{0:d}'.format(storm_times_minutes[i]) for i in unique_indices ] axes_object.set_xticks(x_tick_values) axes_object.set_xticklabels(x_tick_labels) axes_object.set_xlabel('Time (minutes)') axes_object.legend(legend_handles, legend_strings, fontsize=FONT_SIZE, loc=(0.02, 0.55)) 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 _run(top_orig_tracking_dir_name, top_new_tracking_dir_name, first_spc_date_string, last_spc_date_string, output_file_name): """Plots storms that were removed by remove_storms_outside_conus.py. This is effectively the main method. :param top_orig_tracking_dir_name: See documentation at top of file. :param top_new_tracking_dir_name: Same. :param first_spc_date_string: Same. :param last_spc_date_string: Same. :param output_file_name: Same. """ file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name) spc_date_strings = time_conversion.get_spc_dates_in_range( first_spc_date_string=first_spc_date_string, last_spc_date_string=last_spc_date_string) orig_tracking_file_names = [] for d in spc_date_strings: orig_tracking_file_names += tracking_io.find_files_one_spc_date( top_tracking_dir_name=top_orig_tracking_dir_name, tracking_scale_metres2=DUMMY_TRACKING_SCALE_METRES2, source_name=tracking_utils.SEGMOTION_NAME, spc_date_string=d, raise_error_if_missing=False)[0] valid_times_unix_sec = numpy.array( [tracking_io.file_name_to_time(f) for f in orig_tracking_file_names], dtype=int) new_tracking_file_names = [ tracking_io.find_file( top_tracking_dir_name=top_new_tracking_dir_name, tracking_scale_metres2=DUMMY_TRACKING_SCALE_METRES2, source_name=tracking_utils.SEGMOTION_NAME, valid_time_unix_sec=t, spc_date_string=time_conversion.time_to_spc_date_string(t), raise_error_if_missing=True) for t in valid_times_unix_sec ] orig_storm_object_table = tracking_io.read_many_files( orig_tracking_file_names) print(SEPARATOR_STRING) new_storm_object_table = tracking_io.read_many_files( new_tracking_file_names) print(SEPARATOR_STRING) orig_storm_id_strings = ( orig_storm_object_table[tracking_utils.FULL_ID_COLUMN].values.tolist()) orig_storm_times_unix_sec = ( orig_storm_object_table[tracking_utils.VALID_TIME_COLUMN].values) new_storm_id_strings = ( new_storm_object_table[tracking_utils.FULL_ID_COLUMN].values.tolist()) new_storm_times_unix_sec = ( new_storm_object_table[tracking_utils.VALID_TIME_COLUMN].values) num_orig_storm_objects = len(orig_storm_object_table.index) orig_kept_flags = numpy.full(num_orig_storm_objects, 0, dtype=bool) these_indices = tracking_utils.find_storm_objects( all_id_strings=orig_storm_id_strings, all_times_unix_sec=orig_storm_times_unix_sec, id_strings_to_keep=new_storm_id_strings, times_to_keep_unix_sec=new_storm_times_unix_sec, allow_missing=False) orig_kept_flags[these_indices] = True orig_removed_indices = numpy.where(numpy.invert(orig_kept_flags))[0] print('{0:d} of {1:d} storm objects were outside CONUS.'.format( len(orig_removed_indices), num_orig_storm_objects)) removed_storm_object_table = orig_storm_object_table.iloc[ orig_removed_indices] removed_latitudes_deg = removed_storm_object_table[ tracking_utils.CENTROID_LATITUDE_COLUMN].values removed_longitudes_deg = removed_storm_object_table[ tracking_utils.CENTROID_LONGITUDE_COLUMN].values figure_object, axes_object, basemap_object = ( plotting_utils.create_equidist_cylindrical_map( min_latitude_deg=numpy.min(removed_latitudes_deg) - 1., max_latitude_deg=numpy.max(removed_latitudes_deg) + 1., min_longitude_deg=numpy.min(removed_longitudes_deg) - 1., max_longitude_deg=numpy.max(removed_longitudes_deg) + 1., 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) conus_latitudes_deg, conus_longitudes_deg = ( conus_boundary.read_from_netcdf()) conus_latitudes_deg, conus_longitudes_deg = conus_boundary.erode_boundary( latitudes_deg=conus_latitudes_deg, longitudes_deg=conus_longitudes_deg, erosion_distance_metres=EROSION_DISTANCE_METRES) axes_object.plot(conus_longitudes_deg, conus_latitudes_deg, color=LINE_COLOUR, linestyle='solid', linewidth=LINE_WIDTH) axes_object.plot(removed_longitudes_deg, removed_latitudes_deg, linestyle='None', marker=MARKER_TYPE, markersize=MARKER_SIZE, markeredgewidth=0, markerfacecolor=MARKER_COLOUR, markeredgecolor=MARKER_COLOUR) 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 _run(tropical_example_dir_name, non_tropical_example_dir_name, output_file_name): """Plots all sites wtih data. This is effectively the main method. :param tropical_example_dir_name: See documentation at top of file. :param non_tropical_example_dir_name: Same. :param output_file_name: Same. """ first_time_unix_sec = ( time_conversion.first_and_last_times_in_year(FIRST_YEAR)[0]) last_time_unix_sec = ( time_conversion.first_and_last_times_in_year(LAST_YEAR)[-1]) tropical_file_names = example_io.find_many_files( directory_name=tropical_example_dir_name, first_time_unix_sec=first_time_unix_sec, last_time_unix_sec=last_time_unix_sec, raise_error_if_all_missing=True, raise_error_if_any_missing=False) non_tropical_file_names = example_io.find_many_files( directory_name=non_tropical_example_dir_name, first_time_unix_sec=first_time_unix_sec, last_time_unix_sec=last_time_unix_sec, raise_error_if_all_missing=True, raise_error_if_any_missing=False) latitudes_deg_n = numpy.array([]) longitudes_deg_e = numpy.array([]) for this_file_name in tropical_file_names: print('Reading data from: "{0:s}"...'.format(this_file_name)) this_example_dict = example_io.read_file(this_file_name) these_latitudes_deg_n = example_utils.get_field_from_dict( example_dict=this_example_dict, field_name=example_utils.LATITUDE_NAME) these_longitudes_deg_e = example_utils.get_field_from_dict( example_dict=this_example_dict, field_name=example_utils.LONGITUDE_NAME) latitudes_deg_n = numpy.concatenate( (latitudes_deg_n, these_latitudes_deg_n)) longitudes_deg_e = numpy.concatenate( (longitudes_deg_e, these_longitudes_deg_e)) for this_file_name in non_tropical_file_names: print('Reading data from: "{0:s}"...'.format(this_file_name)) this_example_dict = example_io.read_file(this_file_name) these_latitudes_deg_n = example_utils.get_field_from_dict( example_dict=this_example_dict, field_name=example_utils.LATITUDE_NAME) these_longitudes_deg_e = example_utils.get_field_from_dict( example_dict=this_example_dict, field_name=example_utils.LONGITUDE_NAME) latitudes_deg_n = numpy.concatenate( (latitudes_deg_n, these_latitudes_deg_n)) longitudes_deg_e = numpy.concatenate( (longitudes_deg_e, these_longitudes_deg_e)) coord_matrix = numpy.transpose( numpy.vstack((latitudes_deg_n, longitudes_deg_e))) coord_matrix = number_rounding.round_to_nearest(coord_matrix, LATLNG_TOLERANCE_DEG) coord_matrix = numpy.unique(coord_matrix, axis=0) latitudes_deg_n = coord_matrix[:, 0] longitudes_deg_e = coord_matrix[:, 1] figure_object, axes_object, basemap_object = ( plotting_utils.create_equidist_cylindrical_map( min_latitude_deg=MIN_PLOT_LATITUDE_DEG_N, max_latitude_deg=MAX_PLOT_LATITUDE_DEG_N, min_longitude_deg=MIN_PLOT_LONGITUDE_DEG_E, max_longitude_deg=MAX_PLOT_LONGITUDE_DEG_E, resolution_string='l')) plotting_utils.plot_coastlines(basemap_object=basemap_object, axes_object=axes_object, line_colour=BORDER_COLOUR, line_width=BORDER_WIDTH) plotting_utils.plot_countries(basemap_object=basemap_object, axes_object=axes_object, line_colour=BORDER_COLOUR, line_width=BORDER_WIDTH) plotting_utils.plot_parallels(basemap_object=basemap_object, axes_object=axes_object, num_parallels=NUM_PARALLELS, line_colour=GRID_LINE_COLOUR, line_width=GRID_LINE_WIDTH, font_size=FONT_SIZE) plotting_utils.plot_meridians(basemap_object=basemap_object, axes_object=axes_object, num_meridians=NUM_MERIDIANS, line_colour=GRID_LINE_COLOUR, line_width=GRID_LINE_WIDTH, font_size=FONT_SIZE) arctic_indices = numpy.where(latitudes_deg_n >= 66.5)[0] print(len(arctic_indices)) arctic_x_coords, arctic_y_coords = basemap_object( longitudes_deg_e[arctic_indices], latitudes_deg_n[arctic_indices]) axes_object.plot(arctic_x_coords, arctic_y_coords, linestyle='None', marker=MARKER_TYPE, markersize=MARKER_SIZE, markeredgewidth=0, markerfacecolor=ARCTIC_COLOUR, markeredgecolor=ARCTIC_COLOUR) mid_latitude_indices = numpy.where( numpy.logical_and(latitudes_deg_n >= 30., latitudes_deg_n < 66.5))[0] print(len(mid_latitude_indices)) mid_latitude_x_coords, mid_latitude_y_coords = basemap_object( longitudes_deg_e[mid_latitude_indices], latitudes_deg_n[mid_latitude_indices]) axes_object.plot(mid_latitude_x_coords, mid_latitude_y_coords, linestyle='None', marker=MARKER_TYPE, markersize=MARKER_SIZE, markeredgewidth=0, markerfacecolor=MID_LATITUDE_COLOUR, markeredgecolor=MID_LATITUDE_COLOUR) tropical_indices = numpy.where(latitudes_deg_n < 30.)[0] print(len(tropical_indices)) tropical_x_coords, tropical_y_coords = basemap_object( longitudes_deg_e[tropical_indices], latitudes_deg_n[tropical_indices]) axes_object.plot(tropical_x_coords, tropical_y_coords, linestyle='None', marker=MARKER_TYPE, markersize=MARKER_SIZE, markeredgewidth=0, markerfacecolor=TROPICAL_COLOUR, markeredgecolor=TROPICAL_COLOUR) file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name) 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_interp_two_times(storm_object_table, tornado_table, legend_font_size, legend_position_string): """Plots interpolation for one pair of times. :param storm_object_table: See doc for `_get_interp_data_for_split`. :param tornado_table: Same. :param legend_font_size: Font size in legend. :param legend_position_string: Legend position. :return: figure_object: Figure handle (instance of `matplotlib.figure.Figure`). :return: axes_object: Axes handle (instance of `matplotlib.axes._subplots.AxesSubplot`). """ centroid_x_coords = ( storm_object_table[tracking_utils.CENTROID_X_COLUMN].values ) centroid_y_coords = ( storm_object_table[tracking_utils.CENTROID_Y_COLUMN].values ) storm_times_minutes = ( storm_object_table[tracking_utils.VALID_TIME_COLUMN].values ).astype(float) secondary_id_strings = ( storm_object_table[tracking_utils.SECONDARY_ID_COLUMN].values ) storm_object_table = storm_object_table.assign(**{ tracking_utils.CENTROID_LONGITUDE_COLUMN: centroid_x_coords, tracking_utils.CENTROID_LATITUDE_COLUMN: centroid_y_coords }) figure_object, axes_object, basemap_object = ( plotting_utils.create_equidist_cylindrical_map( min_latitude_deg=numpy.min(centroid_y_coords), max_latitude_deg=numpy.max(centroid_y_coords), min_longitude_deg=numpy.min(centroid_x_coords), max_longitude_deg=numpy.max(centroid_x_coords) ) ) 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=TRACK_COLOUR, line_width=TRACK_WIDTH, start_marker_type=None, end_marker_type=None) num_storm_objects = len(storm_object_table.index) legend_handles = [] legend_strings = [] for i in range(num_storm_objects): this_patch_object = PolygonPatch( storm_object_table[POLYGON_COLUMN].values[i], lw=0, ec=NON_INTERP_COLOUR, fc=NON_INTERP_COLOUR, alpha=POLYGON_OPACITY) axes_object.add_patch(this_patch_object) this_handle = axes_object.plot( storm_object_table[tracking_utils.CENTROID_X_COLUMN].values, storm_object_table[tracking_utils.CENTROID_Y_COLUMN].values, linestyle='None', marker=DEFAULT_MARKER_TYPE, markersize=DEFAULT_MARKER_SIZE, markerfacecolor=NON_INTERP_COLOUR, markeredgecolor=NON_INTERP_COLOUR, markeredgewidth=DEFAULT_MARKER_EDGE_WIDTH )[0] legend_handles.append(this_handle) legend_strings.append('Actual storm') for i in range(num_storm_objects): axes_object.text( centroid_x_coords[i], centroid_y_coords[i] - TEXT_OFFSET, secondary_id_strings[i], color=TRACK_COLOUR, fontsize=DEFAULT_FONT_SIZE, fontweight='bold', horizontalalignment='center', verticalalignment='top') tornado_time_minutes = tornado_table[TORNADO_TIME_COLUMN].values[0] previous_time_minutes = numpy.max( storm_times_minutes[storm_times_minutes < tornado_time_minutes] ) next_time_minutes = numpy.min( storm_times_minutes[storm_times_minutes > tornado_time_minutes] ) previous_object_indices = numpy.where( storm_times_minutes == previous_time_minutes )[0] next_object_indices = numpy.where( storm_times_minutes == next_time_minutes )[0] previous_x_coord = numpy.mean(centroid_x_coords[previous_object_indices]) previous_y_coord = numpy.mean(centroid_y_coords[previous_object_indices]) next_x_coord = numpy.mean(centroid_x_coords[next_object_indices]) next_y_coord = numpy.mean(centroid_y_coords[next_object_indices]) if len(next_object_indices) == 1: midpoint_x_coord = previous_x_coord midpoint_y_coord = previous_y_coord midpoint_label_string = 'Midpoint of {0:s} and {1:s}'.format( secondary_id_strings[previous_object_indices[0]], secondary_id_strings[previous_object_indices[1]] ) line_x_coords = numpy.array([midpoint_x_coord, next_x_coord]) line_y_coords = numpy.array([midpoint_y_coord, next_y_coord]) else: midpoint_x_coord = next_x_coord midpoint_y_coord = next_y_coord midpoint_label_string = 'Midpoint of {0:s} and {1:s}'.format( secondary_id_strings[next_object_indices[0]], secondary_id_strings[next_object_indices[1]] ) line_x_coords = numpy.array([previous_x_coord, midpoint_x_coord]) line_y_coords = numpy.array([previous_y_coord, midpoint_y_coord]) this_handle = axes_object.plot( midpoint_x_coord, midpoint_y_coord, linestyle='None', marker=DEFAULT_MARKER_TYPE, markersize=DEFAULT_MARKER_SIZE, markerfacecolor=MIDPOINT_COLOUR, markeredgecolor=MIDPOINT_COLOUR, markeredgewidth=DEFAULT_MARKER_EDGE_WIDTH )[0] legend_handles.append(this_handle) legend_strings.append(midpoint_label_string) this_ratio = ( (tornado_time_minutes - previous_time_minutes) / (next_time_minutes - previous_time_minutes) ) interp_x_coord = previous_x_coord + ( this_ratio * (next_x_coord - previous_x_coord) ) interp_y_coord = previous_y_coord + ( this_ratio * (next_y_coord - previous_y_coord) ) if len(next_object_indices) == 1: x_offset = interp_x_coord - next_x_coord y_offset = interp_y_coord - next_y_coord interp_polygon_object_xy = storm_object_table[POLYGON_COLUMN].values[ next_object_indices[0] ] else: x_offset = interp_x_coord - previous_x_coord y_offset = interp_y_coord - previous_y_coord interp_polygon_object_xy = storm_object_table[POLYGON_COLUMN].values[ previous_object_indices[0] ] interp_polygon_object_xy = polygons.vertex_arrays_to_polygon_object( exterior_x_coords=( x_offset + numpy.array(interp_polygon_object_xy.exterior.xy[0]) ), exterior_y_coords=( y_offset + numpy.array(interp_polygon_object_xy.exterior.xy[1]) ) ) this_patch_object = PolygonPatch( interp_polygon_object_xy, lw=0, ec=INTERP_COLOUR, fc=INTERP_COLOUR, alpha=POLYGON_OPACITY) axes_object.add_patch(this_patch_object) this_handle = axes_object.plot( interp_x_coord, interp_y_coord, linestyle='None', marker=DEFAULT_MARKER_TYPE, markersize=DEFAULT_MARKER_SIZE, markerfacecolor=INTERP_COLOUR, markeredgecolor=INTERP_COLOUR, markeredgewidth=DEFAULT_MARKER_EDGE_WIDTH )[0] legend_handles.append(this_handle) legend_strings.append('Interpolated storm') this_handle = axes_object.plot( line_x_coords, line_y_coords, linestyle='dashed', color=MIDPOINT_COLOUR, linewidth=4 )[0] legend_handles.insert(-1, this_handle) legend_strings.insert(-1, 'Interpolation line') this_handle = axes_object.plot( tornado_table[TORNADO_X_COLUMN].values[0], tornado_table[TORNADO_Y_COLUMN].values[0], linestyle='None', marker=TORNADO_MARKER_TYPE, markersize=TORNADO_MARKER_SIZE, markerfacecolor=INTERP_COLOUR, markeredgecolor=INTERP_COLOUR, markeredgewidth=TORNADO_MARKER_EDGE_WIDTH )[0] legend_handles.insert(1, this_handle) this_string = 'Tornado (at {0:d} min)'.format( int(numpy.round(tornado_time_minutes)) ) legend_strings.insert(1, this_string) x_tick_values, unique_indices = numpy.unique( centroid_x_coords, return_index=True) x_tick_labels = [ '{0:d}'.format(int(numpy.round(storm_times_minutes[i]))) for i in unique_indices ] axes_object.set_xticks(x_tick_values) axes_object.set_xticklabels(x_tick_labels) axes_object.set_xlabel('Storm time (minutes)') axes_object.set_yticks([], []) axes_object.legend( legend_handles, legend_strings, fontsize=legend_font_size, loc=legend_position_string) return figure_object, axes_object
def _run(input_file_name, border_colour, polygon_colour, min_plot_latitude_deg, max_plot_latitude_deg, min_plot_longitude_deg, max_plot_longitude_deg, output_file_name): """Plots tornado-warning polygons. This is effectively the main method. :param input_file_name: See documentation at top of file. :param border_colour: Same. :param polygon_colour: Same. :param min_plot_latitude_deg: Same. :param max_plot_latitude_deg: Same. :param min_plot_longitude_deg: Same. :param max_plot_longitude_deg: Same. :param output_file_name: Same. """ print('Reading data from: "{0:s}"...'.format(input_file_name)) pickle_file_handle = open(input_file_name, 'rb') warning_table = pickle.load(pickle_file_handle) pickle_file_handle.close() num_warnings = len(warning_table.index) warning_min_latitudes_deg = numpy.full(num_warnings, numpy.nan) warning_max_latitudes_deg = numpy.full(num_warnings, numpy.nan) warning_min_longitudes_deg = numpy.full(num_warnings, numpy.nan) warning_max_longitudes_deg = numpy.full(num_warnings, numpy.nan) for i in range(num_warnings): this_vertex_dict_latlng = polygons.polygon_object_to_vertex_arrays( warning_table[POLYGON_COLUMN].values[i]) warning_min_latitudes_deg[i] = numpy.min( this_vertex_dict_latlng[polygons.EXTERIOR_Y_COLUMN]) warning_max_latitudes_deg[i] = numpy.max( this_vertex_dict_latlng[polygons.EXTERIOR_Y_COLUMN]) warning_min_longitudes_deg[i] = numpy.min( this_vertex_dict_latlng[polygons.EXTERIOR_X_COLUMN]) warning_max_longitudes_deg[i] = numpy.max( this_vertex_dict_latlng[polygons.EXTERIOR_X_COLUMN]) if min_plot_latitude_deg <= SENTINEL_VALUE: min_plot_latitude_deg = (numpy.min(warning_min_latitudes_deg) - LATLNG_BUFFER_DEG) if max_plot_latitude_deg <= SENTINEL_VALUE: max_plot_latitude_deg = (numpy.max(warning_min_latitudes_deg) + LATLNG_BUFFER_DEG) if min_plot_longitude_deg <= SENTINEL_VALUE: min_plot_longitude_deg = (numpy.min(warning_min_longitudes_deg) - LATLNG_BUFFER_DEG) if max_plot_longitude_deg <= SENTINEL_VALUE: max_plot_longitude_deg = (numpy.max(warning_min_longitudes_deg) + LATLNG_BUFFER_DEG) good_latitude_flags = numpy.logical_and( warning_max_latitudes_deg >= min_plot_latitude_deg, warning_min_latitudes_deg <= max_plot_latitude_deg) good_longitude_flags = numpy.logical_and( warning_max_longitudes_deg >= min_plot_longitude_deg, warning_min_longitudes_deg <= max_plot_longitude_deg) good_indices = numpy.where( numpy.logical_and(good_latitude_flags, good_longitude_flags))[0] warning_table = warning_table.iloc[good_indices] _, 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')) 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) num_warnings = len(warning_table.index) polygon_colour_tuple = plotting_utils.colour_from_numpy_to_tuple( polygon_colour) for i in range(num_warnings): this_vertex_dict_latlng = polygons.polygon_object_to_vertex_arrays( warning_table[POLYGON_COLUMN].values[i]) these_x_coords_metres, these_y_coords_metres = basemap_object( this_vertex_dict_latlng[polygons.EXTERIOR_X_COLUMN], this_vertex_dict_latlng[polygons.EXTERIOR_Y_COLUMN]) axes_object.plot(these_x_coords_metres, these_y_coords_metres, color=polygon_colour_tuple, linestyle='solid', linewidth=LINE_WIDTH) 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=FIGURE_RESOLUTION_DPI) pyplot.close() imagemagick_utils.trim_whitespace(input_file_name=output_file_name, output_file_name=output_file_name)
def _run(top_linkage_dir_name, genesis_only, max_link_distance_metres, first_spc_date_string, last_spc_date_string, num_colours, min_plot_latitude_deg, max_plot_latitude_deg, min_plot_longitude_deg, max_plot_longitude_deg, output_file_name): """Plots tornado reports, storm tracks, and linkages. This is effectively the main method. :param top_linkage_dir_name: See documentation at top of file. :param genesis_only: Same. :param max_link_distance_metres: Same. :param first_spc_date_string: Same. :param last_spc_date_string: Same. :param num_colours: Same. :param min_plot_latitude_deg: Same. :param max_plot_latitude_deg: Same. :param min_plot_longitude_deg: Same. :param max_plot_longitude_deg: Same. :param output_file_name: Same. """ if max_link_distance_metres < 0: max_link_distance_metres = None colour_map_object = _truncate_colour_map( orig_colour_map_object=pyplot.cm.get_cmap('YlOrRd'), num_colours=num_colours) event_type_string = (linkage.TORNADOGENESIS_EVENT_STRING if genesis_only else linkage.TORNADO_EVENT_STRING) if min_plot_latitude_deg <= SENTINEL_VALUE: min_plot_latitude_deg = None if max_plot_latitude_deg <= SENTINEL_VALUE: max_plot_latitude_deg = None if min_plot_longitude_deg <= SENTINEL_VALUE: min_plot_longitude_deg = None if max_plot_longitude_deg <= SENTINEL_VALUE: max_plot_longitude_deg = None file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name) spc_date_strings = time_conversion.get_spc_dates_in_range( first_spc_date_string=first_spc_date_string, last_spc_date_string=last_spc_date_string) list_of_linkage_tables = [] list_of_tornado_tables = [] linkage_metadata_dict = None for this_spc_date_string in spc_date_strings: this_file_name = linkage.find_linkage_file( top_directory_name=top_linkage_dir_name, event_type_string=event_type_string, spc_date_string=this_spc_date_string, raise_error_if_missing=False) if not os.path.isfile(this_file_name): continue print('Reading data from: "{0:s}"...'.format(this_file_name)) this_linkage_table, linkage_metadata_dict, this_tornado_table = ( linkage.read_linkage_file(this_file_name)) list_of_linkage_tables.append(this_linkage_table) list_of_tornado_tables.append(this_tornado_table) if len(list_of_linkage_tables) == 1: continue list_of_linkage_tables[-1] = list_of_linkage_tables[-1].align( list_of_linkage_tables[0], axis=1)[0] list_of_tornado_tables[-1] = list_of_tornado_tables[-1].align( list_of_tornado_tables[0], axis=1)[0] print(SEPARATOR_STRING) storm_to_tornadoes_table = pandas.concat(list_of_linkage_tables, axis=0, ignore_index=True) tornado_table = pandas.concat(list_of_tornado_tables, axis=0, ignore_index=True) column_dict_old_to_new = { linkage.EVENT_TIME_COLUMN: tornado_io.TIME_COLUMN, linkage.EVENT_LATITUDE_COLUMN: tornado_io.LATITUDE_COLUMN, linkage.EVENT_LONGITUDE_COLUMN: tornado_io.LONGITUDE_COLUMN } tornado_table.rename(columns=column_dict_old_to_new, inplace=True) tornado_table = tornado_io.segments_to_tornadoes(tornado_table) tornado_table = tornado_table.assign( **{ SHORT_TORNADO_ID_COLUMN: _long_to_short_tornado_ids(tornado_table[ tornado_io.TORNADO_ID_COLUMN].values) }) if min_plot_latitude_deg is None: min_plot_latitude_deg = numpy.min( storm_to_tornadoes_table[tracking_utils.CENTROID_LATITUDE_COLUMN]. values) - LATLNG_BUFFER_DEG if max_plot_latitude_deg is None: max_plot_latitude_deg = numpy.max( storm_to_tornadoes_table[tracking_utils.CENTROID_LATITUDE_COLUMN]. values) + LATLNG_BUFFER_DEG if min_plot_longitude_deg is None: min_plot_longitude_deg = numpy.min( storm_to_tornadoes_table[tracking_utils.CENTROID_LONGITUDE_COLUMN]. values) - LATLNG_BUFFER_DEG if max_plot_longitude_deg is None: max_plot_longitude_deg = numpy.max( storm_to_tornadoes_table[tracking_utils.CENTROID_LONGITUDE_COLUMN]. values) + LATLNG_BUFFER_DEG # TODO(thunderhoser): Should maybe restrict this to an inner domain. storm_to_tornadoes_table = storm_to_tornadoes_table.loc[ (storm_to_tornadoes_table[tracking_utils.CENTROID_LATITUDE_COLUMN] >= min_plot_latitude_deg) & (storm_to_tornadoes_table[tracking_utils.CENTROID_LATITUDE_COLUMN] <= max_plot_latitude_deg)] storm_to_tornadoes_table = storm_to_tornadoes_table.loc[ (storm_to_tornadoes_table[tracking_utils.CENTROID_LONGITUDE_COLUMN] >= min_plot_longitude_deg) & (storm_to_tornadoes_table[tracking_utils.CENTROID_LONGITUDE_COLUMN] <= max_plot_longitude_deg)] tornado_io.subset_tornadoes(tornado_table=tornado_table, 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) # TODO(thunderhoser): Make this subsetting optional. storm_to_tornadoes_table = _subset_storms_by_time( storm_to_tornadoes_table=storm_to_tornadoes_table, tornado_table=tornado_table, linkage_metadata_dict=linkage_metadata_dict, genesis_only=genesis_only) print(SEPARATOR_STRING) _, 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')) 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) print('Plotting storm tracks...') storm_plotting.plot_storm_tracks( storm_object_table=storm_to_tornadoes_table, axes_object=axes_object, basemap_object=basemap_object, colour_map_object=colour_map_object, start_marker_type=None, end_marker_type=None) num_tornadoes = len(tornado_table.index) if num_tornadoes == 0: print('Saving figure to: "{0:s}"...'.format(output_file_name)) pyplot.savefig(output_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close() return colour_norm_object = pyplot.Normalize( numpy.min( storm_to_tornadoes_table[tracking_utils.VALID_TIME_COLUMN].values), numpy.max( storm_to_tornadoes_table[tracking_utils.VALID_TIME_COLUMN].values)) print('Plotting tornado markers...') _plot_tornadoes(tornado_table=tornado_table, colour_map_object=colour_map_object, colour_norm_object=colour_norm_object, genesis_only=genesis_only, axes_object=axes_object, basemap_object=basemap_object) print('Plotting tornado IDs with storm objects...') num_storm_objects = len(storm_to_tornadoes_table.index) for i in range(num_storm_objects): _plot_linkages_one_storm_object( storm_to_tornadoes_table=storm_to_tornadoes_table, storm_object_index=i, tornado_table=tornado_table, colour_map_object=colour_map_object, colour_norm_object=colour_norm_object, axes_object=axes_object, basemap_object=basemap_object, max_link_distance_metres=max_link_distance_metres) print('Saving figure to: "{0:s}"...'.format(output_file_name)) pyplot.savefig(output_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close()
def _plot_score_one_field(latitude_matrix_deg, longitude_matrix_deg, score_matrix, colour_map_object, min_colour_value, max_colour_value, taper_cbar_top, taper_cbar_bottom, log_scale=False): """Plots one score for one field. M = number of rows in grid N = number of columns in grid :param latitude_matrix_deg: M-by-N numpy array of latitudes (deg N). :param longitude_matrix_deg: M-by-N numpy array of longitudes (deg E). :param score_matrix: M-by-N numpy array of score values. :param colour_map_object: Colour scheme (instance of `matplotlib.pyplot.cm`). :param min_colour_value: Minimum value in colour bar. :param max_colour_value: Max value in colour bar. :param taper_cbar_top: Boolean flag. If True, will taper bottom of colour bar, implying that lower values are possible. :param taper_cbar_bottom: Same but for top of colour bar. :param log_scale: Boolean flag. If True, will make colour bar logarithmic. :return: figure_object: Figure handle (instance of `matplotlib.figure.Figure`). :return: axes_object: Axes handle (instance of `matplotlib.axes._subplots.AxesSubplot`). """ (figure_object, axes_object, basemap_object) = plotting_utils.create_equidist_cylindrical_map( min_latitude_deg=latitude_matrix_deg[0, 0], max_latitude_deg=latitude_matrix_deg[-1, -1], min_longitude_deg=longitude_matrix_deg[0, 0], max_longitude_deg=longitude_matrix_deg[-1, -1], resolution_string=RESOLUTION_STRING) latitude_spacing_deg = latitude_matrix_deg[1, 0] - latitude_matrix_deg[0, 0] longitude_spacing_deg = (longitude_matrix_deg[0, 1] - longitude_matrix_deg[0, 0]) print(numpy.sum(numpy.invert(numpy.isnan(score_matrix)))) (score_matrix_at_edges, grid_edge_latitudes_deg, grid_edge_longitudes_deg) = grids.latlng_field_grid_points_to_edges( field_matrix=score_matrix, min_latitude_deg=latitude_matrix_deg[0, 0], min_longitude_deg=longitude_matrix_deg[0, 0], lat_spacing_deg=latitude_spacing_deg, lng_spacing_deg=longitude_spacing_deg) score_matrix_at_edges = numpy.ma.masked_where( numpy.isnan(score_matrix_at_edges), score_matrix_at_edges) plotting_utils.plot_coastlines(basemap_object=basemap_object, axes_object=axes_object, line_colour=BORDER_COLOUR, line_width=BORDER_WIDTH) plotting_utils.plot_countries(basemap_object=basemap_object, axes_object=axes_object, line_colour=BORDER_COLOUR, line_width=BORDER_WIDTH) # 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, line_width=0) plotting_utils.plot_meridians(basemap_object=basemap_object, axes_object=axes_object, num_meridians=NUM_MERIDIANS, line_width=0) pyplot.pcolormesh(grid_edge_longitudes_deg, grid_edge_latitudes_deg, score_matrix_at_edges, cmap=colour_map_object, vmin=min_colour_value, vmax=max_colour_value, shading='flat', edgecolors='None', axes=axes_object, zorder=-1e12) colour_bar_object = plotting_utils.plot_linear_colour_bar( axes_object_or_matrix=axes_object, data_matrix=score_matrix, colour_map_object=colour_map_object, min_value=min_colour_value, max_value=max_colour_value, orientation_string='horizontal', extend_min=taper_cbar_bottom, extend_max=taper_cbar_top, padding=0.05, font_size=COLOUR_BAR_FONT_SIZE) tick_values = colour_bar_object.get_ticks() if log_scale: tick_strings = [ '{0:d}'.format(int(numpy.round(10**v))) for v in tick_values ] elif numpy.nanmax(numpy.absolute(score_matrix)) >= 6: tick_strings = [ '{0:d}'.format(int(numpy.round(v))) for v in tick_values ] else: tick_strings = ['{0:.2f}'.format(v) for v in tick_values] colour_bar_object.set_ticks(tick_values) colour_bar_object.set_ticklabels(tick_strings) return figure_object, axes_object