def _plot_sounding(list_of_predictor_matrices, model_metadata_dict, allow_whitespace, title_string=None): """Plots sounding for one example. :param list_of_predictor_matrices: See doc for `_plot_3d_radar_scan`. :param model_metadata_dict: Same. :param allow_whitespace: Same. :param title_string: Same. :return: figure_object: Figure handle (instance of `matplotlib.figure.Figure`). :return: axes_object: Axes handle (instance of `matplotlib.axes._subplots.AxesSubplot`). """ training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY] sounding_field_names = training_option_dict[ trainval_io.SOUNDING_FIELDS_KEY] sounding_heights_m_agl = training_option_dict[ trainval_io.SOUNDING_HEIGHTS_KEY] sounding_matrix = numpy.expand_dims(list_of_predictor_matrices[-1], axis=0) # TODO(thunderhoser): Allow actual storm elevation to be used. metpy_dict = dl_utils.soundings_to_metpy_dictionaries( sounding_matrix=sounding_matrix, field_names=sounding_field_names, height_levels_m_agl=sounding_heights_m_agl, storm_elevations_m_asl=numpy.array([0.]))[0] return sounding_plotting.plot_sounding( sounding_dict_for_metpy=metpy_dict, title_string=title_string if allow_whitespace else None)
def _plot_sounding_saliency( saliency_matrix, colour_map_object, max_colour_value, sounding_matrix, saliency_dict, model_metadata_dict, output_dir_name, pmm_flag, example_index=None): """Plots saliency for sounding. H = number of sounding heights F = number of sounding fields If plotting a composite rather than one example, `full_storm_id_string` and `storm_time_unix_sec` can be None. :param saliency_matrix: H-by-F numpy array of saliency values. :param colour_map_object: See documentation at top of file. :param max_colour_value: Max value in colour scheme for saliency. :param sounding_matrix: H-by-F numpy array of actual sounding values. :param saliency_dict: Dictionary returned from `saliency_maps.read_standard_file` or `saliency_maps.read_pmm_file`. :param model_metadata_dict: Dictionary returned by `cnn.read_model_metadata`. :param output_dir_name: Path to output directory. Figure will be saved here. :param pmm_flag: Boolean flag. If True, will plot composite rather than one example. :param example_index: [used only if `pmm_flag == False`] Will plot the [i]th example, where i = `example_index`. """ if pmm_flag: example_index = 0 training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY] sounding_field_names = training_option_dict[trainval_io.SOUNDING_FIELDS_KEY] sounding_heights_m_agl = training_option_dict[ trainval_io.SOUNDING_HEIGHTS_KEY] sounding_matrix = numpy.expand_dims(sounding_matrix, axis=0) if saliency_maps.SOUNDING_PRESSURES_KEY in saliency_dict: pressure_matrix_pascals = numpy.expand_dims( saliency_dict[saliency_maps.SOUNDING_PRESSURES_KEY], axis=-1 ) pressure_matrix_pascals = pressure_matrix_pascals[[example_index], ...] sounding_matrix = numpy.concatenate( (sounding_matrix, pressure_matrix_pascals), axis=-1 ) sounding_dict_for_metpy = dl_utils.soundings_to_metpy_dictionaries( sounding_matrix=sounding_matrix, field_names=sounding_field_names + [soundings.PRESSURE_NAME] )[0] else: sounding_dict_for_metpy = dl_utils.soundings_to_metpy_dictionaries( sounding_matrix=sounding_matrix, field_names=sounding_field_names, height_levels_m_agl=sounding_heights_m_agl, storm_elevations_m_asl=numpy.array([0.]) )[0] if pmm_flag: full_storm_id_string = None storm_time_unix_sec = None title_string = 'PMM composite' else: full_storm_id_string = saliency_dict[saliency_maps.FULL_IDS_KEY][ example_index] storm_time_unix_sec = saliency_dict[saliency_maps.STORM_TIMES_KEY][ example_index] title_string = 'Storm "{0:s}" at {1:s}'.format( full_storm_id_string, time_conversion.unix_sec_to_string( storm_time_unix_sec, plot_input_examples.TIME_FORMAT) ) sounding_plotting.plot_sounding( sounding_dict_for_metpy=sounding_dict_for_metpy, title_string=title_string) left_panel_file_name = plot_input_examples.metadata_to_file_name( output_dir_name=output_dir_name, is_sounding=False, pmm_flag=pmm_flag, full_storm_id_string=full_storm_id_string, storm_time_unix_sec=storm_time_unix_sec, radar_field_name='sounding-actual') print('Saving figure to file: "{0:s}"...'.format(left_panel_file_name)) pyplot.savefig(left_panel_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close() imagemagick_utils.trim_whitespace( input_file_name=left_panel_file_name, output_file_name=left_panel_file_name) saliency_plotting.plot_saliency_for_sounding( saliency_matrix=saliency_matrix, sounding_field_names=sounding_field_names, pressure_levels_mb=sounding_dict_for_metpy[ soundings.PRESSURE_COLUMN_METPY], colour_map_object=colour_map_object, max_absolute_colour_value=max_colour_value) right_panel_file_name = plot_input_examples.metadata_to_file_name( output_dir_name=output_dir_name, is_sounding=False, pmm_flag=pmm_flag, full_storm_id_string=full_storm_id_string, storm_time_unix_sec=storm_time_unix_sec, radar_field_name='sounding-saliency') print('Saving figure to file: "{0:s}"...'.format(right_panel_file_name)) pyplot.savefig(right_panel_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close() imagemagick_utils.trim_whitespace( input_file_name=right_panel_file_name, output_file_name=right_panel_file_name) concat_file_name = plot_input_examples.metadata_to_file_name( output_dir_name=output_dir_name, is_sounding=True, pmm_flag=pmm_flag, full_storm_id_string=full_storm_id_string, storm_time_unix_sec=storm_time_unix_sec) print('Concatenating figures to: "{0:s}"...\n'.format(concat_file_name)) imagemagick_utils.concatenate_images( input_file_names=[left_panel_file_name, right_panel_file_name], output_file_name=concat_file_name, num_panel_rows=1, num_panel_columns=2) imagemagick_utils.resize_image( input_file_name=concat_file_name, output_file_name=concat_file_name, output_size_pixels=SOUNDING_IMAGE_SIZE_PX) os.remove(left_panel_file_name) os.remove(right_panel_file_name)
def _plot_sounding_saliency( sounding_matrix, sounding_saliency_matrix, sounding_field_names, saliency_metadata_dict, colour_map_object, max_colour_value_by_example, output_dir_name): """Plots soundings along with their saliency maps. E = number of examples H = number of sounding heights F = number of sounding fields :param sounding_matrix: E-by-H-by-F numpy array of sounding values. :param sounding_saliency_matrix: E-by-H-by-F numpy array of corresponding saliency values. :param sounding_field_names: length-F list of field names. :param saliency_metadata_dict: Dictionary returned by `saliency_maps.read_standard_file`. :param colour_map_object: See doc for `_plot_2d3d_radar_saliency`. :param max_colour_value_by_example: Same. :param output_dir_name: Name of output directory (figures will be saved here). """ # TODO(thunderhoser): Generalize this method to deal with # probability-matched means. num_examples = sounding_matrix.shape[0] try: metpy_dict_by_example = dl_utils.soundings_to_metpy_dictionaries( sounding_matrix=sounding_matrix, field_names=sounding_field_names) except: sounding_pressure_matrix_pa = numpy.expand_dims( saliency_metadata_dict[saliency_maps.SOUNDING_PRESSURES_KEY], axis=-1) this_sounding_matrix = numpy.concatenate( (sounding_matrix, sounding_pressure_matrix_pa), axis=-1) metpy_dict_by_example = dl_utils.soundings_to_metpy_dictionaries( sounding_matrix=this_sounding_matrix, field_names=sounding_field_names + [soundings.PRESSURE_NAME]) for i in range(num_examples): this_storm_id = saliency_metadata_dict[ saliency_maps.STORM_IDS_KEY][i] this_storm_time_string = time_conversion.unix_sec_to_string( saliency_metadata_dict[saliency_maps.STORM_TIMES_KEY][i], TIME_FORMAT) this_title_string = 'Storm "{0:s}" at {1:s}'.format( this_storm_id, this_storm_time_string) sounding_plotting.plot_sounding( sounding_dict_for_metpy=metpy_dict_by_example[i], title_string=this_title_string) this_left_file_name = ( '{0:s}/{1:s}_{2:s}_sounding-actual.jpg' ).format( output_dir_name, this_storm_id.replace('_', '-'), this_storm_time_string ) print 'Saving figure to file: "{0:s}"...'.format( this_left_file_name) pyplot.savefig(this_left_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close() imagemagick_utils.trim_whitespace( input_file_name=this_left_file_name, output_file_name=this_left_file_name) saliency_plotting.plot_saliency_for_sounding( saliency_matrix=sounding_saliency_matrix[i, ...], sounding_field_names=sounding_field_names, pressure_levels_mb=metpy_dict_by_example[i][ soundings.PRESSURE_COLUMN_METPY], colour_map_object=colour_map_object, max_absolute_colour_value=max_colour_value_by_example[i]) this_right_file_name = ( '{0:s}/{1:s}_{2:s}_sounding-saliency.jpg' ).format( output_dir_name, this_storm_id.replace('_', '-'), this_storm_time_string ) print 'Saving figure to file: "{0:s}"...'.format( this_right_file_name) pyplot.savefig(this_right_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close() imagemagick_utils.trim_whitespace( input_file_name=this_right_file_name, output_file_name=this_right_file_name) this_file_name = ( '{0:s}/saliency_{1:s}_{2:s}_sounding.jpg' ).format( output_dir_name, this_storm_id.replace('_', '-'), this_storm_time_string ) print 'Concatenating panels into file: "{0:s}"...\n'.format( this_file_name) imagemagick_utils.concatenate_images( input_file_names=[this_left_file_name, this_right_file_name], output_file_name=this_file_name, num_panel_rows=1, num_panel_columns=2) imagemagick_utils.resize_image( input_file_name=this_file_name, output_file_name=this_file_name, output_size_pixels=SOUNDING_IMAGE_SIZE_PX) os.remove(this_left_file_name) os.remove(this_right_file_name)
def _plot_bwo_for_soundings( optimized_sounding_matrix, training_option_dict, top_output_dir_name, pmm_flag, input_sounding_matrix=None, storm_ids=None, storm_times_unix_sec=None): """Plots BWO results for soundings. E = number of examples (storm objects) H = number of sounding heights F = number of sounding fields :param optimized_sounding_matrix: E-by-H-by-F numpy array of sounding values (predictors). :param training_option_dict: See doc for `_plot_bwo_for_2d3d_radar`. :param top_output_dir_name: Same. :param pmm_flag: Same. :param input_sounding_matrix: Same as `optimized_sounding_matrix` but with non-optimized input. :param storm_ids: See doc for `_plot_bwo_for_2d3d_radar`. :param storm_times_unix_sec: Same. """ before_optimization_dir_name = '{0:s}/before_optimization'.format( top_output_dir_name) after_optimization_dir_name = '{0:s}/after_optimization'.format( top_output_dir_name) file_system_utils.mkdir_recursive_if_necessary( directory_name=before_optimization_dir_name) file_system_utils.mkdir_recursive_if_necessary( directory_name=after_optimization_dir_name) if pmm_flag: have_storm_ids = False else: have_storm_ids = not (storm_ids is None or storm_times_unix_sec is None) num_storms = optimized_sounding_matrix.shape[0] list_of_optimized_metpy_dicts = dl_utils.soundings_to_metpy_dictionaries( sounding_matrix=optimized_sounding_matrix, field_names=training_option_dict[trainval_io.SOUNDING_FIELDS_KEY], height_levels_m_agl=training_option_dict[ trainval_io.SOUNDING_HEIGHTS_KEY], storm_elevations_m_asl=numpy.zeros(num_storms)) if input_sounding_matrix is None: list_of_input_metpy_dicts = None else: list_of_input_metpy_dicts = dl_utils.soundings_to_metpy_dictionaries( sounding_matrix=input_sounding_matrix, field_names=training_option_dict[trainval_io.SOUNDING_FIELDS_KEY], height_levels_m_agl=training_option_dict[ trainval_io.SOUNDING_HEIGHTS_KEY], storm_elevations_m_asl=numpy.zeros(num_storms)) for i in range(num_storms): if pmm_flag: this_base_title_string = 'Probability-matched mean' this_base_pathless_file_name = 'pmm' else: if have_storm_ids: this_storm_time_string = time_conversion.unix_sec_to_string( storm_times_unix_sec[i], TIME_FORMAT) this_base_title_string = 'Storm "{0:s}" at {1:s}'.format( storm_ids[i], this_storm_time_string) this_base_pathless_file_name = '{0:s}_{1:s}'.format( storm_ids[i].replace('_', '-'), this_storm_time_string) else: this_base_title_string = 'Example {0:d}'.format(i + 1) this_base_pathless_file_name = 'example{0:06d}'.format(i) this_title_string = '{0:s} (after optimization)'.format( this_base_title_string) this_file_name = '{0:s}/{1:s}_after-optimization_sounding.jpg'.format( after_optimization_dir_name, this_base_pathless_file_name) sounding_plotting.plot_sounding( sounding_dict_for_metpy=list_of_optimized_metpy_dicts[i], title_string=this_title_string) print 'Saving figure to: "{0:s}"...'.format(this_file_name) pyplot.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close() if input_sounding_matrix is None: continue this_title_string = '{0:s} (before optimization)'.format( this_base_title_string) this_file_name = '{0:s}/{1:s}_before-optimization_sounding.jpg'.format( before_optimization_dir_name, this_base_pathless_file_name) sounding_plotting.plot_sounding( sounding_dict_for_metpy=list_of_input_metpy_dicts[i], title_string=this_title_string) print 'Saving figure to: "{0:s}"...'.format(this_file_name) pyplot.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close()
def plot_examples(list_of_predictor_matrices, storm_ids, storm_times_unix_sec, model_metadata_dict, output_dir_name, storm_activations=None): """Plots one or more learning examples. E = number of examples (storm objects) :param list_of_predictor_matrices: List created by `testing_io.read_specific_examples`. Contains data to be plotted. :param storm_ids: length-E list of storm IDs. :param storm_times_unix_sec: length-E numpy array of storm times. :param model_metadata_dict: See doc for `cnn.read_model_metadata`. :param output_dir_name: Name of output directory (figures will be saved here). :param storm_activations: length-E numpy array of storm activations (may be None). Will be included in title of each figure. """ training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY] sounding_field_names = training_option_dict[ trainval_io.SOUNDING_FIELDS_KEY] plot_soundings = sounding_field_names is not None if plot_soundings: list_of_metpy_dictionaries = dl_utils.soundings_to_metpy_dictionaries( sounding_matrix=list_of_predictor_matrices[-1], field_names=sounding_field_names) else: list_of_metpy_dictionaries = None num_radar_dimensions = len(list_of_predictor_matrices[0].shape) - 2 list_of_layer_operation_dicts = model_metadata_dict[ cnn.LAYER_OPERATIONS_KEY] if num_radar_dimensions == 2: if list_of_layer_operation_dicts is None: field_name_by_panel = training_option_dict[ trainval_io.RADAR_FIELDS_KEY] panel_names = ( radar_plotting.radar_fields_and_heights_to_panel_names( field_names=field_name_by_panel, heights_m_agl=training_option_dict[ trainval_io.RADAR_HEIGHTS_KEY])) plot_colour_bar_by_panel = numpy.full(len(panel_names), True, dtype=bool) else: field_name_by_panel, panel_names = ( radar_plotting.layer_ops_to_field_and_panel_names( list_of_layer_operation_dicts)) plot_colour_bar_by_panel = numpy.full(len(panel_names), False, dtype=bool) plot_colour_bar_by_panel[2::3] = True else: field_name_by_panel = None panel_names = None plot_colour_bar_by_panel = None az_shear_field_names = training_option_dict[trainval_io.RADAR_FIELDS_KEY] num_az_shear_fields = len(az_shear_field_names) num_storms = len(storm_ids) myrorss_2d3d = len(list_of_predictor_matrices) == 3 for i in range(num_storms): this_time_string = time_conversion.unix_sec_to_string( storm_times_unix_sec[i], TIME_FORMAT) this_base_title_string = 'Storm "{0:s}" at {1:s}'.format( storm_ids[i], this_time_string) if storm_activations is not None: this_base_title_string += ' (activation = {0:.3f})'.format( storm_activations[i]) this_base_file_name = '{0:s}/storm={1:s}_{2:s}'.format( output_dir_name, storm_ids[i].replace('_', '-'), this_time_string) if plot_soundings: sounding_plotting.plot_sounding( sounding_dict_for_metpy=list_of_metpy_dictionaries[i], title_string=this_base_title_string) this_file_name = '{0:s}_sounding.jpg'.format(this_base_file_name) print 'Saving figure to: "{0:s}"...'.format(this_file_name) pyplot.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close() if myrorss_2d3d: this_reflectivity_matrix_dbz = numpy.flip( list_of_predictor_matrices[0][i, ..., 0], axis=0) this_num_heights = this_reflectivity_matrix_dbz.shape[-1] this_num_panel_rows = int(numpy.floor( numpy.sqrt(this_num_heights))) _, these_axes_objects = radar_plotting.plot_3d_grid_without_coords( field_matrix=this_reflectivity_matrix_dbz, field_name=radar_utils.REFL_NAME, grid_point_heights_metres=training_option_dict[ trainval_io.RADAR_HEIGHTS_KEY], ground_relative=True, num_panel_rows=this_num_panel_rows, font_size=FONT_SIZE_SANS_COLOUR_BARS) this_colour_map_object, this_colour_norm_object = ( radar_plotting.get_default_colour_scheme( radar_utils.REFL_NAME)) plotting_utils.add_colour_bar( axes_object_or_list=these_axes_objects, values_to_colour=this_reflectivity_matrix_dbz, colour_map=this_colour_map_object, colour_norm_object=this_colour_norm_object, orientation='horizontal', extend_min=True, extend_max=True) this_title_string = '{0:s}; {1:s}'.format(this_base_title_string, radar_utils.REFL_NAME) this_file_name = '{0:s}_reflectivity.jpg'.format( this_base_file_name) pyplot.suptitle(this_title_string, fontsize=TITLE_FONT_SIZE) print 'Saving figure to: "{0:s}"...'.format(this_file_name) pyplot.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close() this_az_shear_matrix_s01 = numpy.flip( list_of_predictor_matrices[1][i, ..., 0], axis=0) _, these_axes_objects = ( radar_plotting.plot_many_2d_grids_without_coords( field_matrix=this_az_shear_matrix_s01, field_name_by_panel=az_shear_field_names, panel_names=az_shear_field_names, num_panel_rows=1, plot_colour_bar_by_panel=numpy.full(num_az_shear_fields, False, dtype=bool), font_size=FONT_SIZE_SANS_COLOUR_BARS)) this_colour_map_object, this_colour_norm_object = ( radar_plotting.get_default_colour_scheme( radar_utils.LOW_LEVEL_SHEAR_NAME)) plotting_utils.add_colour_bar( axes_object_or_list=these_axes_objects, values_to_colour=this_az_shear_matrix_s01, colour_map=this_colour_map_object, colour_norm_object=this_colour_norm_object, orientation='horizontal', extend_min=True, extend_max=True) this_file_name = '{0:s}_shear.jpg'.format(this_base_file_name) pyplot.suptitle(this_base_title_string, fontsize=TITLE_FONT_SIZE) print 'Saving figure to: "{0:s}"...'.format(this_file_name) pyplot.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close() continue this_radar_matrix = list_of_predictor_matrices[0] if num_radar_dimensions == 2: this_num_channels = this_radar_matrix.shape[-1] this_num_panel_rows = int( numpy.floor(numpy.sqrt(this_num_channels))) radar_plotting.plot_many_2d_grids_without_coords( field_matrix=numpy.flip(this_radar_matrix[i, ...], axis=0), field_name_by_panel=field_name_by_panel, panel_names=panel_names, num_panel_rows=this_num_panel_rows, plot_colour_bar_by_panel=plot_colour_bar_by_panel, font_size=FONT_SIZE_WITH_COLOUR_BARS, row_major=False) this_title_string = this_base_title_string + '' pyplot.suptitle(this_title_string, fontsize=TITLE_FONT_SIZE) this_file_name = '{0:s}.jpg'.format(this_base_file_name) print 'Saving figure to: "{0:s}"...'.format(this_file_name) pyplot.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close() continue radar_field_names = training_option_dict[trainval_io.RADAR_FIELDS_KEY] radar_heights_m_agl = training_option_dict[ trainval_io.RADAR_HEIGHTS_KEY] for j in range(len(radar_field_names)): this_num_heights = this_radar_matrix.shape[-2] this_num_panel_rows = int(numpy.floor( numpy.sqrt(this_num_heights))) _, these_axes_objects = radar_plotting.plot_3d_grid_without_coords( field_matrix=numpy.flip(this_radar_matrix[i, ..., j], axis=0), field_name=radar_field_names[j], grid_point_heights_metres=radar_heights_m_agl, ground_relative=True, num_panel_rows=this_num_panel_rows, font_size=FONT_SIZE_SANS_COLOUR_BARS) this_colour_map_object, this_colour_norm_object = ( radar_plotting.get_default_colour_scheme(radar_field_names[j])) plotting_utils.add_colour_bar( axes_object_or_list=these_axes_objects, values_to_colour=this_radar_matrix[i, ..., j], colour_map=this_colour_map_object, colour_norm_object=this_colour_norm_object, orientation='horizontal', extend_min=True, extend_max=True) this_title_string = '{0:s}; {1:s}'.format(this_base_title_string, radar_field_names[j]) this_file_name = '{0:s}_{1:s}.jpg'.format( this_base_file_name, radar_field_names[j].replace('_', '-')) pyplot.suptitle(this_title_string, fontsize=TITLE_FONT_SIZE) print 'Saving figure to: "{0:s}"...'.format(this_file_name) pyplot.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI) pyplot.close()