def _plot_2d_radar_cam(colour_map_object, max_colour_percentile, figure_objects, axes_object_matrices, model_metadata_dict, output_dir_name, cam_matrix=None, guided_cam_matrix=None, significance_matrix=None, full_storm_id_string=None, storm_time_unix_sec=None): """Plots guided or unguided class-activation map for 2-D radar data. M = number of rows in spatial grid N = number of columns in spatial grid C = number of radar channels :param colour_map_object: See doc for `_plot_3d_radar_cam`. :param max_colour_percentile: Same. :param figure_objects: Same. :param axes_object_matrices: Same. :param model_metadata_dict: Same. :param output_dir_name: Same. :param cam_matrix: M-by-N numpy array of class activations. :param guided_cam_matrix: M-by-N-by-C numpy array of guided-CAM output. :param significance_matrix: See doc for `_plot_3d_radar_cam`. :param full_storm_id_string: Same. :param storm_time_unix_sec: Same. """ if cam_matrix is None: quantity_string = 'max abs value' else: quantity_string = 'max activation' pmm_flag = full_storm_id_string is None and storm_time_unix_sec is None conv_2d3d = model_metadata_dict[cnn.CONV_2D3D_KEY] figure_index = 1 if conv_2d3d else 0 list_of_layer_operation_dicts = model_metadata_dict[ cnn.LAYER_OPERATIONS_KEY] if list_of_layer_operation_dicts is None: training_option_dict = model_metadata_dict[ cnn.TRAINING_OPTION_DICT_KEY] radar_field_names = training_option_dict[trainval_io.RADAR_FIELDS_KEY] num_channels = len(radar_field_names) else: num_channels = len(list_of_layer_operation_dicts) if cam_matrix is None: this_matrix = guided_cam_matrix else: this_matrix = numpy.expand_dims(cam_matrix, axis=-1) this_matrix = numpy.repeat(this_matrix, repeats=num_channels, axis=-1) max_contour_level = numpy.percentile(numpy.absolute(this_matrix), max_colour_percentile) if cam_matrix is None: saliency_plotting.plot_many_2d_grids_with_contours( saliency_matrix_3d=numpy.flip(this_matrix, axis=0), axes_object_matrix=axes_object_matrices[figure_index], colour_map_object=colour_map_object, max_absolute_contour_level=max_contour_level, contour_interval=max_contour_level / HALF_NUM_CONTOURS, row_major=False) else: cam_plotting.plot_many_2d_grids( class_activation_matrix_3d=numpy.flip(this_matrix, axis=0), axes_object_matrix=axes_object_matrices[figure_index], colour_map_object=colour_map_object, max_contour_level=max_contour_level, contour_interval=max_contour_level / NUM_CONTOURS, row_major=False) if significance_matrix is not None: if cam_matrix is None: this_matrix = significance_matrix else: this_matrix = numpy.expand_dims(significance_matrix, axis=-1) this_matrix = numpy.repeat(this_matrix, repeats=num_channels, axis=-1) significance_plotting.plot_many_2d_grids_without_coords( significance_matrix=numpy.flip(this_matrix, axis=0), axes_object_matrix=axes_object_matrices[figure_index], row_major=False) this_title_string = figure_objects[figure_index]._suptitle if this_title_string is not None: this_title_string += ' ({0:s} = {1:.2e})'.format( quantity_string, max_contour_level) figure_objects[figure_index].suptitle( this_title_string, fontsize=plot_input_examples.TITLE_FONT_SIZE) output_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='shear' if conv_2d3d else None) print('Saving figure to: "{0:s}"...'.format(output_file_name)) figure_objects[figure_index].savefig(output_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_objects[figure_index])
def _plot_2d_radar_saliency( saliency_matrix, colour_map_object, max_colour_value, figure_objects, axes_object_matrices, model_metadata_dict, output_dir_name, significance_matrix=None, full_storm_id_string=None, storm_time_unix_sec=None): """Plots saliency map for 2-D radar data. M = number of rows in spatial grid N = number of columns in spatial grid C = number of radar channels If this method is plotting a composite rather than single example (storm object), `full_storm_id_string` and `storm_time_unix_sec` can be None. :param saliency_matrix: M-by-N-by-C 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 figure_objects: See doc for `plot_input_examples._plot_2d_radar_scan`. :param axes_object_matrices: Same. :param model_metadata_dict: Dictionary returned by `cnn.read_model_metadata`. :param output_dir_name: Path to output directory. Figure(s) will be saved here. :param significance_matrix: M-by-N-by-H numpy array of Boolean flags, indicating where differences with some other saliency map are significant. :param full_storm_id_string: Full storm ID. :param storm_time_unix_sec: Storm time. """ pmm_flag = full_storm_id_string is None and storm_time_unix_sec is None conv_2d3d = model_metadata_dict[cnn.CONV_2D3D_KEY] if conv_2d3d: figure_index = 1 radar_field_name = 'shear' else: figure_index = 0 radar_field_name = None list_of_layer_operation_dicts = model_metadata_dict[ cnn.LAYER_OPERATIONS_KEY] if list_of_layer_operation_dicts is not None: saliency_matrix = saliency_matrix[ ..., plot_input_examples.LAYER_OP_INDICES_TO_KEEP ] if significance_matrix is not None: significance_matrix = significance_matrix[ ..., plot_input_examples.LAYER_OP_INDICES_TO_KEEP ] saliency_plotting.plot_many_2d_grids_with_contours( saliency_matrix_3d=numpy.flip(saliency_matrix, axis=0), axes_object_matrix=axes_object_matrices[figure_index], colour_map_object=colour_map_object, max_absolute_contour_level=max_colour_value, contour_interval=max_colour_value / HALF_NUM_CONTOURS, row_major=False) if significance_matrix is not None: significance_plotting.plot_many_2d_grids_without_coords( significance_matrix=numpy.flip(significance_matrix, axis=0), axes_object_matrix=axes_object_matrices[figure_index], row_major=False) this_title_object = figure_objects[figure_index]._suptitle if this_title_object is not None: this_title_string = '{0:s} (max abs saliency = {1:.2e})'.format( this_title_object.get_text(), max_colour_value ) figure_objects[figure_index].suptitle( this_title_string, fontsize=plot_input_examples.TITLE_FONT_SIZE) output_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=radar_field_name) print('Saving figure to: "{0:s}"...'.format(output_file_name)) figure_objects[figure_index].savefig( output_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) pyplot.close(figure_objects[figure_index])
def _plot_3d_radar_cam(colour_map_object, max_colour_percentile, figure_objects, axes_object_matrices, model_metadata_dict, output_dir_name, cam_matrix=None, guided_cam_matrix=None, significance_matrix=None, full_storm_id_string=None, storm_time_unix_sec=None): """Plots guided or unguided class-activation map for 3-D radar data. This method will plot either `cam_matrix` or `guided_cam_matrix`, not both. M = number of rows in spatial grid N = number of columns in spatial grid H = number of heights in spatial grid F = number of radar fields If this method is plotting a composite rather than single example (storm object), `full_storm_id_string` and `storm_time_unix_sec` can be None. :param colour_map_object: See documentation at top of file. :param max_colour_percentile: Same. :param figure_objects: See doc for `plot_input_examples._plot_3d_example`. :param axes_object_matrices: Same. :param model_metadata_dict: Dictionary returned by `cnn.read_model_metadata`. :param output_dir_name: Path to output directory. Figure(s) will be saved here. :param cam_matrix: M-by-N-by-H numpy array of class activations. :param guided_cam_matrix: M-by-N-by-H-by-F numpy array of guided-CAM output. :param significance_matrix: Boolean numpy array with the same dimensions as the array being plotted (`cam_matrix` or `guided_cam_matrix`), indicating where differences with some other CAM are significant. :param full_storm_id_string: Full storm ID. :param storm_time_unix_sec: Storm time. """ if cam_matrix is None: quantity_string = 'max abs value' else: quantity_string = 'max activation' pmm_flag = full_storm_id_string is None and storm_time_unix_sec is None conv_2d3d = model_metadata_dict[cnn.CONV_2D3D_KEY] if conv_2d3d: loop_max = 1 radar_field_names = ['reflectivity'] else: loop_max = len(figure_objects) training_option_dict = model_metadata_dict[ cnn.TRAINING_OPTION_DICT_KEY] radar_field_names = training_option_dict[trainval_io.RADAR_FIELDS_KEY] for j in range(loop_max): if cam_matrix is None: this_matrix = guided_cam_matrix[..., j] else: this_matrix = cam_matrix this_max_contour_level = numpy.percentile(numpy.absolute(this_matrix), max_colour_percentile) if cam_matrix is None: saliency_plotting.plot_many_2d_grids_with_contours( saliency_matrix_3d=numpy.flip(this_matrix, axis=0), axes_object_matrix=axes_object_matrices[j], colour_map_object=colour_map_object, max_absolute_contour_level=this_max_contour_level, contour_interval=this_max_contour_level / HALF_NUM_CONTOURS) else: cam_plotting.plot_many_2d_grids( class_activation_matrix_3d=numpy.flip(this_matrix, axis=0), axes_object_matrix=axes_object_matrices[j], colour_map_object=colour_map_object, max_contour_level=this_max_contour_level, contour_interval=this_max_contour_level / NUM_CONTOURS) if significance_matrix is not None: if cam_matrix is None: this_matrix = significance_matrix[..., j] else: this_matrix = significance_matrix significance_plotting.plot_many_2d_grids_without_coords( significance_matrix=numpy.flip(this_matrix, axis=0), axes_object_matrix=axes_object_matrices[j]) this_title_string = figure_objects[j]._suptitle if this_title_string is not None: this_title_string += ' ({0:s} = {1:.2e})'.format( quantity_string, this_max_contour_level) figure_objects[j].suptitle( this_title_string, fontsize=plot_input_examples.TITLE_FONT_SIZE) this_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=radar_field_names[j]) print('Saving figure to: "{0:s}"...'.format(this_file_name)) figure_objects[j].savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_objects[j])
def _plot_one_composite(saliency_file_name, monte_carlo_file_name, composite_name_abbrev, composite_name_verbose, colour_map_object, max_colour_value, half_num_contours, smoothing_radius_grid_cells, output_dir_name): """Plots saliency map for one composite. :param saliency_file_name: Path to saliency file (will be read by `saliency.read_file`). :param monte_carlo_file_name: Path to Monte Carlo file (will be read by `_read_monte_carlo_file`). :param composite_name_abbrev: Abbrev composite name (will be used in file names). :param composite_name_verbose: Verbose composite name (will be used in figure title). :param colour_map_object: See documentation at top of file. :param max_colour_value: Same. :param half_num_contours: Same. :param smoothing_radius_grid_cells: Same. :param output_dir_name: Name of output directory (figures will be saved here). :return: main_figure_file_name: Path to main image file created by this method. """ (mean_radar_matrices, mean_saliency_matrices, significance_matrices, model_metadata_dict) = _read_one_composite( saliency_file_name=saliency_file_name, smoothing_radius_grid_cells=smoothing_radius_grid_cells, monte_carlo_file_name=monte_carlo_file_name) refl_heights_m_agl = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY][ trainval_io.RADAR_HEIGHTS_KEY] num_refl_heights = len(refl_heights_m_agl) handle_dict = plot_examples.plot_one_example( list_of_predictor_matrices=mean_radar_matrices, model_metadata_dict=model_metadata_dict, pmm_flag=True, plot_sounding=False, allow_whitespace=True, plot_panel_names=True, panel_name_font_size=PANEL_NAME_FONT_SIZE, add_titles=False, label_colour_bars=True, colour_bar_length=COLOUR_BAR_LENGTH, colour_bar_font_size=COLOUR_BAR_FONT_SIZE, num_panel_rows=num_refl_heights) axes_object_matrices = handle_dict[plot_examples.RADAR_AXES_KEY] this_saliency_matrix = numpy.flip(mean_saliency_matrices[0][0, ..., 0], axis=0) saliency_plotting.plot_many_2d_grids_with_contours( saliency_matrix_3d=this_saliency_matrix, axes_object_matrix=axes_object_matrices[0], colour_map_object=colour_map_object, max_absolute_contour_level=max_colour_value, contour_interval=max_colour_value / half_num_contours, row_major=True) this_sig_matrix = numpy.flip(significance_matrices[0][0, ..., 0], axis=0) significance_plotting.plot_many_2d_grids_without_coords( significance_matrix=this_sig_matrix, axes_object_matrix=axes_object_matrices[0], marker_size=2, row_major=True) this_saliency_matrix = numpy.flip(mean_saliency_matrices[1][0, ...], axis=0) saliency_plotting.plot_many_2d_grids_with_contours( saliency_matrix_3d=this_saliency_matrix, axes_object_matrix=axes_object_matrices[1], colour_map_object=colour_map_object, max_absolute_contour_level=max_colour_value, contour_interval=max_colour_value / half_num_contours, row_major=False) this_sig_matrix = numpy.flip(significance_matrices[1][0, ...], axis=0) significance_plotting.plot_many_2d_grids_without_coords( significance_matrix=this_sig_matrix, axes_object_matrix=axes_object_matrices[1], marker_size=2, row_major=False) refl_figure_object = handle_dict[plot_examples.RADAR_FIGURES_KEY][0] refl_figure_file_name = '{0:s}/{1:s}_reflectivity.jpg'.format( output_dir_name, composite_name_abbrev) print('Saving figure to: "{0:s}"...'.format(refl_figure_file_name)) refl_figure_object.savefig(refl_figure_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(refl_figure_object) shear_figure_object = handle_dict[plot_examples.RADAR_FIGURES_KEY][1] shear_figure_file_name = '{0:s}/{1:s}_shear.jpg'.format( output_dir_name, composite_name_abbrev) print('Saving figure to: "{0:s}"...'.format(shear_figure_file_name)) shear_figure_object.savefig(shear_figure_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(shear_figure_object) main_figure_file_name = '{0:s}/{1:s}_saliency.jpg'.format( output_dir_name, composite_name_abbrev) print('Concatenating panels to: "{0:s}"...'.format(main_figure_file_name)) imagemagick_utils.concatenate_images( input_file_names=[refl_figure_file_name, shear_figure_file_name], output_file_name=main_figure_file_name, num_panel_rows=1, num_panel_columns=2, border_width_pixels=50, extra_args_string='-gravity south') imagemagick_utils.resize_image(input_file_name=main_figure_file_name, output_file_name=main_figure_file_name, output_size_pixels=CONCAT_FIGURE_SIZE_PX) imagemagick_utils.trim_whitespace(input_file_name=main_figure_file_name, output_file_name=main_figure_file_name, border_width_pixels=TITLE_FONT_SIZE + 25) _overlay_text(image_file_name=main_figure_file_name, x_offset_from_center_px=0, y_offset_from_top_px=0, text_string=composite_name_verbose) imagemagick_utils.trim_whitespace(input_file_name=main_figure_file_name, output_file_name=main_figure_file_name, border_width_pixels=10) return main_figure_file_name
def _plot_3d_radar_saliency( saliency_matrix, colour_map_object, max_colour_value, figure_objects, axes_object_matrices, model_metadata_dict, output_dir_name, significance_matrix=None, full_storm_id_string=None, storm_time_unix_sec=None): """Plots saliency map for 3-D radar data. M = number of rows in spatial grid N = number of columns in spatial grid H = number of heights in spatial grid F = number of radar fields If this method is plotting a composite rather than single example (storm object), `full_storm_id_string` and `storm_time_unix_sec` can be None. :param saliency_matrix: M-by-N-by-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 figure_objects: See doc for `plot_input_examples._plot_3d_radar_scan`. :param axes_object_matrices: Same. :param model_metadata_dict: Dictionary returned by `cnn.read_model_metadata`. :param output_dir_name: Path to output directory. Figure(s) will be saved here. :param significance_matrix: M-by-N-by-H-by-F numpy array of Boolean flags, indicating where differences with some other saliency map are significant. :param full_storm_id_string: Full storm ID. :param storm_time_unix_sec: Storm time. """ pmm_flag = full_storm_id_string is None and storm_time_unix_sec is None conv_2d3d = model_metadata_dict[cnn.CONV_2D3D_KEY] if conv_2d3d: loop_max = 1 radar_field_names = ['reflectivity'] else: loop_max = len(figure_objects) training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY] radar_field_names = training_option_dict[trainval_io.RADAR_FIELDS_KEY] for j in range(loop_max): saliency_plotting.plot_many_2d_grids_with_contours( saliency_matrix_3d=numpy.flip(saliency_matrix[..., j], axis=0), axes_object_matrix=axes_object_matrices[j], colour_map_object=colour_map_object, max_absolute_contour_level=max_colour_value, contour_interval=max_colour_value / HALF_NUM_CONTOURS) if significance_matrix is not None: this_matrix = numpy.flip(significance_matrix[..., j], axis=0) significance_plotting.plot_many_2d_grids_without_coords( significance_matrix=this_matrix, axes_object_matrix=axes_object_matrices[j] ) this_title_object = figure_objects[j]._suptitle if this_title_object is not None: this_title_string = '{0:s} (max abs saliency = {1:.2e})'.format( this_title_object.get_text(), max_colour_value ) figure_objects[j].suptitle( this_title_string, fontsize=plot_input_examples.TITLE_FONT_SIZE) this_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=radar_field_names[j] ) print('Saving figure to: "{0:s}"...'.format(this_file_name)) figure_objects[j].savefig( this_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) pyplot.close(figure_objects[j])
def _plot_2d_radar_saliency( saliency_matrix, colour_map_object, max_colour_value, half_num_contours, label_colour_bars, colour_bar_length, figure_objects, axes_object_matrices, model_metadata_dict, output_dir_name, significance_matrix=None, full_storm_id_string=None, storm_time_unix_sec=None): """Plots saliency map for 2-D radar data. M = number of rows in spatial grid N = number of columns in spatial grid C = number of radar channels If this method is plotting a composite rather than single example (storm object), `full_storm_id_string` and `storm_time_unix_sec` can be None. :param saliency_matrix: M-by-N-by-C numpy array of saliency values. :param colour_map_object: See documentation at top of file. :param max_colour_value: Same. :param half_num_contours: Same. :param label_colour_bars: Same. :param colour_bar_length: Same. :param figure_objects: See doc for `plot_input_examples._plot_2d_radar_scan`. :param axes_object_matrices: Same. :param model_metadata_dict: Dictionary returned by `cnn.read_model_metadata`. :param output_dir_name: Path to output directory. Figure(s) will be saved here. :param significance_matrix: M-by-N-by-H numpy array of Boolean flags, indicating where differences with some other saliency map are significant. :param full_storm_id_string: Full storm ID. :param storm_time_unix_sec: Storm time. """ if max_colour_value is None: max_colour_value = numpy.percentile( numpy.absolute(saliency_matrix), MAX_COLOUR_PERCENTILE ) pmm_flag = full_storm_id_string is None and storm_time_unix_sec is None conv_2d3d = model_metadata_dict[cnn.CONV_2D3D_KEY] if conv_2d3d: figure_index = 1 radar_field_name = 'shear' else: figure_index = 0 radar_field_name = None saliency_plotting.plot_many_2d_grids_with_contours( saliency_matrix_3d=numpy.flip(saliency_matrix, axis=0), axes_object_matrix=axes_object_matrices[figure_index], colour_map_object=colour_map_object, max_absolute_contour_level=max_colour_value, contour_interval=max_colour_value / half_num_contours, row_major=False) if significance_matrix is not None: significance_plotting.plot_many_2d_grids_without_coords( significance_matrix=numpy.flip(significance_matrix, axis=0), axes_object_matrix=axes_object_matrices[figure_index], row_major=False) colour_bar_object = plotting_utils.plot_linear_colour_bar( axes_object_or_matrix=axes_object_matrices[figure_index], data_matrix=saliency_matrix, colour_map_object=colour_map_object, min_value=0., max_value=max_colour_value, orientation_string='horizontal', fraction_of_axis_length=colour_bar_length / (1 + int(conv_2d3d)), extend_min=False, extend_max=True, font_size=COLOUR_BAR_FONT_SIZE) if label_colour_bars: colour_bar_object.set_label( 'Absolute saliency', fontsize=COLOUR_BAR_FONT_SIZE) output_file_name = plot_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=radar_field_name) print('Saving figure to: "{0:s}"...'.format(output_file_name)) figure_objects[figure_index].savefig( output_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) pyplot.close(figure_objects[figure_index])
def _plot_one_composite(saliency_file_name, monte_carlo_file_name, composite_name_abbrev, composite_name_verbose, colour_map_object, max_colour_value, half_num_contours, smoothing_radius_grid_cells, output_dir_name): """Plots saliency map for one composite. :param saliency_file_name: Path to saliency file (will be read by `saliency.read_file`). :param monte_carlo_file_name: Path to Monte Carlo file (will be read by `_read_monte_carlo_file`). :param composite_name_abbrev: Abbrev composite name (will be used in file names). :param composite_name_verbose: Verbose composite name (will be used in figure title). :param colour_map_object: See documentation at top of file. :param max_colour_value: Max value in colour bar (may be NaN). :param half_num_contours: See documentation at top of file. :param smoothing_radius_grid_cells: Same. :param output_dir_name: Name of output directory (figures will be saved here). :return: main_figure_file_name: Path to main image file created by this method. :return: max_colour_value: Same as input but cannot be None. """ (mean_radar_matrix, mean_saliency_matrix, significance_matrix, model_metadata_dict) = _read_one_composite( saliency_file_name=saliency_file_name, smoothing_radius_grid_cells=smoothing_radius_grid_cells, monte_carlo_file_name=monte_carlo_file_name) training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY] field_names = training_option_dict[trainval_io.RADAR_FIELDS_KEY] num_fields = mean_radar_matrix.shape[-1] num_heights = mean_radar_matrix.shape[-2] if numpy.isnan(max_colour_value): max_colour_value = numpy.percentile( numpy.absolute(mean_saliency_matrix[0, ...]), 99.) these_indices = numpy.where( max_colour_value <= POSSIBLE_MAX_COLOUR_VALUES)[0] if len(these_indices) == 0: this_index = -1 else: this_index = these_indices[0] this_index -= 1 max_colour_value = POSSIBLE_MAX_COLOUR_VALUES[this_index] handle_dict = plot_examples.plot_one_example( list_of_predictor_matrices=[mean_radar_matrix], model_metadata_dict=model_metadata_dict, pmm_flag=True, allow_whitespace=True, plot_panel_names=True, panel_name_font_size=PANEL_NAME_FONT_SIZE, add_titles=False, label_colour_bars=True, colour_bar_length=COLOUR_BAR_LENGTH, colour_bar_font_size=COLOUR_BAR_FONT_SIZE, num_panel_rows=num_heights) figure_objects = handle_dict[plot_examples.RADAR_FIGURES_KEY] axes_object_matrices = handle_dict[plot_examples.RADAR_AXES_KEY] for k in range(num_fields): this_saliency_matrix = mean_saliency_matrix[0, ..., k] saliency_plotting.plot_many_2d_grids_with_contours( saliency_matrix_3d=numpy.flip(this_saliency_matrix, axis=0), axes_object_matrix=axes_object_matrices[k], colour_map_object=colour_map_object, max_absolute_contour_level=max_colour_value, contour_interval=max_colour_value / half_num_contours) this_sig_matrix = significance_matrix[0, ..., k] significance_plotting.plot_many_2d_grids_without_coords( significance_matrix=numpy.flip(this_sig_matrix, axis=0), axes_object_matrix=axes_object_matrices[k]) panel_file_names = [None] * num_fields for k in range(num_fields): panel_file_names[k] = '{0:s}/{1:s}_{2:s}.jpg'.format( output_dir_name, composite_name_abbrev, field_names[k].replace('_', '-')) print('Saving figure to: "{0:s}"...'.format(panel_file_names[k])) figure_objects[k].savefig(panel_file_names[k], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_objects[k]) main_figure_file_name = '{0:s}/{1:s}_saliency.jpg'.format( output_dir_name, composite_name_abbrev) print('Concatenating panels to: "{0:s}"...'.format(main_figure_file_name)) imagemagick_utils.concatenate_images( input_file_names=panel_file_names, output_file_name=main_figure_file_name, num_panel_rows=1, num_panel_columns=num_fields, border_width_pixels=50) imagemagick_utils.resize_image(input_file_name=main_figure_file_name, output_file_name=main_figure_file_name, output_size_pixels=CONCAT_FIGURE_SIZE_PX) imagemagick_utils.trim_whitespace(input_file_name=main_figure_file_name, output_file_name=main_figure_file_name, border_width_pixels=TITLE_FONT_SIZE + 25) _overlay_text(image_file_name=main_figure_file_name, x_offset_from_center_px=0, y_offset_from_top_px=0, text_string=composite_name_verbose) imagemagick_utils.trim_whitespace(input_file_name=main_figure_file_name, output_file_name=main_figure_file_name, border_width_pixels=10) return main_figure_file_name, max_colour_value
def _plot_one_composite(gradcam_file_name, monte_carlo_file_name, composite_name_abbrev, composite_name_verbose, colour_map_object, min_colour_value, max_colour_value, num_contours, smoothing_radius_grid_cells, monte_carlo_max_fdr, output_dir_name): """Plots class-activation map for one composite. :param gradcam_file_name: Path to input file (will be read by `gradcam.read_file`). :param monte_carlo_file_name: Path to Monte Carlo file (will be read by `_read_monte_carlo_file`). :param composite_name_abbrev: Abbrev composite name (will be used in file names). :param composite_name_verbose: Verbose composite name (will be used in figure title). :param colour_map_object: See documentation at top of file. :param min_colour_value: Minimum value in colour bar (may be NaN). :param max_colour_value: Max value in colour bar (may be NaN). :param num_contours: See documentation at top of file. :param smoothing_radius_grid_cells: Same. :param monte_carlo_max_fdr: Same. :param output_dir_name: Name of output directory (figures will be saved here). :return: main_figure_file_name: Path to main image file created by this method. :return: min_colour_value: Same as input but cannot be None. :return: max_colour_value: Same as input but cannot be None. """ (mean_radar_matrix, mean_class_activn_matrix, significance_matrix, model_metadata_dict) = _read_one_composite( gradcam_file_name=gradcam_file_name, smoothing_radius_grid_cells=smoothing_radius_grid_cells, monte_carlo_file_name=monte_carlo_file_name, monte_carlo_max_fdr=monte_carlo_max_fdr) if numpy.isnan(min_colour_value) or numpy.isnan(max_colour_value): min_colour_value_log10 = numpy.log10( numpy.percentile(mean_class_activn_matrix, 1.)) max_colour_value_log10 = numpy.log10( numpy.percentile(mean_class_activn_matrix, 99.)) min_colour_value_log10 = max([min_colour_value_log10, -2.]) max_colour_value_log10 = max([max_colour_value_log10, -1.]) min_colour_value_log10 = min([min_colour_value_log10, 1.]) max_colour_value_log10 = min([max_colour_value_log10, 2.]) min_colour_value = 10**min_colour_value_log10 max_colour_value = 10**max_colour_value_log10 else: min_colour_value_log10 = numpy.log10(min_colour_value) max_colour_value_log10 = numpy.log10(max_colour_value) contour_interval_log10 = ( (max_colour_value_log10 - min_colour_value_log10) / (num_contours - 1)) mean_activn_matrix_log10 = numpy.log10(mean_class_activn_matrix) training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY] field_names = training_option_dict[trainval_io.RADAR_FIELDS_KEY] num_fields = mean_radar_matrix.shape[-1] num_heights = mean_radar_matrix.shape[-2] handle_dict = plot_examples.plot_one_example( list_of_predictor_matrices=[mean_radar_matrix], model_metadata_dict=model_metadata_dict, pmm_flag=True, allow_whitespace=True, plot_panel_names=True, panel_name_font_size=PANEL_NAME_FONT_SIZE, add_titles=False, label_colour_bars=True, colour_bar_length=COLOUR_BAR_LENGTH, colour_bar_font_size=COLOUR_BAR_FONT_SIZE, num_panel_rows=num_heights) figure_objects = handle_dict[plot_examples.RADAR_FIGURES_KEY] axes_object_matrices = handle_dict[plot_examples.RADAR_AXES_KEY] for k in range(num_fields): cam_plotting.plot_many_2d_grids( class_activation_matrix_3d=numpy.flip( mean_activn_matrix_log10[0, ...], axis=0), axes_object_matrix=axes_object_matrices[k], colour_map_object=colour_map_object, min_contour_level=min_colour_value_log10, max_contour_level=max_colour_value_log10, contour_interval=contour_interval_log10) significance_plotting.plot_many_2d_grids_without_coords( significance_matrix=numpy.flip(significance_matrix[0, ...], axis=0), axes_object_matrix=axes_object_matrices[k]) panel_file_names = [None] * num_fields for k in range(num_fields): panel_file_names[k] = '{0:s}/{1:s}_{2:s}.jpg'.format( output_dir_name, composite_name_abbrev, field_names[k].replace('_', '-')) print('Saving figure to: "{0:s}"...'.format(panel_file_names[k])) figure_objects[k].savefig(panel_file_names[k], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_objects[k]) main_figure_file_name = '{0:s}/{1:s}_gradcam.jpg'.format( output_dir_name, composite_name_abbrev) print('Concatenating panels to: "{0:s}"...'.format(main_figure_file_name)) imagemagick_utils.concatenate_images( input_file_names=panel_file_names, output_file_name=main_figure_file_name, num_panel_rows=1, num_panel_columns=num_fields, border_width_pixels=50) imagemagick_utils.resize_image(input_file_name=main_figure_file_name, output_file_name=main_figure_file_name, output_size_pixels=CONCAT_FIGURE_SIZE_PX) imagemagick_utils.trim_whitespace(input_file_name=main_figure_file_name, output_file_name=main_figure_file_name, border_width_pixels=TITLE_FONT_SIZE + 25) _overlay_text(image_file_name=main_figure_file_name, x_offset_from_center_px=0, y_offset_from_top_px=0, text_string=composite_name_verbose) imagemagick_utils.trim_whitespace(input_file_name=main_figure_file_name, output_file_name=main_figure_file_name, border_width_pixels=10) return main_figure_file_name, min_colour_value, max_colour_value
def _plot_3d_radar_difference(difference_matrix, colour_map_object, max_colour_percentile, model_metadata_dict, backwards_opt_dict, output_dir_name, example_index=None, significance_matrix=None): """Plots difference (after minus before optimization) for 3-D radar data. M = number of rows in spatial grid N = number of columns in spatial grid H = number of heights in spatial grid F = number of fields :param difference_matrix: M-by-N-by-H-by-F numpy array of differences (after minus before optimization). :param colour_map_object: See documentation at top of file. :param max_colour_percentile: Same. :param model_metadata_dict: Dictionary returned by `cnn.read_model_metadata`. :param backwards_opt_dict: Dictionary returned by `backwards_optimization.read_standard_file` or `backwards_optimization.read_pmm_file`, containing metadata. :param output_dir_name: Name of output directory. Figure(s) will be saved here. :param example_index: This method will plot only the [i]th example, where i = `example_index`. This will be used to find metadata for the given example in `backwards_opt_dict`. If `backwards_opt_dict` contains PMM (probability-matched means), leave this argument alone. :param significance_matrix: M-by-N-by-H-by-F numpy array of Boolean flags, indicating where these differences are significantly different than differences from another backwards optimization. """ training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY] radar_heights_m_agl = training_option_dict[trainval_io.RADAR_HEIGHTS_KEY] num_heights = len(radar_heights_m_agl) num_panel_rows = int(numpy.floor(numpy.sqrt(num_heights))) pmm_flag = backwards_opt.MEAN_FINAL_ACTIVATION_KEY in backwards_opt_dict if pmm_flag: initial_activation = backwards_opt_dict[ backwards_opt.MEAN_INITIAL_ACTIVATION_KEY] final_activation = backwards_opt_dict[ backwards_opt.MEAN_FINAL_ACTIVATION_KEY] full_storm_id_string = None storm_time_string = None else: initial_activation = backwards_opt_dict[ backwards_opt.INITIAL_ACTIVATIONS_KEY][example_index] final_activation = backwards_opt_dict[ backwards_opt.FINAL_ACTIVATIONS_KEY][example_index] full_storm_id_string = backwards_opt_dict[ backwards_opt.FULL_IDS_KEY][example_index] storm_time_string = time_conversion.unix_sec_to_string( backwards_opt_dict[backwards_opt.STORM_TIMES_KEY][example_index], plot_input_examples.TIME_FORMAT) conv_2d3d = model_metadata_dict[cnn.CONV_2D3D_KEY] if conv_2d3d: radar_field_names = [radar_utils.REFL_NAME] else: radar_field_names = training_option_dict[trainval_io.RADAR_FIELDS_KEY] num_fields = len(radar_field_names) for j in range(num_fields): this_max_colour_value = numpy.percentile( numpy.absolute(difference_matrix[..., j]), max_colour_percentile) this_colour_norm_object = matplotlib.colors.Normalize( vmin=-1 * this_max_colour_value, vmax=this_max_colour_value, clip=False) # TODO(thunderhoser): Deal with change of units. this_figure_object, this_axes_object_matrix = ( radar_plotting.plot_3d_grid_without_coords( field_matrix=numpy.flip(difference_matrix[..., j], axis=0), field_name=radar_field_names[j], grid_point_heights_metres=radar_heights_m_agl, ground_relative=True, num_panel_rows=num_panel_rows, font_size=FONT_SIZE_SANS_COLOUR_BARS, colour_map_object=colour_map_object, colour_norm_object=this_colour_norm_object)) if significance_matrix is not None: this_matrix = numpy.flip(significance_matrix[..., j], axis=0) significance_plotting.plot_many_2d_grids_without_coords( significance_matrix=this_matrix, axes_object_matrix=this_axes_object_matrix) plotting_utils.plot_colour_bar( axes_object_or_matrix=this_axes_object_matrix, data_matrix=difference_matrix[..., j], colour_map_object=colour_map_object, colour_norm_object=this_colour_norm_object, orientation_string='horizontal', extend_min=True, extend_max=True) if pmm_flag: this_title_string = 'PMM' else: this_title_string = 'Storm "{0:s}" at {1:s}'.format( full_storm_id_string, storm_time_string) this_title_string += ( '; {0:s}; activation from {1:.2e} to {2:.2e}').format( radar_field_names[j], initial_activation, final_activation) this_figure_object.suptitle(this_title_string, fontsize=TITLE_FONT_SIZE) this_file_name = plot_input_examples.metadata_to_radar_fig_file_name( output_dir_name=output_dir_name, pmm_flag=pmm_flag, full_storm_id_string=full_storm_id_string, storm_time_string=storm_time_string, radar_field_name=radar_field_names[j]) print('Saving figure to: "{0:s}"...'.format(this_file_name)) this_figure_object.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(this_figure_object)
def _plot_2d_radar_difference(difference_matrix, colour_map_object, max_colour_percentile, model_metadata_dict, backwards_opt_dict, output_dir_name, example_index=None, significance_matrix=None): """Plots difference (after minus before optimization) for 2-D radar data. M = number of rows in spatial grid N = number of columns in spatial grid C = number of channels :param difference_matrix: M-by-N-by-C numpy array of differences (after minus before optimization). :param colour_map_object: See doc for `_plot_3d_radar_difference`. :param max_colour_percentile: Same. :param model_metadata_dict: Same. :param backwards_opt_dict: Same. :param output_dir_name: Same. :param example_index: Same. :param significance_matrix: M-by-N-by-C numpy array of Boolean flags, indicating where these differences are significantly different than differences from another backwards optimization. """ pmm_flag = backwards_opt.MEAN_FINAL_ACTIVATION_KEY in backwards_opt_dict if pmm_flag: initial_activation = backwards_opt_dict[ backwards_opt.MEAN_INITIAL_ACTIVATION_KEY] final_activation = backwards_opt_dict[ backwards_opt.MEAN_FINAL_ACTIVATION_KEY] full_storm_id_string = None storm_time_string = None else: initial_activation = backwards_opt_dict[ backwards_opt.INITIAL_ACTIVATIONS_KEY][example_index] final_activation = backwards_opt_dict[ backwards_opt.FINAL_ACTIVATIONS_KEY][example_index] full_storm_id_string = backwards_opt_dict[ backwards_opt.FULL_IDS_KEY][example_index] storm_time_string = time_conversion.unix_sec_to_string( backwards_opt_dict[backwards_opt.STORM_TIMES_KEY][example_index], plot_input_examples.TIME_FORMAT) conv_2d3d = model_metadata_dict[cnn.CONV_2D3D_KEY] training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY] if conv_2d3d: num_fields = len(training_option_dict[trainval_io.RADAR_FIELDS_KEY]) radar_heights_m_agl = numpy.full(num_fields, radar_utils.SHEAR_HEIGHT_M_ASL, dtype=int) else: radar_heights_m_agl = training_option_dict[ trainval_io.RADAR_HEIGHTS_KEY] list_of_layer_operation_dicts = model_metadata_dict[ cnn.LAYER_OPERATIONS_KEY] 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=radar_heights_m_agl) else: field_name_by_panel, panel_names = ( radar_plotting.layer_ops_to_field_and_panel_names( list_of_layer_operation_dicts=list_of_layer_operation_dicts)) num_panels = len(field_name_by_panel) plot_cbar_by_panel = numpy.full(num_panels, True, dtype=bool) cmap_object_by_panel = [colour_map_object] * num_panels cnorm_object_by_panel = [None] * num_panels for j in range(num_panels): this_max_colour_value = numpy.percentile( numpy.absolute(difference_matrix[..., j]), max_colour_percentile) cnorm_object_by_panel[j] = matplotlib.colors.Normalize( vmin=-1 * this_max_colour_value, vmax=this_max_colour_value, clip=False) num_panel_rows = int(numpy.floor(numpy.sqrt(num_panels))) figure_object, axes_object_matrix = ( radar_plotting.plot_many_2d_grids_without_coords( field_matrix=numpy.flip(difference_matrix, axis=0), field_name_by_panel=field_name_by_panel, num_panel_rows=num_panel_rows, panel_names=panel_names, row_major=False, colour_map_object_by_panel=cmap_object_by_panel, colour_norm_object_by_panel=cnorm_object_by_panel, plot_colour_bar_by_panel=plot_cbar_by_panel, font_size=FONT_SIZE_WITH_COLOUR_BARS)) if significance_matrix is not None: significance_plotting.plot_many_2d_grids_without_coords( significance_matrix=numpy.flip(significance_matrix, axis=0), axes_object_matrix=axes_object_matrix, row_major=False) if pmm_flag: this_title_string = 'PMM' else: this_title_string = 'Storm "{0:s}" at {1:s}'.format( full_storm_id_string, storm_time_string) this_title_string += '; activation from {0:.2e} to {1:.2e}'.format( initial_activation, final_activation) figure_object.suptitle(this_title_string, fontsize=TITLE_FONT_SIZE) output_file_name = plot_input_examples.metadata_to_radar_fig_file_name( output_dir_name=output_dir_name, pmm_flag=pmm_flag, full_storm_id_string=full_storm_id_string, storm_time_string=storm_time_string, radar_field_name='shear' if conv_2d3d else None) 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)