def _plot_roc_curves(evaluation_tables, model_names, best_threshold_indices, marker_indices_by_model, output_file_name, plot_best_thresholds, confidence_level=None): """Plots ROC curves (one for each model). M = number of models :param evaluation_tables: length-M list of pandas DataFrames. See `model_evaluation.run_evaluation` for columns in each DataFrame. The only difference is that each table here may have multiple rows (one per bootstrap replicate). :param model_names: length-M list of model names (will be used in legend). :param best_threshold_indices: length-M numpy array with index of best probability threshold for each model. :param marker_indices_by_model: Blah. :param output_file_name: Path to output file (figure will be saved here). :param plot_best_thresholds: See documentation at top of file. :param confidence_level: Confidence level for bootstrapping. """ num_models = len(evaluation_tables) pod_matrices = [None] * num_models pofd_matrices = [None] * num_models legend_strings = [None] * num_models num_bootstrap_reps = None for i in range(num_models): pod_matrices[i] = numpy.vstack( tuple(evaluation_tables[i][ model_eval.POD_BY_THRESHOLD_KEY].values.tolist())) pofd_matrices[i] = numpy.vstack( tuple(evaluation_tables[i][ model_eval.POFD_BY_THRESHOLD_KEY].values.tolist())) if num_bootstrap_reps is None: num_bootstrap_reps = pod_matrices[i].shape[0] this_num_bootstrap_reps = pod_matrices[i].shape[0] # assert num_bootstrap_reps == this_num_bootstrap_reps if num_bootstrap_reps > 1: this_min_auc, this_max_auc = bootstrapping.get_confidence_interval( stat_values=evaluation_tables[i][model_eval.AUC_KEY].values, confidence_level=confidence_level) legend_strings[i] = '{0:s}: AUC = {1:.3f} to {2:.3f}'.format( model_names[i], this_min_auc, this_max_auc) else: this_auc = evaluation_tables[i][model_eval.AUC_KEY].values[0] legend_strings[i] = '{0:s}: AUC = {1:.3f}'.format( model_names[i], this_auc) print(legend_strings[i]) figure_object, axes_object = pyplot.subplots( 1, 1, figsize=(FIGURE_WIDTH_INCHES, FIGURE_HEIGHT_INCHES)) legend_handles = [None] * num_models num_colours = COLOUR_MATRIX.shape[0] for i in range(num_models): this_colour = COLOUR_MATRIX[numpy.mod(i, num_colours), ...] if num_bootstrap_reps == 1: legend_handles[i] = model_eval_plotting.plot_roc_curve( axes_object=axes_object, pod_by_threshold=pod_matrices[i][0, :], pofd_by_threshold=pofd_matrices[i][0, :], line_colour=this_colour, plot_background=i == 0) this_x = pofd_matrices[i][0, best_threshold_indices[i]] this_y = pod_matrices[i][0, best_threshold_indices[i]] these_x = pofd_matrices[i][0, marker_indices_by_model[i]] these_y = pod_matrices[i][0, marker_indices_by_model[i]] else: this_ci_bottom_dict, this_ci_mean_dict, this_ci_top_dict = ( _get_ci_one_model(evaluation_table=evaluation_tables[i], for_roc_curve=True, confidence_level=confidence_level)) legend_handles[ i] = model_eval_plotting.plot_bootstrapped_roc_curve( axes_object=axes_object, ci_bottom_dict=this_ci_bottom_dict, ci_mean_dict=this_ci_mean_dict, ci_top_dict=this_ci_top_dict, line_colour=this_colour, plot_background=i == 0) this_x = this_ci_mean_dict[model_eval.POFD_BY_THRESHOLD_KEY][ best_threshold_indices[i]] this_y = this_ci_mean_dict[model_eval.POD_BY_THRESHOLD_KEY][ best_threshold_indices[i]] these_x = this_ci_mean_dict[model_eval.POFD_BY_THRESHOLD_KEY][ marker_indices_by_model[i]] these_y = this_ci_mean_dict[model_eval.POD_BY_THRESHOLD_KEY][ marker_indices_by_model[i]] print(('POD and POFD at best probability threshold = {0:.3f}, {1:.3f}' ).format(this_y, this_x)) if plot_best_thresholds: axes_object.plot(this_x, this_y, linestyle='None', marker=MARKER_TYPE, markersize=MARKER_SIZE, markeredgewidth=MARKER_EDGE_WIDTH, markerfacecolor=this_colour, markeredgecolor=this_colour) # axes_object.plot( # these_x, these_y, linestyle='None', marker='o', # markersize=12, markeredgewidth=MARKER_EDGE_WIDTH, # markerfacecolor=this_colour, markeredgecolor=this_colour # ) main_legend_handle = axes_object.legend(legend_handles, legend_strings, loc='lower right', bbox_to_anchor=(1, 0), fancybox=True, shadow=False, framealpha=0.5, ncol=1) for this_object in main_legend_handle.legendHandles: this_object.set_linewidth(5.) axes_object.set_title('ROC curve') plotting_utils.label_axes(axes_object=axes_object, label_string='(a)', y_coord_normalized=1.025) axes_object.set_aspect('equal') 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_perf_diagrams(evaluation_tables, model_names, best_threshold_indices, marker_indices_by_model, output_file_name, plot_best_thresholds, confidence_level=None): """Plots performance diagrams (one for each model). :param evaluation_tables: See doc for `_plot_roc_curves`. :param model_names: Same. :param best_threshold_indices: Same. :param marker_indices_by_model: Same. :param output_file_name: Same. :param plot_best_thresholds: Same. :param confidence_level: Same. """ num_models = len(evaluation_tables) pod_matrices = [None] * num_models success_ratio_matrices = [None] * num_models legend_strings = [None] * num_models num_bootstrap_reps = None for i in range(num_models): pod_matrices[i] = numpy.vstack( tuple(evaluation_tables[i][ model_eval.POD_BY_THRESHOLD_KEY].values.tolist())) success_ratio_matrices[i] = numpy.vstack( tuple(evaluation_tables[i][ model_eval.SR_BY_THRESHOLD_KEY].values.tolist())) if num_bootstrap_reps is None: num_bootstrap_reps = pod_matrices[i].shape[0] this_num_bootstrap_reps = pod_matrices[i].shape[0] # assert num_bootstrap_reps == this_num_bootstrap_reps if num_bootstrap_reps > 1: this_min_aupd, this_max_aupd = ( bootstrapping.get_confidence_interval( stat_values=evaluation_tables[i][ model_eval.AUPD_KEY].values, confidence_level=confidence_level)) legend_strings[i] = '{0:s}: AUPD = {1:.3f} to {2:.3f}'.format( model_names[i], this_min_aupd, this_max_aupd) else: this_aupd = evaluation_tables[i][model_eval.AUPD_KEY].values[0] legend_strings[i] = '{0:s}: AUPD = {1:.3f}'.format( model_names[i], this_aupd) print(legend_strings[i]) figure_object, axes_object = pyplot.subplots( 1, 1, figsize=(FIGURE_WIDTH_INCHES, FIGURE_HEIGHT_INCHES)) legend_handles = [None] * num_models num_colours = COLOUR_MATRIX.shape[0] for i in range(num_models): this_colour = COLOUR_MATRIX[numpy.mod(i, num_colours), ...] if num_bootstrap_reps == 1: legend_handles[i] = model_eval_plotting.plot_performance_diagram( axes_object=axes_object, pod_by_threshold=pod_matrices[i][0, :], success_ratio_by_threshold=success_ratio_matrices[i][0, :], line_colour=this_colour, plot_background=i == 0) this_x = success_ratio_matrices[i][0, best_threshold_indices[i]] this_y = pod_matrices[i][0, best_threshold_indices[i]] these_x = success_ratio_matrices[i][0, marker_indices_by_model[i]] these_y = pod_matrices[i][0, marker_indices_by_model[i]] else: this_ci_bottom_dict, this_ci_mean_dict, this_ci_top_dict = ( _get_ci_one_model(evaluation_table=evaluation_tables[i], for_roc_curve=False, confidence_level=confidence_level)) legend_handles[i] = ( model_eval_plotting.plot_bootstrapped_performance_diagram( axes_object=axes_object, ci_bottom_dict=this_ci_bottom_dict, ci_mean_dict=this_ci_mean_dict, ci_top_dict=this_ci_top_dict, line_colour=this_colour, plot_background=i == 0)) this_x = this_ci_mean_dict[model_eval.SR_BY_THRESHOLD_KEY][ best_threshold_indices[i]] this_y = this_ci_mean_dict[model_eval.POD_BY_THRESHOLD_KEY][ best_threshold_indices[i]] these_x = this_ci_mean_dict[model_eval.SR_BY_THRESHOLD_KEY][ marker_indices_by_model[i]] these_y = this_ci_mean_dict[model_eval.POD_BY_THRESHOLD_KEY][ marker_indices_by_model[i]] this_csi = model_eval.csi_from_sr_and_pod( success_ratio_array=numpy.array([this_x]), pod_array=numpy.array([this_y]))[0] print(('POD, success ratio, and CSI at best probability threshold = ' '{0:.3f}, {1:.3f}, {2:.3f}').format(this_y, this_x, this_csi)) if plot_best_thresholds: axes_object.plot(this_x, this_y, linestyle='None', marker=MARKER_TYPE, markersize=MARKER_SIZE, markeredgewidth=MARKER_EDGE_WIDTH, markerfacecolor=this_colour, markeredgecolor=this_colour) # axes_object.plot( # these_x, these_y, linestyle='None', marker='o', # markersize=12, markeredgewidth=MARKER_EDGE_WIDTH, # markerfacecolor=this_colour, markeredgecolor=this_colour # ) main_legend_handle = axes_object.legend(legend_handles, legend_strings, loc='upper right', bbox_to_anchor=(1, 1), fancybox=True, shadow=False, framealpha=0.5, ncol=1) for this_object in main_legend_handle.legendHandles: this_object.set_linewidth(5.) axes_object.set_title('Performance diagram') plotting_utils.label_axes(axes_object=axes_object, label_string='(b)', y_coord_normalized=1.025) axes_object.set_aspect('equal') 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(exp1_permutation_dir_name, exp2_permutation_dir_name, use_forward_test, use_multipass_test, output_file_name): """Creates figure showing permutation-test results for both models. This is effectively the main method. :param exp1_permutation_dir_name: See documentation at top of file. :param exp2_permutation_dir_name: Same. :param use_forward_test: Same. :param use_multipass_test: Same. :param output_file_name: Same. """ file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name) exp1_flux_file_name = '{0:s}/{1:s}_perm_test_fluxes-only.nc'.format( exp1_permutation_dir_name, 'forward' if use_forward_test else 'backwards') exp1_heating_rate_file_name = '{0:s}/{1:s}_perm_test_hr-only.nc'.format( exp1_permutation_dir_name, 'forward' if use_forward_test else 'backwards') exp2_flux_file_name = '{0:s}/{1:s}_perm_test_fluxes-only.nc'.format( exp2_permutation_dir_name, 'forward' if use_forward_test else 'backwards') exp2_heating_rate_file_name = '{0:s}/{1:s}_perm_test_hr-only.nc'.format( exp2_permutation_dir_name, 'forward' if use_forward_test else 'backwards') print('Reading data from: "{0:s}"...'.format(exp1_heating_rate_file_name)) exp1_heating_permutation_dict = ml4rt_permutation.read_file( exp1_heating_rate_file_name) exp1_heating_permutation_dict = _results_to_gg_format( exp1_heating_permutation_dict) figure_object, axes_object_matrix = plotting_utils.create_paneled_figure( num_rows=2, num_columns=2, shared_x_axis=False, shared_y_axis=True, keep_aspect_ratio=False, horizontal_spacing=0.25, vertical_spacing=0.25) if use_multipass_test: permutation_plotting.plot_multipass_test( permutation_dict=exp1_heating_permutation_dict, axes_object=axes_object_matrix[0, 0], plot_percent_increase=False, confidence_level=CONFIDENCE_LEVEL) else: permutation_plotting.plot_single_pass_test( permutation_dict=exp1_heating_permutation_dict, axes_object=axes_object_matrix[0, 0], plot_percent_increase=False, confidence_level=CONFIDENCE_LEVEL) plotting_utils.label_axes(axes_object=axes_object_matrix[0, 0], label_string='(a)', font_size=30, x_coord_normalized=0.1, y_coord_normalized=1.01) axes_object_matrix[0, 0].set_title('Exp 1, heating rates only') axes_object_matrix[0, 0].set_xlabel(r'Dual-weighted MSE (K$^3$ day$^{-3}$)') axes_object_matrix[0, 0].set_ylabel('') print('Reading data from: "{0:s}"...'.format(exp1_flux_file_name)) exp1_flux_permutation_dict = ml4rt_permutation.read_file( exp1_flux_file_name) exp1_flux_permutation_dict = _results_to_gg_format( exp1_flux_permutation_dict) if use_multipass_test: permutation_plotting.plot_multipass_test( permutation_dict=exp1_flux_permutation_dict, axes_object=axes_object_matrix[0, 1], plot_percent_increase=False, confidence_level=CONFIDENCE_LEVEL) else: permutation_plotting.plot_single_pass_test( permutation_dict=exp1_flux_permutation_dict, axes_object=axes_object_matrix[0, 1], plot_percent_increase=False, confidence_level=CONFIDENCE_LEVEL) plotting_utils.label_axes(axes_object=axes_object_matrix[0, 1], label_string='(b)', font_size=30, x_coord_normalized=0.1, y_coord_normalized=1.01) axes_object_matrix[0, 1].set_title('Exp 1, fluxes only') axes_object_matrix[0, 1].set_xlabel(r'MSE (K day$^{-1}$)') axes_object_matrix[0, 1].set_ylabel('') print('Reading data from: "{0:s}"...'.format(exp2_heating_rate_file_name)) exp2_heating_permutation_dict = ml4rt_permutation.read_file( exp2_heating_rate_file_name) exp2_heating_permutation_dict = _results_to_gg_format( exp2_heating_permutation_dict) if use_multipass_test: permutation_plotting.plot_multipass_test( permutation_dict=exp2_heating_permutation_dict, axes_object=axes_object_matrix[1, 0], plot_percent_increase=False, confidence_level=CONFIDENCE_LEVEL) else: permutation_plotting.plot_single_pass_test( permutation_dict=exp2_heating_permutation_dict, axes_object=axes_object_matrix[1, 0], plot_percent_increase=False, confidence_level=CONFIDENCE_LEVEL) plotting_utils.label_axes(axes_object=axes_object_matrix[1, 0], label_string='(c)', font_size=30, x_coord_normalized=0.1, y_coord_normalized=1.01) axes_object_matrix[1, 0].set_title('Exp 2, heating rates only') axes_object_matrix[1, 0].set_xlabel(r'Dual-weighted MSE (K$^3$ day$^{-3}$)') axes_object_matrix[1, 0].set_ylabel('') print('Reading data from: "{0:s}"...'.format(exp2_flux_file_name)) exp2_flux_permutation_dict = ml4rt_permutation.read_file( exp2_flux_file_name) exp2_flux_permutation_dict = _results_to_gg_format( exp2_flux_permutation_dict) if use_multipass_test: permutation_plotting.plot_multipass_test( permutation_dict=exp2_flux_permutation_dict, axes_object=axes_object_matrix[1, 1], plot_percent_increase=False, confidence_level=CONFIDENCE_LEVEL) else: permutation_plotting.plot_single_pass_test( permutation_dict=exp2_flux_permutation_dict, axes_object=axes_object_matrix[1, 1], plot_percent_increase=False, confidence_level=CONFIDENCE_LEVEL) plotting_utils.label_axes(axes_object=axes_object_matrix[1, 1], label_string='(d)', font_size=30, x_coord_normalized=0.1, y_coord_normalized=1.01) axes_object_matrix[1, 1].set_title('Exp 2, fluxes only') axes_object_matrix[1, 1].set_xlabel(r'MSE (K day$^{-1}$)') axes_object_matrix[1, 1].set_ylabel('') 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(): """Makes storm-tracking schematics for 2019 prediction paper. This is effectively the main method. """ file_system_utils.mkdir_recursive_if_necessary( directory_name=OUTPUT_DIR_NAME) # Linkage with extrapolation. figure_object, axes_object = _make_linkage_schema(True) this_file_name = '{0:s}/linkage_with_extrap_standalone.jpg'.format( OUTPUT_DIR_NAME) print('Saving figure to: "{0:s}"...'.format(this_file_name)) figure_object.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') plotting_utils.label_axes(axes_object=axes_object, label_string='(a)') axes_object.set_title('Linkage with extrapolation') panel_file_names = [ '{0:s}/linkage_with_extrap.jpg'.format(OUTPUT_DIR_NAME) ] print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Linkage without extrapolation. figure_object, axes_object = _make_linkage_schema(False) this_file_name = '{0:s}/linkage_sans_extrap_standalone.jpg'.format( OUTPUT_DIR_NAME) print('Saving figure to: "{0:s}"...'.format(this_file_name)) figure_object.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') plotting_utils.label_axes(axes_object=axes_object, label_string='(b)') axes_object.set_title('Linkage without extrapolation') panel_file_names.append( '{0:s}/linkage_sans_extrap.jpg'.format(OUTPUT_DIR_NAME)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Pruning with 3-way split. figure_object, axes_object = _make_3way_split_schema() axes_object.set_title('Pruning with 3-way split') this_file_name = '{0:s}/pruning_3way_split_standalone.jpg'.format( OUTPUT_DIR_NAME) print('Saving figure to: "{0:s}"...'.format(this_file_name)) figure_object.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') plotting_utils.label_axes(axes_object=axes_object, label_string='(c)') panel_file_names.append( '{0:s}/pruning_3way_split.jpg'.format(OUTPUT_DIR_NAME)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Pruning with hybrid split and merger. figure_object, axes_object = _make_splitmerge_schema() axes_object.set_title('Pruning with hybrid split and merger') this_file_name = '{0:s}/pruning_splitmerge_standalone.jpg'.format( OUTPUT_DIR_NAME) print('Saving figure to: "{0:s}"...'.format(this_file_name)) figure_object.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') plotting_utils.label_axes(axes_object=axes_object, label_string='(d)') panel_file_names.append( '{0:s}/pruning_splitmerge.jpg'.format(OUTPUT_DIR_NAME)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Concatenate all panels into one figure. concat_file_name = '{0:s}/tracking_schemas.jpg'.format(OUTPUT_DIR_NAME) print('Concatenating panels to: "{0:s}"...'.format(concat_file_name)) imagemagick_utils.concatenate_images(input_file_names=panel_file_names, output_file_name=concat_file_name, num_panel_rows=2, num_panel_columns=2) imagemagick_utils.resize_image(input_file_name=concat_file_name, output_file_name=concat_file_name, output_size_pixels=CONCAT_FIGURE_SIZE_PX)
def _run(evaluation_dir_name, smoothing_radius_grid_cells, score_colour_map_name, num_ex_colour_map_name, max_colour_percentile, output_dir_name): """Plots spatially subset model evaluation. This is effectively the main method. :param evaluation_dir_name: See documentation at top of file. :param smoothing_radius_grid_cells: Same. :param score_colour_map_name: Same. :param num_ex_colour_map_name: Same. :param max_colour_percentile: Same. :param output_dir_name: Same. """ if smoothing_radius_grid_cells <= 0: smoothing_radius_grid_cells = None score_colour_map_object = pyplot.get_cmap(score_colour_map_name) num_ex_colour_map_object = pyplot.get_cmap(num_ex_colour_map_name) error_checking.assert_is_geq(max_colour_percentile, 90.) error_checking.assert_is_leq(max_colour_percentile, 100.) grid_metafile_name = grids.find_equidistant_metafile( directory_name=evaluation_dir_name, raise_error_if_missing=True) print('Reading grid metadata from: "{0:s}"...'.format(grid_metafile_name)) grid_metadata_dict = grids.read_equidistant_metafile(grid_metafile_name) print(SEPARATOR_STRING) num_grid_rows = len(grid_metadata_dict[grids.Y_COORDS_KEY]) num_grid_columns = len(grid_metadata_dict[grids.X_COORDS_KEY]) auc_matrix = numpy.full((num_grid_rows, num_grid_columns), numpy.nan) csi_matrix = numpy.full((num_grid_rows, num_grid_columns), numpy.nan) pod_matrix = numpy.full((num_grid_rows, num_grid_columns), numpy.nan) far_matrix = numpy.full((num_grid_rows, num_grid_columns), numpy.nan) num_examples_matrix = numpy.full((num_grid_rows, num_grid_columns), 0, dtype=int) num_positive_examples_matrix = numpy.full( (num_grid_rows, num_grid_columns), 0, dtype=int) for i in range(num_grid_rows): for j in range(num_grid_columns): this_eval_file_name = model_eval.find_file( directory_name=evaluation_dir_name, grid_row=i, grid_column=j, raise_error_if_missing=False) if not os.path.isfile(this_eval_file_name): warning_string = ( 'Cannot find file (this may or may not be a problem). ' 'Expected at: "{0:s}"').format(this_eval_file_name) warnings.warn(warning_string) continue print('Reading data from: "{0:s}"...'.format(this_eval_file_name)) this_evaluation_dict = model_eval.read_evaluation( this_eval_file_name) num_examples_matrix[i, j] = len( this_evaluation_dict[model_eval.OBSERVED_LABELS_KEY]) num_positive_examples_matrix[i, j] = numpy.sum( this_evaluation_dict[model_eval.OBSERVED_LABELS_KEY]) this_evaluation_table = this_evaluation_dict[ model_eval.EVALUATION_TABLE_KEY] auc_matrix[i, j] = numpy.nanmean( this_evaluation_table[model_eval.AUC_KEY].values) csi_matrix[i, j] = numpy.nanmean( this_evaluation_table[model_eval.CSI_KEY].values) pod_matrix[i, j] = numpy.nanmean( this_evaluation_table[model_eval.POD_KEY].values) far_matrix[i, j] = 1. - numpy.nanmean( this_evaluation_table[model_eval.SUCCESS_RATIO_KEY].values) print(SEPARATOR_STRING) auc_matrix[num_positive_examples_matrix == 0] = numpy.nan csi_matrix[num_positive_examples_matrix == 0] = numpy.nan pod_matrix[num_positive_examples_matrix == 0] = numpy.nan far_matrix[num_positive_examples_matrix == 0] = numpy.nan if smoothing_radius_grid_cells is not None: print(( 'Applying Gaussian smoother with e-folding radius of {0:.1f} grid ' 'cells...').format(smoothing_radius_grid_cells)) orig_num_examples_matrix = num_examples_matrix + 0 num_examples_matrix = general_utils.apply_gaussian_filter( input_matrix=num_examples_matrix.astype(float), e_folding_radius_grid_cells=smoothing_radius_grid_cells) num_examples_matrix = numpy.round(num_examples_matrix).astype(int) num_examples_matrix[orig_num_examples_matrix == 0] = 0 # HACK num_positive_examples_matrix = general_utils.apply_gaussian_filter( input_matrix=num_positive_examples_matrix.astype(float), e_folding_radius_grid_cells=smoothing_radius_grid_cells) num_positive_examples_matrix = ( numpy.round(num_positive_examples_matrix).astype(int)) num_positive_examples_matrix[num_examples_matrix == 0] = 0 auc_matrix = general_utils.apply_gaussian_filter( input_matrix=ge_utils.fill_nans(auc_matrix), e_folding_radius_grid_cells=smoothing_radius_grid_cells) csi_matrix = general_utils.apply_gaussian_filter( input_matrix=ge_utils.fill_nans(csi_matrix), e_folding_radius_grid_cells=smoothing_radius_grid_cells) pod_matrix = general_utils.apply_gaussian_filter( input_matrix=ge_utils.fill_nans(pod_matrix), e_folding_radius_grid_cells=smoothing_radius_grid_cells) far_matrix = general_utils.apply_gaussian_filter( input_matrix=ge_utils.fill_nans(far_matrix), e_folding_radius_grid_cells=smoothing_radius_grid_cells) auc_matrix[num_positive_examples_matrix == 0] = numpy.nan csi_matrix[num_positive_examples_matrix == 0] = numpy.nan pod_matrix[num_positive_examples_matrix == 0] = numpy.nan far_matrix[num_positive_examples_matrix == 0] = numpy.nan panel_file_names = [] file_system_utils.mkdir_recursive_if_necessary( directory_name=output_dir_name) # Plot number of examples. this_data_matrix = numpy.maximum(numpy.log10(num_examples_matrix), 0.) this_data_matrix[this_data_matrix == 0] = numpy.nan max_colour_value = numpy.nanpercentile(this_data_matrix, max_colour_percentile) figure_object, axes_object = _plot_one_value( data_matrix=this_data_matrix, grid_metadata_dict=grid_metadata_dict, colour_map_object=num_ex_colour_map_object, min_colour_value=0., max_colour_value=max_colour_value, plot_cbar_min_arrow=False, plot_cbar_max_arrow=True, log_scale=True) axes_object.set_title(r'Number of examples') plotting_utils.label_axes(axes_object=axes_object, label_string='(a)') panel_file_names.append('{0:s}/num_examples.jpg'.format(output_dir_name)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Plot number of positive examples. this_data_matrix = num_positive_examples_matrix.astype(float) this_data_matrix[this_data_matrix == 0] = numpy.nan max_colour_value = numpy.nanpercentile(this_data_matrix, max_colour_percentile) min_colour_value = numpy.nanpercentile(this_data_matrix, 100. - max_colour_percentile) figure_object, axes_object = _plot_one_value( data_matrix=this_data_matrix, grid_metadata_dict=grid_metadata_dict, colour_map_object=num_ex_colour_map_object, min_colour_value=min_colour_value, max_colour_value=max_colour_value, plot_cbar_min_arrow=True, plot_cbar_max_arrow=True) axes_object.set_title('Number of tornadic examples') plotting_utils.label_axes(axes_object=axes_object, label_string='(b)') panel_file_names.append( '{0:s}/num_positive_examples.jpg'.format(output_dir_name)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Plot AUC. max_colour_value = numpy.nanpercentile(auc_matrix, max_colour_percentile) min_colour_value = numpy.maximum( numpy.nanpercentile(auc_matrix, 100. - max_colour_percentile), 0.5) figure_object, axes_object = _plot_one_value( data_matrix=auc_matrix, grid_metadata_dict=grid_metadata_dict, colour_map_object=score_colour_map_object, min_colour_value=min_colour_value, max_colour_value=max_colour_value, plot_cbar_min_arrow=True, plot_cbar_max_arrow=max_colour_value < 1.) axes_object.set_title('AUC (area under ROC curve)') plotting_utils.label_axes(axes_object=axes_object, label_string='(c)') panel_file_names.append('{0:s}/auc.jpg'.format(output_dir_name)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Plot CSI. max_colour_value = numpy.nanpercentile(csi_matrix, max_colour_percentile) min_colour_value = numpy.nanpercentile(csi_matrix, 100. - max_colour_percentile) figure_object, axes_object = _plot_one_value( data_matrix=csi_matrix, grid_metadata_dict=grid_metadata_dict, colour_map_object=score_colour_map_object, min_colour_value=min_colour_value, max_colour_value=max_colour_value, plot_cbar_min_arrow=min_colour_value > 0., plot_cbar_max_arrow=max_colour_value < 1.) axes_object.set_title('CSI (critical success index)') plotting_utils.label_axes(axes_object=axes_object, label_string='(d)') panel_file_names.append('{0:s}/csi.jpg'.format(output_dir_name)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Plot POD. max_colour_value = numpy.nanpercentile(pod_matrix, max_colour_percentile) min_colour_value = numpy.nanpercentile(pod_matrix, 100. - max_colour_percentile) figure_object, axes_object = _plot_one_value( data_matrix=pod_matrix, grid_metadata_dict=grid_metadata_dict, colour_map_object=score_colour_map_object, min_colour_value=min_colour_value, max_colour_value=max_colour_value, plot_cbar_min_arrow=min_colour_value > 0., plot_cbar_max_arrow=max_colour_value < 1.) axes_object.set_title('POD (probability of detection)') plotting_utils.label_axes(axes_object=axes_object, label_string='(e)') panel_file_names.append('{0:s}/pod.jpg'.format(output_dir_name)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Plot FAR. max_colour_value = numpy.nanpercentile(far_matrix, max_colour_percentile) min_colour_value = numpy.nanpercentile(far_matrix, 100. - max_colour_percentile) figure_object, axes_object = _plot_one_value( data_matrix=far_matrix, grid_metadata_dict=grid_metadata_dict, colour_map_object=score_colour_map_object, min_colour_value=min_colour_value, max_colour_value=max_colour_value, plot_cbar_min_arrow=min_colour_value > 0., plot_cbar_max_arrow=max_colour_value < 1.) axes_object.set_title('FAR (false-alarm ratio)') plotting_utils.label_axes(axes_object=axes_object, label_string='(f)') panel_file_names.append('{0:s}/far.jpg'.format(output_dir_name)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Concatenate panels. concat_file_name = '{0:s}/spatially_subset_evaluation.jpg'.format( output_dir_name) print('Concatenating panels to: "{0:s}"...'.format(concat_file_name)) imagemagick_utils.concatenate_images(input_file_names=panel_file_names, output_file_name=concat_file_name, num_panel_rows=NUM_PANEL_ROWS, num_panel_columns=NUM_PANEL_COLUMNS) imagemagick_utils.resize_image(input_file_name=concat_file_name, output_file_name=concat_file_name, output_size_pixels=CONCAT_FIGURE_SIZE_PX)
def _run(include_caption, output_dir_name): """Makes animation to explain multivariate convolution. This is effectively the main method. :param include_caption: See documentation at top of file. :param output_dir_name: Same. """ file_system_utils.mkdir_recursive_if_necessary( directory_name=output_dir_name) output_feature_matrix = standalone_utils.do_2d_convolution( feature_matrix=INPUT_FEATURE_MATRIX, kernel_matrix=KERNEL_MATRIX, pad_edges=True, stride_length_px=1) output_feature_matrix = output_feature_matrix[0, ..., 0] num_grid_rows = INPUT_FEATURE_MATRIX.shape[0] num_grid_columns = INPUT_FEATURE_MATRIX.shape[1] image_file_names = [] kernel_width_ratio = float(KERNEL_MATRIX.shape[1]) / num_grid_columns kernel_height_ratio = float(KERNEL_MATRIX.shape[0]) / num_grid_rows for i in range(num_grid_rows): for j in range(num_grid_columns): this_figure_object, this_axes_object_matrix = ( plotting_utils.create_paneled_figure( num_rows=NUM_PANEL_ROWS, num_columns=NUM_PANEL_COLUMNS, horizontal_spacing=0.2, vertical_spacing=0., shared_x_axis=False, shared_y_axis=False, keep_aspect_ratio=True) ) letter_label = None _plot_feature_map( feature_matrix_2d=INPUT_FEATURE_MATRIX[..., 0], kernel_row=i, kernel_column=j, is_output_map=False, axes_object=this_axes_object_matrix[0, 0] ) if letter_label is None: letter_label = 'a' else: letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes( axes_object=this_axes_object_matrix[0, 0], label_string='({0:s})'.format(letter_label), font_size=PANEL_LETTER_FONT_SIZE, y_coord_normalized=1.04, x_coord_normalized=0.1 ) _plot_feature_map( feature_matrix_2d=output_feature_matrix, kernel_row=i, kernel_column=j, is_output_map=True, axes_object=this_axes_object_matrix[0, 2] ) this_bbox_object = this_axes_object_matrix[0, 1].get_position() this_width = kernel_width_ratio * ( this_bbox_object.x1 - this_bbox_object.x0 ) this_height = kernel_height_ratio * ( this_bbox_object.y1 - this_bbox_object.y0 ) this_bbox_object.x0 += 0.5 * this_width this_bbox_object.y0 = ( this_axes_object_matrix[0, 0].get_position().y0 + 0.1 ) this_bbox_object.x1 = this_bbox_object.x0 + this_width this_bbox_object.y1 = this_bbox_object.y0 + this_height this_axes_object_matrix[0, 1].set_position(this_bbox_object) _plot_kernel( kernel_matrix_2d=KERNEL_MATRIX[..., 0, 0], feature_matrix_2d=INPUT_FEATURE_MATRIX[..., 0], feature_row_at_center=i, feature_column_at_center=j, axes_object=this_axes_object_matrix[0, 1] ) letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes( axes_object=this_axes_object_matrix[0, 1], label_string='({0:s})'.format(letter_label), font_size=PANEL_LETTER_FONT_SIZE, y_coord_normalized=1.04, x_coord_normalized=0.2 ) _plot_feature_to_kernel_lines( kernel_matrix_2d=KERNEL_MATRIX[..., 0, 0], feature_matrix_2d=INPUT_FEATURE_MATRIX[..., 0], feature_row_at_center=i, feature_column_at_center=j, kernel_axes_object=this_axes_object_matrix[0, 1], feature_axes_object=this_axes_object_matrix[0, 0] ) letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes( axes_object=this_axes_object_matrix[0, 2], label_string='({0:s})'.format(letter_label), font_size=PANEL_LETTER_FONT_SIZE, y_coord_normalized=1.04, x_coord_normalized=0.1 ) if include_caption: this_figure_object.text( 0.5, 0.35, FIGURE_CAPTION, fontsize=DEFAULT_FONT_SIZE, color='k', horizontalalignment='center', verticalalignment='top') image_file_names.append( '{0:s}/conv_animation_row{1:d}_column{2:d}.jpg'.format( output_dir_name, i, j) ) print('Saving figure to: "{0:s}"...'.format(image_file_names[-1])) this_figure_object.savefig( image_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) pyplot.close(this_figure_object) animation_file_name = '{0:s}/conv_animation.gif'.format(output_dir_name) print('Creating animation: "{0:s}"...'.format(animation_file_name)) imagemagick_utils.create_gif( input_file_names=image_file_names, output_file_name=animation_file_name, num_seconds_per_frame=0.5, resize_factor=0.5)
def _plot_tornado_histogram(num_tornadoes_by_day, output_file_name): """Plots histogram for daily number of tornado reports. D = number of SPC dates with GridRad data :param num_tornadoes_by_day: length-D numpy array with number of tornado reports by day. :param output_file_name: Path to output file (figure will be saved here). """ lower_bin_edges = numpy.concatenate( (numpy.linspace(0, 6, num=7, dtype=int), numpy.linspace(11, 101, num=10, dtype=int))) upper_bin_edges = numpy.concatenate( (numpy.linspace(0, 5, num=6, dtype=int), numpy.linspace(10, 100, num=10, dtype=int), numpy.array([LARGE_INTEGER], dtype=int))) num_bins = len(lower_bin_edges) num_days_by_bin = numpy.full(num_bins, -1, dtype=int) x_tick_labels = [''] * num_bins for k in range(num_bins): num_days_by_bin[k] = numpy.sum( numpy.logical_and(num_tornadoes_by_day >= lower_bin_edges[k], num_tornadoes_by_day <= upper_bin_edges[k])) if lower_bin_edges[k] == upper_bin_edges[k]: x_tick_labels[k] = '{0:d}'.format(lower_bin_edges[k]) elif k == num_bins - 1: x_tick_labels[k] = '{0:d}+'.format(lower_bin_edges[k]) else: x_tick_labels[k] = '{0:d}-{1:d}'.format(lower_bin_edges[k], upper_bin_edges[k]) figure_object, axes_object = pyplot.subplots( 1, 1, figsize=(FIGURE_WIDTH_INCHES, FIGURE_HEIGHT_INCHES)) x_tick_coords = 0.5 + numpy.linspace( 0, num_bins - 1, num=num_bins, dtype=float) axes_object.bar(x=x_tick_coords, height=num_days_by_bin, width=1., color=FACE_COLOUR, edgecolor=EDGE_COLOUR, linewidth=EDGE_WIDTH) axes_object.set_xlim([x_tick_coords[0] - 0.5, x_tick_coords[-1] + 0.5]) axes_object.set_xticks(x_tick_coords) axes_object.set_xticklabels(x_tick_labels, rotation=90.) axes_object.set_title('Histogram of daily tornado reports') axes_object.set_ylabel('Number of convective days') axes_object.set_xlabel('Tornado reports') plotting_utils.label_axes(axes_object=axes_object, label_string='(a)') 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(top_gridrad_dir_name, first_spc_date_string, last_spc_date_string, colour_map_name, grid_spacing_metres, output_file_name): """Plots GridRad domains. This is effectively the main method. :param top_gridrad_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 grid_spacing_metres: Same. :param output_file_name: Same. """ colour_map_object = pyplot.get_cmap(colour_map_name) file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name) first_time_unix_sec = time_conversion.get_start_of_spc_date( first_spc_date_string) last_time_unix_sec = time_conversion.get_end_of_spc_date( last_spc_date_string) valid_times_unix_sec = time_periods.range_and_interval_to_list( start_time_unix_sec=first_time_unix_sec, end_time_unix_sec=last_time_unix_sec, time_interval_sec=TIME_INTERVAL_SEC, include_endpoint=True) valid_spc_date_strings = [ time_conversion.time_to_spc_date_string(t) for t in valid_times_unix_sec ] domain_min_latitudes_deg = [] domain_max_latitudes_deg = [] domain_min_longitudes_deg = [] domain_max_longitudes_deg = [] prev_domain_limits_deg = numpy.full(4, numpy.nan) prev_spc_date_string = 'foo' num_times = len(valid_times_unix_sec) for i in range(num_times): this_gridrad_file_name = gridrad_io.find_file( unix_time_sec=valid_times_unix_sec[i], top_directory_name=top_gridrad_dir_name, raise_error_if_missing=False) if not os.path.isfile(this_gridrad_file_name): continue these_domain_limits_deg = _get_domain_one_file(this_gridrad_file_name) same_domain = (valid_spc_date_strings[i] == prev_spc_date_string and numpy.allclose(these_domain_limits_deg, prev_domain_limits_deg, TOLERANCE)) if same_domain: continue prev_domain_limits_deg = these_domain_limits_deg + 0. prev_spc_date_string = valid_spc_date_strings[i] domain_min_latitudes_deg.append(these_domain_limits_deg[0]) domain_max_latitudes_deg.append(these_domain_limits_deg[1]) domain_min_longitudes_deg.append(these_domain_limits_deg[2]) domain_max_longitudes_deg.append(these_domain_limits_deg[3]) print(SEPARATOR_STRING) domain_min_latitudes_deg = numpy.array(domain_min_latitudes_deg) domain_max_latitudes_deg = numpy.array(domain_max_latitudes_deg) domain_min_longitudes_deg = numpy.array(domain_min_longitudes_deg) domain_max_longitudes_deg = numpy.array(domain_max_longitudes_deg) num_domains = len(domain_min_latitudes_deg) grid_metadata_dict = grids.create_equidistant_grid( min_latitude_deg=OVERALL_MIN_LATITUDE_DEG, max_latitude_deg=OVERALL_MAX_LATITUDE_DEG, min_longitude_deg=OVERALL_MIN_LONGITUDE_DEG, max_longitude_deg=OVERALL_MAX_LONGITUDE_DEG, x_spacing_metres=grid_spacing_metres, y_spacing_metres=grid_spacing_metres, azimuthal=False) unique_x_coords_metres = grid_metadata_dict[grids.X_COORDS_KEY] unique_y_coords_metres = grid_metadata_dict[grids.Y_COORDS_KEY] projection_object = grid_metadata_dict[grids.PROJECTION_KEY] x_coord_matrix_metres, y_coord_matrix_metres = grids.xy_vectors_to_matrices( x_unique_metres=unique_x_coords_metres, y_unique_metres=unique_y_coords_metres) latitude_matrix_deg, longitude_matrix_deg = ( projections.project_xy_to_latlng(x_coords_metres=x_coord_matrix_metres, y_coords_metres=y_coord_matrix_metres, projection_object=projection_object)) num_grid_rows = latitude_matrix_deg.shape[0] num_grid_columns = latitude_matrix_deg.shape[1] num_days_matrix = numpy.full((num_grid_rows, num_grid_columns), 0) for i in range(num_domains): if numpy.mod(i, 10) == 0: print('Have found grid points in {0:d} of {1:d} domains...'.format( i, num_domains)) this_lat_flag_matrix = numpy.logical_and( latitude_matrix_deg >= domain_min_latitudes_deg[i], latitude_matrix_deg <= domain_max_latitudes_deg[i]) this_lng_flag_matrix = numpy.logical_and( longitude_matrix_deg >= domain_min_longitudes_deg[i], longitude_matrix_deg <= domain_max_longitudes_deg[i]) num_days_matrix += numpy.logical_and(this_lat_flag_matrix, this_lng_flag_matrix).astype(int) print(SEPARATOR_STRING) figure_object, axes_object = _plot_data( num_days_matrix=num_days_matrix, grid_metadata_dict=grid_metadata_dict, colour_map_object=colour_map_object) plotting_utils.label_axes(axes_object=axes_object, label_string='(c)') 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_attributes_diagram(evaluation_table, num_examples_by_bin, output_file_name, confidence_level=None): """Plots attributes diagram. K = number of bins for forecast probability :param evaluation_table: See doc for `_plot_roc_curve`. :param num_examples_by_bin: length-K numpy array with number of examples in each bin. :param output_file_name: See doc for `_plot_roc_curve`. :param confidence_level: Same. """ mean_forecast_prob_matrix = numpy.vstack( tuple(evaluation_table[ model_eval.MEAN_FORECAST_BY_BIN_KEY].values.tolist())) event_frequency_matrix = numpy.vstack( tuple(evaluation_table[ model_eval.EVENT_FREQ_BY_BIN_KEY].values.tolist())) mean_bss = numpy.nanmean(evaluation_table[model_eval.BSS_KEY].values) annotation_string = 'Brier skill score = {0:.3f}'.format(mean_bss) num_bootstrap_reps = mean_forecast_prob_matrix.shape[0] num_bins = mean_forecast_prob_matrix.shape[1] if num_bootstrap_reps > 1: min_bss, max_bss = bootstrapping.get_confidence_interval( stat_values=evaluation_table[model_eval.BSS_KEY].values, confidence_level=confidence_level) annotation_string = 'Brier skill score = [{0:.3f}, {1:.3f}]'.format( min_bss, max_bss) print(annotation_string) figure_object, axes_object = pyplot.subplots( 1, 1, figsize=(FIGURE_WIDTH_INCHES, FIGURE_HEIGHT_INCHES)) if num_bootstrap_reps > 1: ci_bottom_dict = { model_eval.MEAN_FORECAST_BY_BIN_KEY: numpy.full(num_bins, numpy.nan), model_eval.EVENT_FREQ_BY_BIN_KEY: numpy.full(num_bins, numpy.nan) } ci_top_dict = copy.deepcopy(ci_bottom_dict) ci_mean_dict = copy.deepcopy(ci_bottom_dict) for j in range(num_bins): (ci_top_dict[model_eval.MEAN_FORECAST_BY_BIN_KEY][j], ci_bottom_dict[model_eval.MEAN_FORECAST_BY_BIN_KEY][j] ) = bootstrapping.get_confidence_interval( stat_values=mean_forecast_prob_matrix[:, j], confidence_level=confidence_level) (ci_bottom_dict[model_eval.EVENT_FREQ_BY_BIN_KEY][j], ci_top_dict[model_eval.EVENT_FREQ_BY_BIN_KEY][j] ) = bootstrapping.get_confidence_interval( stat_values=event_frequency_matrix[:, j], confidence_level=confidence_level) ci_mean_dict[model_eval.MEAN_FORECAST_BY_BIN_KEY][j] = ( numpy.nanmean(mean_forecast_prob_matrix[:, j])) ci_mean_dict[model_eval.EVENT_FREQ_BY_BIN_KEY][j] = numpy.nanmean( event_frequency_matrix[:, j]) model_eval_plotting.plot_bootstrapped_attributes_diagram( figure_object=figure_object, axes_object=axes_object, ci_bottom_dict=ci_bottom_dict, ci_mean_dict=ci_mean_dict, ci_top_dict=ci_top_dict, num_examples_by_bin=num_examples_by_bin) else: model_eval_plotting.plot_attributes_diagram( figure_object=figure_object, axes_object=axes_object, mean_forecast_by_bin=mean_forecast_prob_matrix[0, :], event_frequency_by_bin=event_frequency_matrix[0, :], num_examples_by_bin=num_examples_by_bin) axes_object.text(0.02, 0.98, annotation_string, bbox=BOUNDING_BOX_DICT, color='k', horizontalalignment='left', verticalalignment='top', transform=axes_object.transAxes) axes_object.set_title('Attributes diagram') plotting_utils.label_axes(axes_object=axes_object, label_string='(c)', y_coord_normalized=1.025) axes_object.set_aspect('equal') print('Saving attributes diagram 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_roc_curve(evaluation_table, best_threshold_index, output_file_name, confidence_level=None): """Plots ROC curve. :param evaluation_table: See doc for `model_evaluation.run_evaluation`. The only difference is that this table may have multiple rows (one per bootstrap replicate). :param best_threshold_index: Array index of best probability threshold. :param output_file_name: Path to output file (figure will be saved here). :param confidence_level: Confidence level for bootstrapping. """ pod_matrix = numpy.vstack( tuple( evaluation_table[model_eval.POD_BY_THRESHOLD_KEY].values.tolist())) pofd_matrix = numpy.vstack( tuple(evaluation_table[ model_eval.POFD_BY_THRESHOLD_KEY].values.tolist())) num_bootstrap_reps = pod_matrix.shape[0] num_prob_thresholds = pod_matrix.shape[1] if num_bootstrap_reps > 1: min_auc, max_auc = bootstrapping.get_confidence_interval( stat_values=evaluation_table[model_eval.AUC_KEY].values, confidence_level=confidence_level) annotation_string = 'AUC = [{0:.3f}, {1:.3f}]'.format(min_auc, max_auc) mean_auc = numpy.nanmean(evaluation_table[model_eval.AUC_KEY].values) annotation_string = 'AUC = {0:.3f}'.format(mean_auc) else: mean_auc = numpy.nanmean(evaluation_table[model_eval.AUC_KEY].values) annotation_string = 'AUC = {0:.3f}'.format(mean_auc) print(annotation_string) _, axes_object = pyplot.subplots(1, 1, figsize=(FIGURE_WIDTH_INCHES, FIGURE_HEIGHT_INCHES)) if num_bootstrap_reps > 1: ci_bottom_dict = { model_eval.POD_BY_THRESHOLD_KEY: numpy.full(num_prob_thresholds, numpy.nan), model_eval.POFD_BY_THRESHOLD_KEY: numpy.full(num_prob_thresholds, numpy.nan) } ci_top_dict = copy.deepcopy(ci_bottom_dict) ci_mean_dict = copy.deepcopy(ci_bottom_dict) for j in range(num_prob_thresholds): (ci_bottom_dict[model_eval.POD_BY_THRESHOLD_KEY][j], ci_top_dict[model_eval.POD_BY_THRESHOLD_KEY][j] ) = bootstrapping.get_confidence_interval( stat_values=pod_matrix[:, j], confidence_level=confidence_level) (ci_top_dict[model_eval.POFD_BY_THRESHOLD_KEY][j], ci_bottom_dict[model_eval.POFD_BY_THRESHOLD_KEY][j] ) = bootstrapping.get_confidence_interval( stat_values=pofd_matrix[:, j], confidence_level=confidence_level) ci_mean_dict[model_eval.POD_BY_THRESHOLD_KEY][j] = numpy.nanmean( pod_matrix[:, j]) ci_mean_dict[model_eval.POFD_BY_THRESHOLD_KEY][j] = numpy.nanmean( pofd_matrix[:, j]) model_eval_plotting.plot_bootstrapped_roc_curve( axes_object=axes_object, ci_bottom_dict=ci_bottom_dict, ci_mean_dict=ci_mean_dict, ci_top_dict=ci_top_dict) best_x = ci_mean_dict[ model_eval.POFD_BY_THRESHOLD_KEY][best_threshold_index] best_y = ci_mean_dict[ model_eval.POD_BY_THRESHOLD_KEY][best_threshold_index] else: model_eval_plotting.plot_roc_curve(axes_object=axes_object, pod_by_threshold=pod_matrix[0, :], pofd_by_threshold=pofd_matrix[0, :]) best_x = pofd_matrix[0, best_threshold_index] best_y = pod_matrix[0, best_threshold_index] print(('POD and POFD at best probability threshold = {0:.3f}, {1:.3f}' ).format(best_y, best_x)) marker_colour = model_eval_plotting.ROC_CURVE_COLOUR # axes_object.plot( # best_x, best_y, linestyle='None', marker=MARKER_TYPE, # markersize=MARKER_SIZE, markeredgewidth=MARKER_EDGE_WIDTH, # markerfacecolor=marker_colour, markeredgecolor=marker_colour) axes_object.text(0.98, 0.02, annotation_string, bbox=BOUNDING_BOX_DICT, color='k', horizontalalignment='right', verticalalignment='bottom', transform=axes_object.transAxes) axes_object.set_title('ROC curve') plotting_utils.label_axes(axes_object=axes_object, label_string='(a)', y_coord_normalized=1.025) axes_object.set_aspect('equal') print('Saving ROC curve 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_performance_diagram(evaluation_table, best_threshold_index, output_file_name, confidence_level=None): """Plots performance diagram. :param evaluation_table: See doc for `_plot_roc_curve`. :param best_threshold_index: Array index of best probability threshold. :param output_file_name: Same. :param confidence_level: Same. """ pod_matrix = numpy.vstack( tuple( evaluation_table[model_eval.POD_BY_THRESHOLD_KEY].values.tolist())) success_ratio_matrix = numpy.vstack( tuple( evaluation_table[model_eval.SR_BY_THRESHOLD_KEY].values.tolist())) mean_aupd = numpy.nanmean(evaluation_table[model_eval.AUPD_KEY].values) annotation_string = 'AUPD = {0:.3f}'.format(mean_aupd) num_bootstrap_reps = pod_matrix.shape[0] num_prob_thresholds = pod_matrix.shape[1] if num_bootstrap_reps > 1: min_aupd, max_aupd = bootstrapping.get_confidence_interval( stat_values=evaluation_table[model_eval.AUPD_KEY].values, confidence_level=confidence_level) annotation_string = 'AUPD = [{0:.3f}, {1:.3f}]'.format( min_aupd, max_aupd) mean_aupd = numpy.nanmean(evaluation_table[model_eval.AUPD_KEY].values) annotation_string = 'AUPD = {0:.3f}'.format(mean_aupd) print(annotation_string) _, axes_object = pyplot.subplots(1, 1, figsize=(FIGURE_WIDTH_INCHES, FIGURE_HEIGHT_INCHES)) if num_bootstrap_reps > 1: ci_bottom_dict = { model_eval.POD_BY_THRESHOLD_KEY: numpy.full(num_prob_thresholds, numpy.nan), model_eval.SR_BY_THRESHOLD_KEY: numpy.full(num_prob_thresholds, numpy.nan) } ci_top_dict = copy.deepcopy(ci_bottom_dict) ci_mean_dict = copy.deepcopy(ci_bottom_dict) for j in range(num_prob_thresholds): (ci_bottom_dict[model_eval.POD_BY_THRESHOLD_KEY][j], ci_top_dict[model_eval.POD_BY_THRESHOLD_KEY][j] ) = bootstrapping.get_confidence_interval( stat_values=pod_matrix[:, j], confidence_level=confidence_level) (ci_bottom_dict[model_eval.SR_BY_THRESHOLD_KEY][j], ci_top_dict[model_eval.SR_BY_THRESHOLD_KEY][j] ) = bootstrapping.get_confidence_interval( stat_values=success_ratio_matrix[:, j], confidence_level=confidence_level) ci_mean_dict[model_eval.POD_BY_THRESHOLD_KEY][j] = numpy.nanmean( pod_matrix[:, j]) ci_mean_dict[model_eval.SR_BY_THRESHOLD_KEY][j] = numpy.nanmean( success_ratio_matrix[:, j]) model_eval_plotting.plot_bootstrapped_performance_diagram( axes_object=axes_object, ci_bottom_dict=ci_bottom_dict, ci_mean_dict=ci_mean_dict, ci_top_dict=ci_top_dict) best_x = ci_mean_dict[ model_eval.SR_BY_THRESHOLD_KEY][best_threshold_index] best_y = ci_mean_dict[ model_eval.POD_BY_THRESHOLD_KEY][best_threshold_index] else: model_eval_plotting.plot_performance_diagram( axes_object=axes_object, pod_by_threshold=pod_matrix[0, :], success_ratio_by_threshold=success_ratio_matrix[0, :]) best_x = success_ratio_matrix[0, best_threshold_index] best_y = pod_matrix[0, best_threshold_index] print(( 'POD and success ratio at best probability threshold = {0:.3f}, {1:.3f}' ).format(best_y, best_x)) marker_colour = model_eval_plotting.PERF_DIAGRAM_COLOUR # axes_object.plot( # best_x, best_y, linestyle='None', marker=MARKER_TYPE, # markersize=MARKER_SIZE, markeredgewidth=MARKER_EDGE_WIDTH, # markerfacecolor=marker_colour, markeredgecolor=marker_colour) axes_object.text(0.98, 0.98, annotation_string, bbox=BOUNDING_BOX_DICT, color='k', horizontalalignment='right', verticalalignment='top', transform=axes_object.transAxes) axes_object.set_title('Performance diagram') plotting_utils.label_axes(axes_object=axes_object, label_string='(b)', y_coord_normalized=1.025) axes_object.set_aspect('equal') print('Saving performance diagram 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 _do_plotting(example_dict, example_index, output_dir_name): """Does the plotting. :param example_dict: See doc for `example_io.read_file`. :param example_index: Will plot predictors and targets for [k]th example in dictionary, where k = `example_index`. :param output_dir_name: Name of output directory. Figures will be saved here. """ example_id_string = ( example_dict[example_utils.EXAMPLE_IDS_KEY][example_index]) num_predictor_sets = len(PREDICTOR_NAMES_BY_SET) letter_label = None panel_file_names = [] for k in range(num_predictor_sets): these_flags = numpy.array([ n in example_dict[example_utils.VECTOR_PREDICTOR_NAMES_KEY] for n in PREDICTOR_NAMES_BY_SET[k] ], dtype=bool) these_indices = numpy.where(these_flags)[0] if len(these_indices) == 0: continue predictor_names = [PREDICTOR_NAMES_BY_SET[k][i] for i in these_indices] predictor_colours = [ PREDICTOR_COLOURS_BY_SET[k][i] for i in these_indices ] handle_dict = profile_plotting.plot_predictors( example_dict=example_dict, example_index=example_index, predictor_names=predictor_names, predictor_colours=predictor_colours, predictor_line_widths=numpy.full(len(these_indices), LINE_WIDTH), predictor_line_styles=['solid'] * len(these_indices), use_log_scale=True) if letter_label is None: letter_label = 'a' else: letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes( axes_object=handle_dict[profile_plotting.AXES_OBJECTS_KEY][0], label_string='({0:s})'.format(letter_label), font_size=LETTER_LABEL_FONT_SIZE, x_coord_normalized=LETTER_LABEL_X_COORD, y_coord_normalized=LETTER_LABEL_Y_COORD) this_file_name = '{0:s}/{1:s}_predictor-set-{2:d}.jpg'.format( output_dir_name, example_id_string.replace('_', '-'), k) panel_file_names.append(this_file_name) print('Saving figure to: "{0:s}"...'.format(this_file_name)) figure_object = handle_dict[profile_plotting.FIGURE_HANDLE_KEY] figure_object.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) imagemagick_utils.trim_whitespace(input_file_name=this_file_name, output_file_name=this_file_name) imagemagick_utils.resize_image(input_file_name=this_file_name, output_file_name=this_file_name, output_size_pixels=int(2.5e6)) handle_dict = profile_plotting.plot_targets(example_dict=example_dict, example_index=example_index, use_log_scale=True, line_width=LINE_WIDTH, line_style='solid') letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes( axes_object=handle_dict[profile_plotting.HEATING_RATE_HANDLE_KEY], label_string='({0:s})'.format(letter_label), font_size=LETTER_LABEL_FONT_SIZE, x_coord_normalized=LETTER_LABEL_X_COORD, y_coord_normalized=LETTER_LABEL_Y_COORD) this_file_name = '{0:s}/{1:s}_targets.jpg'.format( output_dir_name, example_id_string.replace('_', '-')) panel_file_names.append(this_file_name) print('Saving figure to: "{0:s}"...'.format(this_file_name)) figure_object = handle_dict[profile_plotting.FIGURE_HANDLE_KEY] figure_object.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) imagemagick_utils.trim_whitespace(input_file_name=this_file_name, output_file_name=this_file_name) imagemagick_utils.resize_image(input_file_name=this_file_name, output_file_name=this_file_name, output_size_pixels=int(2.5e6)) concat_file_name = '{0:s}/{1:s}_concat.jpg'.format( output_dir_name, example_id_string.replace('_', '-')) print('Concatenating panels to: "{0:s}"...'.format(concat_file_name)) imagemagick_utils.concatenate_images(input_file_names=panel_file_names, output_file_name=concat_file_name, num_panel_rows=2, num_panel_columns=2, border_width_pixels=25) imagemagick_utils.trim_whitespace(input_file_name=concat_file_name, output_file_name=concat_file_name)
def _run(top_radar_dir_name, top_echo_classifn_dir_name, valid_time_string, min_latitude_deg, max_latitude_deg, min_longitude_deg, max_longitude_deg, output_dir_name): """Makes figure to explain storm detection. This is effectively the main method. :param top_radar_dir_name: See documentation at top of file. :param top_echo_classifn_dir_name: Same. :param valid_time_string: Same. :param min_latitude_deg: Same. :param max_latitude_deg: Same. :param min_longitude_deg: Same. :param max_longitude_deg: Same. :param output_dir_name: Same. """ file_system_utils.mkdir_recursive_if_necessary( directory_name=output_dir_name ) valid_time_unix_sec = time_conversion.string_to_unix_sec( valid_time_string, TIME_FORMAT ) spc_date_string = time_conversion.time_to_spc_date_string( valid_time_unix_sec ) num_trials = len(MIN_POLYGON_SIZES_PX) tracking_dir_names = [None] * num_trials for k in range(num_trials): tracking_dir_names[k] = ( '{0:s}/tracking/min-polygon-size-px={1:d}_recompute-centroids={2:d}' ).format( output_dir_name, MIN_POLYGON_SIZES_PX[k], int(RECOMPUTE_CENTROID_FLAGS[k]) ) echo_top_tracking.run_tracking( top_radar_dir_name=top_radar_dir_name, top_output_dir_name=tracking_dir_names[k], first_spc_date_string=spc_date_string, last_spc_date_string=spc_date_string, first_time_unix_sec=valid_time_unix_sec, last_time_unix_sec=valid_time_unix_sec + 1, top_echo_classifn_dir_name=top_echo_classifn_dir_name, min_polygon_size_pixels=MIN_POLYGON_SIZES_PX[k], recompute_centroids=RECOMPUTE_CENTROID_FLAGS[k] ) print(SEPARATOR_STRING) echo_top_file_name = myrorss_and_mrms_io.find_raw_file( top_directory_name=top_radar_dir_name, unix_time_sec=valid_time_unix_sec, spc_date_string=spc_date_string, field_name=radar_utils.ECHO_TOP_40DBZ_NAME, data_source=radar_utils.MYRORSS_SOURCE_ID, raise_error_if_missing=True ) print('Reading data from: "{0:s}"...'.format(echo_top_file_name)) metadata_dict = myrorss_and_mrms_io.read_metadata_from_raw_file( netcdf_file_name=echo_top_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=echo_top_file_name, field_name_orig=metadata_dict[ myrorss_and_mrms_io.FIELD_NAME_COLUMN_ORIG], data_source=radar_utils.MYRORSS_SOURCE_ID, sentinel_values=metadata_dict[radar_utils.SENTINEL_VALUE_COLUMN] ) echo_top_matrix_km_asl, radar_latitudes_deg, radar_longitudes_deg = ( radar_s2f.sparse_to_full_grid( sparse_grid_table=sparse_grid_table, metadata_dict=metadata_dict) ) echo_top_matrix_km_asl = numpy.flip(echo_top_matrix_km_asl, axis=0) radar_latitudes_deg = radar_latitudes_deg[::-1] echo_classifn_file_name = echo_classifn.find_classification_file( top_directory_name=top_echo_classifn_dir_name, valid_time_unix_sec=valid_time_unix_sec, desire_zipped=True, allow_zipped_or_unzipped=True, raise_error_if_missing=True ) print('Reading data from: "{0:s}"...'.format(echo_classifn_file_name)) convective_flag_matrix = echo_classifn.read_classifications( echo_classifn_file_name )[0] good_indices = numpy.where(numpy.logical_and( radar_latitudes_deg >= min_latitude_deg, radar_latitudes_deg <= max_latitude_deg ))[0] echo_top_matrix_km_asl = echo_top_matrix_km_asl[good_indices, ...] convective_flag_matrix = convective_flag_matrix[good_indices, ...] radar_latitudes_deg = radar_latitudes_deg[good_indices] good_indices = numpy.where(numpy.logical_and( radar_longitudes_deg >= min_longitude_deg, radar_longitudes_deg <= max_longitude_deg ))[0] echo_top_matrix_km_asl = echo_top_matrix_km_asl[..., good_indices] convective_flag_matrix = convective_flag_matrix[..., good_indices] radar_longitudes_deg = radar_longitudes_deg[good_indices] this_figure_object, this_axes_object = _plot_echo_tops( echo_top_matrix_km_asl=echo_top_matrix_km_asl, latitudes_deg=radar_latitudes_deg, longitudes_deg=radar_longitudes_deg, plot_colour_bar=False, convective_flag_matrix=None )[:2] this_axes_object.set_title('All echoes') plotting_utils.label_axes(axes_object=this_axes_object, label_string='(a)') panel_file_names = [ '{0:s}/before_echo_classification.jpg'.format(output_dir_name) ] print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) this_figure_object.savefig( panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) pyplot.close(this_figure_object) this_figure_object, this_axes_object = _plot_echo_tops( echo_top_matrix_km_asl=echo_top_matrix_km_asl, latitudes_deg=radar_latitudes_deg, longitudes_deg=radar_longitudes_deg, plot_colour_bar=False, convective_flag_matrix=convective_flag_matrix )[:2] this_axes_object.set_title('Convective echoes only') plotting_utils.label_axes(axes_object=this_axes_object, label_string='(b)') panel_file_names.append( '{0:s}/after_echo_classification.jpg'.format(output_dir_name) ) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) this_figure_object.savefig( panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) pyplot.close(this_figure_object) letter_label = 'b' for k in range(num_trials): this_tracking_file_name = tracking_io.find_file( top_tracking_dir_name=tracking_dir_names[k], tracking_scale_metres2= echo_top_tracking.DUMMY_TRACKING_SCALE_METRES2, source_name=tracking_utils.SEGMOTION_NAME, valid_time_unix_sec=valid_time_unix_sec, spc_date_string=spc_date_string, raise_error_if_missing=True ) print('Reading data from: "{0:s}"...'.format(this_tracking_file_name)) this_storm_object_table = tracking_io.read_file(this_tracking_file_name) this_figure_object, this_axes_object, this_basemap_object = ( _plot_echo_tops( echo_top_matrix_km_asl=echo_top_matrix_km_asl, latitudes_deg=radar_latitudes_deg, longitudes_deg=radar_longitudes_deg, plot_colour_bar=k > 0, convective_flag_matrix=convective_flag_matrix) ) storm_plotting.plot_storm_outlines( storm_object_table=this_storm_object_table, axes_object=this_axes_object, basemap_object=this_basemap_object, line_width=POLYGON_WIDTH, line_colour=POLYGON_COLOUR ) these_x_metres, these_y_metres = this_basemap_object( this_storm_object_table[ tracking_utils.CENTROID_LONGITUDE_COLUMN].values, this_storm_object_table[ tracking_utils.CENTROID_LATITUDE_COLUMN].values ) this_axes_object.plot( these_x_metres, these_y_metres, linestyle='None', marker=MARKER_TYPE, markersize=MARKER_SIZE, markerfacecolor=MARKER_COLOUR, markeredgecolor=MARKER_COLOUR, markeredgewidth=MARKER_EDGE_WIDTH ) this_title_string = ( 'Minimum size = {0:d} GP, {1:s} storm centers' ).format( MIN_POLYGON_SIZES_PX[k], 'recomputed' if RECOMPUTE_CENTROID_FLAGS[k] else 'original' ) this_axes_object.set_title(this_title_string) letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes( axes_object=this_axes_object, label_string='({0:s})'.format(letter_label) ) panel_file_names.append( '{0:s}/detection{1:d}.jpg'.format(output_dir_name, k) ) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) this_figure_object.savefig( panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) pyplot.close(this_figure_object) concat_file_name = '{0:s}/storm_detection.jpg'.format(output_dir_name) print('Concatenating panels to: "{0:s}"...'.format(concat_file_name)) imagemagick_utils.concatenate_images( input_file_names=panel_file_names, output_file_name=concat_file_name, num_panel_rows=3, num_panel_columns=2 )
def _run(gridrad_example_dir_name, gridrad_full_id_string, gridrad_time_string, myrorss_example_dir_name, myrorss_full_id_string, myrorss_time_string, output_dir_name): """Makes figure with GridRad and MYRORSS predictors. This is effectively the main method. :param gridrad_example_dir_name: See documentation at top of file. :param gridrad_full_id_string: Same. :param gridrad_time_string: Same. :param myrorss_example_dir_name: Same. :param myrorss_full_id_string: Same. :param myrorss_time_string: Same. :param output_dir_name: Same. """ file_system_utils.mkdir_recursive_if_necessary( directory_name=output_dir_name) gridrad_time_unix_sec = time_conversion.string_to_unix_sec( gridrad_time_string, TIME_FORMAT) myrorss_time_unix_sec = time_conversion.string_to_unix_sec( myrorss_time_string, TIME_FORMAT) letter_label = None num_gridrad_fields = len(GRIDRAD_FIELD_NAMES) panel_file_names = [None] * num_gridrad_fields * 2 for j in range(num_gridrad_fields): these_predictor_matrices, this_metadata_dict = _read_one_example( top_example_dir_name=gridrad_example_dir_name, full_storm_id_string=gridrad_full_id_string, storm_time_unix_sec=gridrad_time_unix_sec, source_name=radar_utils.GRIDRAD_SOURCE_ID, radar_field_name=GRIDRAD_FIELD_NAMES[j], include_sounding=False)[:2] print(MINOR_SEPARATOR_STRING) this_handle_dict = plot_examples.plot_one_example( list_of_predictor_matrices=these_predictor_matrices, model_metadata_dict=this_metadata_dict, pmm_flag=False, example_index=0, plot_sounding=False, allow_whitespace=True, plot_panel_names=False, add_titles=False, label_colour_bars=False, colour_bar_font_size=COLOUR_BAR_FONT_SIZE, colour_bar_length=COLOUR_BAR_LENGTH) this_title_string = radar_plotting.fields_and_heights_to_names( field_names=[GRIDRAD_FIELD_NAMES[j]], heights_m_agl=RADAR_HEIGHTS_M_AGL[[0]], include_units=True)[0] this_title_string = this_title_string.replace('\n', ' ').replace( ' km AGL', ' km') this_title_string = 'GridRad {0:s}{1:s}'.format( this_title_string[0].lower(), this_title_string[1:]) this_figure_object = this_handle_dict[ plot_examples.RADAR_FIGURES_KEY][0] this_axes_object = this_handle_dict[plot_examples.RADAR_AXES_KEY][0][0, 0] this_figure_object.suptitle('') this_axes_object.set_title(this_title_string, fontsize=TITLE_FONT_SIZE) # this_axes_object.set_yticklabels( # this_axes_object.get_yticks(), color=ALMOST_WHITE_COLOUR # ) if letter_label is None: letter_label = 'a' else: letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes(axes_object=this_axes_object, label_string='({0:s})'.format(letter_label), font_size=PANEL_LETTER_FONT_SIZE, x_coord_normalized=X_LABEL_COORD_NORMALIZED, y_coord_normalized=Y_LABEL_COORD_NORMALIZED) panel_file_names[j * 2] = '{0:s}/gridrad_{1:s}.jpg'.format( output_dir_name, GRIDRAD_FIELD_NAMES[j].replace('_', '-')) print('Saving figure to: "{0:s}"...'.format(panel_file_names[j * 2])) this_figure_object.savefig(panel_file_names[j * 2], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(this_figure_object) print(SEPARATOR_STRING) num_myrorss_shear_fields = len(MYRORSS_SHEAR_FIELD_NAMES) for j in range(num_myrorss_shear_fields): (these_predictor_matrices, this_metadata_dict, these_pressures_pascals) = _read_one_example( top_example_dir_name=myrorss_example_dir_name, full_storm_id_string=myrorss_full_id_string, storm_time_unix_sec=myrorss_time_unix_sec, source_name=radar_utils.MYRORSS_SOURCE_ID, radar_field_name=MYRORSS_SHEAR_FIELD_NAMES[j], include_sounding=j == 0) print(MINOR_SEPARATOR_STRING) this_handle_dict = plot_examples.plot_one_example( list_of_predictor_matrices=these_predictor_matrices, model_metadata_dict=this_metadata_dict, pmm_flag=False, example_index=0, plot_sounding=j == 0, sounding_pressures_pascals=these_pressures_pascals, allow_whitespace=True, plot_panel_names=False, add_titles=False, label_colour_bars=False, colour_bar_font_size=COLOUR_BAR_FONT_SIZE, colour_bar_length=COLOUR_BAR_LENGTH, sounding_font_size=SOUNDING_FONT_SIZE) if j == 0: this_axes_object = this_handle_dict[ plot_examples.SOUNDING_AXES_KEY] this_axes_object.set_title('Proximity sounding') letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes( axes_object=this_axes_object, label_string='({0:s})'.format(letter_label), font_size=PANEL_LETTER_FONT_SIZE, x_coord_normalized=X_LABEL_COORD_NORMALIZED, y_coord_normalized=Y_LABEL_COORD_NORMALIZED) this_figure_object = this_handle_dict[ plot_examples.SOUNDING_FIGURE_KEY] panel_file_names[1] = '{0:s}/sounding.jpg'.format(output_dir_name) print('Saving figure to: "{0:s}"...'.format(panel_file_names[1])) this_figure_object.savefig(panel_file_names[1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(this_figure_object) this_title_string = radar_plotting.fields_and_heights_to_names( field_names=[radar_utils.REFL_NAME], heights_m_agl=RADAR_HEIGHTS_M_AGL[[0]], include_units=True)[0] this_title_string = this_title_string.replace('\n', ' ').replace( ' km AGL', ' km') this_title_string = 'MYRORSS {0:s}{1:s}'.format( this_title_string[0].lower(), this_title_string[1:]) this_figure_object = this_handle_dict[ plot_examples.RADAR_FIGURES_KEY][0] this_axes_object = this_handle_dict[ plot_examples.RADAR_AXES_KEY][0][0, 0] this_figure_object.suptitle('') this_axes_object.set_title(this_title_string, fontsize=TITLE_FONT_SIZE) letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes( axes_object=this_axes_object, label_string='({0:s})'.format(letter_label), font_size=PANEL_LETTER_FONT_SIZE, x_coord_normalized=X_LABEL_COORD_NORMALIZED, y_coord_normalized=Y_LABEL_COORD_NORMALIZED) panel_file_names[3] = '{0:s}/myrorss_{1:s}.jpg'.format( output_dir_name, radar_utils.REFL_NAME.replace('_', '-')) print('Saving figure to: "{0:s}"...'.format(panel_file_names[3])) this_figure_object.savefig(panel_file_names[3], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(this_figure_object) this_title_string = radar_plotting.fields_and_heights_to_names( field_names=[MYRORSS_SHEAR_FIELD_NAMES[j]], heights_m_agl=RADAR_HEIGHTS_M_AGL[[0]], include_units=True)[0] this_title_string = this_title_string.split('\n')[0] this_title_string = 'MYRORSS {0:s}{1:s}'.format( this_title_string[0].lower(), this_title_string[1:]) this_figure_object = this_handle_dict[ plot_examples.RADAR_FIGURES_KEY][1] this_axes_object = this_handle_dict[plot_examples.RADAR_AXES_KEY][1][0, 0] this_figure_object.suptitle('') this_axes_object.set_title(this_title_string, fontsize=TITLE_FONT_SIZE) letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes(axes_object=this_axes_object, label_string='({0:s})'.format(letter_label), font_size=PANEL_LETTER_FONT_SIZE, x_coord_normalized=X_LABEL_COORD_NORMALIZED, y_coord_normalized=Y_LABEL_COORD_NORMALIZED) panel_file_names[5 + j * 2] = '{0:s}/myrorss_{1:s}.jpg'.format( output_dir_name, MYRORSS_SHEAR_FIELD_NAMES[j].replace('_', '-')) print('Saving figure to: "{0:s}"...'.format(panel_file_names[5 + j * 2])) this_figure_object.savefig(panel_file_names[5 + j * 2], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(this_figure_object) if j != num_myrorss_shear_fields: print(SEPARATOR_STRING) concat_file_name = '{0:s}/predictors.jpg'.format(output_dir_name) print('Concatenating panels to: "{0:s}"...'.format(concat_file_name)) imagemagick_utils.concatenate_images(input_file_names=panel_file_names, output_file_name=concat_file_name, num_panel_rows=4, num_panel_columns=2) imagemagick_utils.resize_image(input_file_name=concat_file_name, output_file_name=concat_file_name, output_size_pixels=CONCAT_FIGURE_SIZE_PX)
def _plot_month_histogram(spc_date_strings, output_file_name): """Plots histogram of months. :param spc_date_strings: 1-D list of SPC dates (format "yyyymmdd") with GridRad data. :param output_file_name: Path to output file (figure will be saved here). """ start_times_unix_sec = numpy.array( [time_conversion.get_start_of_spc_date(d) for d in spc_date_strings], dtype=int) end_times_unix_sec = numpy.array( [time_conversion.get_end_of_spc_date(d) for d in spc_date_strings], dtype=int) start_month_by_date = numpy.array([ int(time_conversion.unix_sec_to_string(t, '%m')) for t in start_times_unix_sec ], dtype=int) end_month_by_date = numpy.array([ int(time_conversion.unix_sec_to_string(t, '%m')) for t in end_times_unix_sec ], dtype=int) num_days_by_month = numpy.full(NUM_MONTHS_IN_YEAR, numpy.nan) for k in range(NUM_MONTHS_IN_YEAR): num_days_by_month[k] = 0.5 * (numpy.sum(start_month_by_date == k + 1) + numpy.sum(end_month_by_date == k + 1)) figure_object, axes_object = pyplot.subplots( 1, 1, figsize=(FIGURE_WIDTH_INCHES, FIGURE_HEIGHT_INCHES)) x_tick_coords = 0.5 + numpy.linspace( 0, NUM_MONTHS_IN_YEAR - 1, num=NUM_MONTHS_IN_YEAR, dtype=float) x_tick_labels = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ] axes_object.bar(x=x_tick_coords, height=num_days_by_month, width=1., color=FACE_COLOUR, edgecolor=EDGE_COLOUR, linewidth=EDGE_WIDTH) axes_object.set_xlim([x_tick_coords[0] - 0.5, x_tick_coords[-1] + 0.5]) axes_object.set_xticks(x_tick_coords) axes_object.set_xticklabels(x_tick_labels, rotation=90.) axes_object.set_title('Histogram of months') axes_object.set_ylabel('Number of convective days') axes_object.set_xlabel('Month') plotting_utils.label_axes(axes_object=axes_object, label_string='(b)') 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(forward_test_file_name, backwards_test_file_name, num_predictors, confidence_level, output_file_name): """Makes figure with results of all 4 permutation tests. This is effectively the main method. :param forward_test_file_name: See documentation at top of file. :param backwards_test_file_name: Same. :param num_predictors: Same. :param confidence_level: Same. :param output_file_name: Same. """ if num_predictors <= 0: num_predictors = None file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name) print('Reading data from: "{0:s}"...'.format(forward_test_file_name)) forward_test_dict = permutation_utils.read_results(forward_test_file_name) print('Reading data from: "{0:s}"...'.format(backwards_test_file_name)) backwards_test_dict = permutation_utils.read_results( backwards_test_file_name ) figure_object, axes_object_matrix = plotting_utils.create_paneled_figure( num_rows=2, num_columns=2, shared_x_axis=False, shared_y_axis=True, keep_aspect_ratio=False, horizontal_spacing=0.1, vertical_spacing=0.05 ) permutation_plotting.plot_single_pass_test( permutation_dict=forward_test_dict, axes_object=axes_object_matrix[0, 0], plot_percent_increase=False, confidence_level=confidence_level, num_predictors_to_plot=num_predictors ) axes_object_matrix[0, 0].set_title('Forward single-pass test') axes_object_matrix[0, 0].set_xticks([]) axes_object_matrix[0, 0].set_xlabel('') plotting_utils.label_axes( axes_object=axes_object_matrix[0, 0], label_string='(a)', x_coord_normalized=-0.01, y_coord_normalized=0.925 ) permutation_plotting.plot_multipass_test( permutation_dict=forward_test_dict, axes_object=axes_object_matrix[0, 1], plot_percent_increase=False, confidence_level=confidence_level, num_predictors_to_plot=num_predictors ) axes_object_matrix[0, 1].set_title('Forward multi-pass test') axes_object_matrix[0, 1].set_xticks([]) axes_object_matrix[0, 1].set_xlabel('') axes_object_matrix[0, 1].set_ylabel('') plotting_utils.label_axes( axes_object=axes_object_matrix[0, 1], label_string='(b)', x_coord_normalized=1.15, y_coord_normalized=0.925 ) permutation_plotting.plot_single_pass_test( permutation_dict=backwards_test_dict, axes_object=axes_object_matrix[1, 0], plot_percent_increase=False, confidence_level=confidence_level, num_predictors_to_plot=num_predictors ) axes_object_matrix[1, 0].set_title('Backward single-pass test') axes_object_matrix[1, 0].set_xlabel('Area under ROC curve (AUC)') plotting_utils.label_axes( axes_object=axes_object_matrix[1, 0], label_string='(c)', x_coord_normalized=-0.01, y_coord_normalized=0.925 ) permutation_plotting.plot_multipass_test( permutation_dict=backwards_test_dict, axes_object=axes_object_matrix[1, 1], plot_percent_increase=False, confidence_level=confidence_level, num_predictors_to_plot=num_predictors ) axes_object_matrix[1, 1].set_title('Backward multi-pass test') axes_object_matrix[1, 1].set_xlabel('Area under ROC curve (AUC)') axes_object_matrix[1, 1].set_ylabel('') plotting_utils.label_axes( axes_object=axes_object_matrix[1, 1], label_string='(d)', x_coord_normalized=1.15, y_coord_normalized=0.925 ) 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(include_caption, output_dir_name): """Makes animation to explain pooling. This is effectively the main method. :param include_caption: See documentation at top of file. :param output_dir_name: Same. """ file_system_utils.mkdir_recursive_if_necessary( directory_name=output_dir_name) num_input_rows = INPUT_FEATURE_MATRIX.shape[0] num_input_columns = INPUT_FEATURE_MATRIX.shape[1] num_channels = INPUT_FEATURE_MATRIX.shape[2] image_file_names = [] for i in range(num_input_rows): for j in range(num_input_columns): this_figure_object, this_axes_object_matrix = ( plotting_utils.create_paneled_figure( num_rows=num_channels, num_columns=NUM_PANEL_COLUMNS, horizontal_spacing=HORIZ_PANEL_SPACING, vertical_spacing=VERTICAL_PANEL_SPACING, shared_x_axis=False, shared_y_axis=False, keep_aspect_ratio=True)) letter_label = None for k in range(num_channels): _plot_feature_map(feature_matrix_2d=INPUT_FEATURE_MATRIX[..., k], pooled_row=i, pooled_column=j, pooled=True, axes_object=this_axes_object_matrix[k, 0]) if letter_label is None: letter_label = 'a' else: letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes( axes_object=this_axes_object_matrix[k, 0], label_string='({0:s})'.format(letter_label), font_size=PANEL_LETTER_FONT_SIZE, y_coord_normalized=0.85, x_coord_normalized=-0.02) for k in range(num_channels): _plot_feature_map(feature_matrix_2d=OUTPUT_FEATURE_MATRIX[..., k], pooled_row=i, pooled_column=j, pooled=False, axes_object=this_axes_object_matrix[k, 1]) letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes( axes_object=this_axes_object_matrix[k, 1], label_string='({0:s})'.format(letter_label), font_size=PANEL_LETTER_FONT_SIZE, y_coord_normalized=0.85, x_coord_normalized=-0.02) _plot_interpanel_lines( pooled_row=i, pooled_column=j, input_fm_axes_object=this_axes_object_matrix[k, 0], output_fm_axes_object=this_axes_object_matrix[k, 1]) if include_caption: this_figure_object.text(0.5, CAPTION_Y_COORD, FIGURE_CAPTION, fontsize=DEFAULT_FONT_SIZE, color='k', horizontalalignment='center', verticalalignment='top') image_file_names.append( '{0:s}/upsampling_animation_row{1:d}_column{2:d}.jpg'.format( output_dir_name, i, j)) print('Saving figure to: "{0:s}"...'.format(image_file_names[-1])) this_figure_object.savefig(image_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(this_figure_object) animation_file_name = '{0:s}/upsampling_animation.gif'.format( output_dir_name) print('Creating animation: "{0:s}"...'.format(animation_file_name)) imagemagick_utils.create_gif(input_file_names=image_file_names, output_file_name=animation_file_name, num_seconds_per_frame=0.5, resize_factor=0.5)
def _plot_by_hour(evaluation_dir_name, num_hours_per_chunk, confidence_level, output_dir_name): """Plots model evaluation by hour. :param evaluation_dir_name: See documentation at top of file. :param num_hours_per_chunk: Same. :param confidence_level: Same. :param output_dir_name: Same. :return: output_file_names: Paths to figures saved by this method. """ chunk_to_hours_dict = temporal_subsetting.get_hourly_chunks( num_hours_per_chunk=num_hours_per_chunk, verbose=False) num_bootstrap_reps = None num_chunks = len(chunk_to_hours_dict.keys()) auc_matrix = numpy.full((num_chunks, 3), numpy.nan) pod_matrix = numpy.full((num_chunks, 3), numpy.nan) far_matrix = numpy.full((num_chunks, 3), numpy.nan) csi_matrix = numpy.full((num_chunks, 3), numpy.nan) num_examples_by_chunk = numpy.full(num_chunks, 0, dtype=int) num_positive_ex_by_chunk = numpy.full(num_chunks, 0, dtype=int) for i in range(num_chunks): this_eval_file_name = model_eval.find_file( directory_name=evaluation_dir_name, hours_in_subset=chunk_to_hours_dict[i], raise_error_if_missing=False) if not os.path.isfile(this_eval_file_name): warning_string = ( 'Cannot find file (this may or may not be a problem). Expected' ' at: "{0:s}"').format(this_eval_file_name) warnings.warn(warning_string) continue print('Reading data from: "{0:s}"...'.format(this_eval_file_name)) this_evaluation_dict = model_eval.read_evaluation(this_eval_file_name) num_examples_by_chunk[i] = len( this_evaluation_dict[model_eval.OBSERVED_LABELS_KEY]) num_positive_ex_by_chunk[i] = numpy.sum( this_evaluation_dict[model_eval.OBSERVED_LABELS_KEY]) this_evaluation_table = this_evaluation_dict[ model_eval.EVALUATION_TABLE_KEY] this_num_bootstrap_reps = len(this_evaluation_table.index) if num_bootstrap_reps is None: num_bootstrap_reps = this_num_bootstrap_reps assert num_bootstrap_reps == this_num_bootstrap_reps these_auc = this_evaluation_table[model_eval.AUC_KEY].values these_pod = this_evaluation_table[model_eval.POD_KEY].values these_far = ( 1. - this_evaluation_table[model_eval.SUCCESS_RATIO_KEY].values) these_csi = this_evaluation_table[model_eval.CSI_KEY].values auc_matrix[i, 1] = numpy.nanmean(these_auc) pod_matrix[i, 1] = numpy.nanmean(these_pod) far_matrix[i, 1] = numpy.nanmean(these_far) csi_matrix[i, 1] = numpy.nanmean(these_csi) auc_matrix[i, 0], auc_matrix[i, 2] = (bootstrapping.get_confidence_interval( stat_values=these_auc, confidence_level=confidence_level)) pod_matrix[i, 0], pod_matrix[i, 2] = (bootstrapping.get_confidence_interval( stat_values=these_pod, confidence_level=confidence_level)) far_matrix[i, 0], far_matrix[i, 2] = (bootstrapping.get_confidence_interval( stat_values=these_far, confidence_level=confidence_level)) csi_matrix[i, 0], csi_matrix[i, 2] = (bootstrapping.get_confidence_interval( stat_values=these_csi, confidence_level=confidence_level)) x_tick_labels = [None] * num_chunks x_tick_values = numpy.linspace(0, num_chunks - 1, num=num_chunks, dtype=float) for i in range(num_chunks): these_hours = chunk_to_hours_dict[i] if len(these_hours) == 1: x_tick_labels[i] = '{0:02d}'.format(these_hours[0]) else: x_tick_labels[i] = '{0:02d}-{1:02d}'.format( numpy.min(these_hours), numpy.max(these_hours)) figure_object, axes_object = _plot_auc_and_csi( auc_matrix=auc_matrix, csi_matrix=csi_matrix, num_examples_by_chunk=num_examples_by_chunk, num_bootstrap_reps=num_bootstrap_reps, plot_legend=False) axes_object.set_xticks(x_tick_values) axes_object.set_xticklabels(x_tick_labels, rotation=90.) axes_object.set_xlabel('Hour (UTC)') plotting_utils.label_axes(axes_object=axes_object, label_string='(b)', x_coord_normalized=-0.075, y_coord_normalized=1.02) auc_csi_file_name = '{0:s}/hourly_auc_and_csi.jpg'.format(output_dir_name) print('Saving figure to: "{0:s}"...'.format(auc_csi_file_name)) figure_object.savefig(auc_csi_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) figure_object, axes_object = _plot_pod_and_far( pod_matrix=pod_matrix, far_matrix=far_matrix, num_positive_ex_by_chunk=num_positive_ex_by_chunk, num_bootstrap_reps=num_bootstrap_reps, plot_legend=False) axes_object.set_xticks(x_tick_values) axes_object.set_xticklabels(x_tick_labels, rotation=90.) axes_object.set_xlabel('Hour (UTC)') plotting_utils.label_axes(axes_object=axes_object, label_string='(d)', x_coord_normalized=-0.075, y_coord_normalized=1.02) pod_far_file_name = '{0:s}/hourly_pod_and_far.jpg'.format(output_dir_name) print('Saving figure to: "{0:s}"...'.format(pod_far_file_name)) figure_object.savefig(pod_far_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) return [auc_csi_file_name, pod_far_file_name]
def _plot_one_example( input_feature_matrix, feature_matrix_after_conv, feature_matrix_after_activn, feature_matrix_after_bn, feature_matrix_after_pooling, output_file_name): """Plots entire figure for one example (storm object). :param input_feature_matrix: 2-D numpy array with input features. :param feature_matrix_after_conv: 2-D numpy array with features after convolution. :param feature_matrix_after_activn: 2-D numpy array with features after activation. :param feature_matrix_after_bn: 2-D numpy array with features after batch normalization. :param feature_matrix_after_pooling: 2-D numpy array with features after pooling. :param output_file_name: Path to output file. Figure will be saved here. """ num_output_channels = feature_matrix_after_conv.shape[-1] figure_object, axes_object_matrix = plotting_utils.create_paneled_figure( num_rows=num_output_channels, num_columns=NUM_PANEL_COLUMNS, horizontal_spacing=0., vertical_spacing=0., shared_x_axis=False, shared_y_axis=False, keep_aspect_ratio=True) max_colour_value = numpy.percentile( numpy.absolute(input_feature_matrix), MAX_COLOUR_PERCENTILE ) axes_object_matrix[0, 0].set_title('Input', fontsize=TITLE_FONT_SIZE) for k in range(num_output_channels): if k == 0: _plot_one_feature_map( feature_matrix_2d=input_feature_matrix[..., k], max_colour_value=max_colour_value, plot_colour_bar=False, axes_object=axes_object_matrix[k, 0] ) continue axes_object_matrix[k, 0].axis('off') colour_bar_object = plotting_utils.plot_linear_colour_bar( axes_object_or_matrix=axes_object_matrix[num_output_channels - 1, 0], data_matrix=input_feature_matrix[..., 0], colour_map_object=COLOUR_MAP_OBJECT, min_value=-1 * max_colour_value, max_value=max_colour_value, orientation_string='horizontal', padding=0.015, fraction_of_axis_length=0.9, extend_min=True, extend_max=True, font_size=DEFAULT_FONT_SIZE) tick_values = colour_bar_object.ax.get_xticks() tick_label_strings = ['{0:.1f}'.format(x) for x in tick_values] colour_bar_object.set_ticks(tick_values) colour_bar_object.set_ticklabels(tick_label_strings) letter_label = 'a' plotting_utils.label_axes( axes_object=axes_object_matrix[0, 0], label_string='({0:s})'.format(letter_label), font_size=TITLE_FONT_SIZE, x_coord_normalized=0.125, y_coord_normalized=1.025 ) this_matrix = numpy.stack( (feature_matrix_after_conv, feature_matrix_after_activn), axis=0 ) max_colour_value = numpy.percentile( numpy.absolute(this_matrix), MAX_COLOUR_PERCENTILE ) axes_object_matrix[0, 1].set_title( ' After convolution', fontsize=TITLE_FONT_SIZE) for k in range(num_output_channels): _plot_one_feature_map( feature_matrix_2d=feature_matrix_after_conv[..., k], max_colour_value=max_colour_value, plot_colour_bar=k == num_output_channels - 1, axes_object=axes_object_matrix[k, 1] ) letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes( axes_object=axes_object_matrix[k, 1], label_string='({0:s})'.format(letter_label), font_size=TITLE_FONT_SIZE, x_coord_normalized=0.125, y_coord_normalized=1.025 ) axes_object_matrix[0, 2].set_title( ' After activation', fontsize=TITLE_FONT_SIZE) for k in range(num_output_channels): _plot_one_feature_map( feature_matrix_2d=feature_matrix_after_activn[..., k], max_colour_value=max_colour_value, plot_colour_bar=k == num_output_channels - 1, axes_object=axes_object_matrix[k, 2] ) letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes( axes_object=axes_object_matrix[k, 2], label_string='({0:s})'.format(letter_label), font_size=TITLE_FONT_SIZE, x_coord_normalized=0.125, y_coord_normalized=1.025 ) max_colour_value = numpy.percentile( numpy.absolute(feature_matrix_after_bn), MAX_COLOUR_PERCENTILE ) axes_object_matrix[0, 3].set_title( ' After batch norm', fontsize=TITLE_FONT_SIZE) for k in range(num_output_channels): _plot_one_feature_map( feature_matrix_2d=feature_matrix_after_bn[..., k], max_colour_value=max_colour_value, plot_colour_bar=k == num_output_channels - 1, axes_object=axes_object_matrix[k, 3] ) letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes( axes_object=axes_object_matrix[k, 3], label_string='({0:s})'.format(letter_label), font_size=TITLE_FONT_SIZE, x_coord_normalized=0.125, y_coord_normalized=1.025 ) max_colour_value = numpy.percentile( numpy.absolute(feature_matrix_after_pooling), MAX_COLOUR_PERCENTILE ) axes_object_matrix[0, 4].set_title( 'After pooling', fontsize=TITLE_FONT_SIZE) for k in range(num_output_channels): _plot_one_feature_map( feature_matrix_2d=feature_matrix_after_pooling[..., k], max_colour_value=max_colour_value, plot_colour_bar=k == num_output_channels - 1, axes_object=axes_object_matrix[k, 4] ) letter_label = chr(ord(letter_label) + 1) plotting_utils.label_axes( axes_object=axes_object_matrix[k, 4], label_string='({0:s})'.format(letter_label), font_size=TITLE_FONT_SIZE, x_coord_normalized=0.125, y_coord_normalized=1.025 ) 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(): """Makes event-attribution schematics for 2019 tornado-prediction paper. This is effectively the main method. """ file_system_utils.mkdir_recursive_if_necessary( directory_name=OUTPUT_DIR_NAME) # Interpolation with merger. figure_object, axes_object = _plot_interp_two_times( storm_object_table=_get_data_for_interp_with_merger()[0], tornado_table=_get_data_for_interp_with_merger()[1], legend_font_size=SMALL_LEGEND_FONT_SIZE, legend_position_string='upper right' ) axes_object.set_title('Interpolation with merger') this_file_name = '{0:s}/interp_with_merger_standalone.jpg'.format( OUTPUT_DIR_NAME) print('Saving figure to: "{0:s}"...'.format(this_file_name)) figure_object.savefig( this_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) plotting_utils.label_axes(axes_object=axes_object, label_string='(a)') panel_file_names = ['{0:s}/interp_with_merger.jpg'.format(OUTPUT_DIR_NAME)] print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig( panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) pyplot.close(figure_object) # Interpolation with split. figure_object, axes_object = _plot_interp_two_times( storm_object_table=_get_data_for_interp_with_split()[0], tornado_table=_get_data_for_interp_with_split()[1], legend_font_size=DEFAULT_FONT_SIZE, legend_position_string='upper left' ) axes_object.set_title('Interpolation with split') this_file_name = '{0:s}/interp_with_split_standalone.jpg'.format( OUTPUT_DIR_NAME) print('Saving figure to: "{0:s}"...'.format(this_file_name)) figure_object.savefig( this_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) plotting_utils.label_axes(axes_object=axes_object, label_string='(b)') panel_file_names.append( '{0:s}/interp_with_split.jpg'.format(OUTPUT_DIR_NAME) ) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig( panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) pyplot.close(figure_object) # Simple successors. figure_object, axes_object = _plot_attribution_one_track( storm_object_table=_get_track_for_simple_succ(), plot_legend=True, plot_x_ticks=True, legend_font_size=SMALL_LEGEND_FONT_SIZE, legend_location='lower right' ) this_file_name = '{0:s}/simple_successors_standalone.jpg'.format( OUTPUT_DIR_NAME) print('Saving figure to: "{0:s}"...'.format(this_file_name)) figure_object.savefig( this_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) plotting_utils.label_axes(axes_object=axes_object, label_string='(c)') axes_object.set_title('Linking to simple successors') panel_file_names.append( '{0:s}/simple_successors.jpg'.format(OUTPUT_DIR_NAME) ) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig( panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) pyplot.close(figure_object) # Simple predecessors, example 1. figure_object, axes_object = _plot_attribution_one_track( storm_object_table=_get_track1_for_simple_pred(), plot_legend=True, plot_x_ticks=False, legend_font_size=DEFAULT_FONT_SIZE, legend_location=(0.28, 0.1) ) axes_object.set_title('Simple predecessors, example 1') this_file_name = '{0:s}/simple_predecessors_track1_standalone.jpg'.format( OUTPUT_DIR_NAME) print('Saving figure to: "{0:s}"...'.format(this_file_name)) figure_object.savefig( this_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) plotting_utils.label_axes(axes_object=axes_object, label_string='(d)') axes_object.set_title('Linking to simple predecessors, example 1') panel_file_names.append( '{0:s}/simple_predecessors_track1.jpg'.format(OUTPUT_DIR_NAME) ) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig( panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) pyplot.close(figure_object) # Simple predecessors, example 2. figure_object, axes_object = _plot_attribution_one_track( storm_object_table=_get_track2_for_simple_pred(), plot_legend=False, plot_x_ticks=False ) axes_object.set_title('Simple predecessors, example 2') this_file_name = '{0:s}/simple_predecessors_track2_standalone.jpg'.format( OUTPUT_DIR_NAME) print('Saving figure to: "{0:s}"...'.format(this_file_name)) figure_object.savefig( this_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) plotting_utils.label_axes(axes_object=axes_object, label_string='(e)') axes_object.set_title('Linking to simple predecessors, example 2') panel_file_names.append( '{0:s}/simple_predecessors_track2.jpg'.format(OUTPUT_DIR_NAME) ) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig( panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight' ) pyplot.close(figure_object) # Concatenate all panels into one figure. concat_file_name = '{0:s}/attribution_schemas.jpg'.format(OUTPUT_DIR_NAME) print('Concatenating panels to: "{0:s}"...'.format(concat_file_name)) imagemagick_utils.concatenate_images( input_file_names=panel_file_names, output_file_name=concat_file_name, num_panel_rows=2, num_panel_columns=3) imagemagick_utils.resize_image( input_file_name=concat_file_name, output_file_name=concat_file_name, output_size_pixels=CONCAT_FIGURE_SIZE_PX)
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_histogram_one_target(target_values, target_name, num_bins, letter_label, output_dir_name): """Plots histogram for one target variable. :param target_values: 1-D numpy array of values. :param target_name: Name of target variable. :param num_bins: Number of bins in histogram. :param letter_label: Letter label (will be used to label panel). :param output_dir_name: Name of output directory. Figure will be saved here. :return: output_file_name: Path to output file. """ min_value = (numpy.min(target_values) if target_name == SHORTWAVE_NET_FLUX_NAME else 0.) max_value = numpy.max(target_values) num_examples_by_bin = histograms.create_histogram( input_values=target_values, num_bins=num_bins, min_value=min_value, max_value=max_value)[1] frequency_by_bin = (num_examples_by_bin.astype(float) / numpy.sum(num_examples_by_bin)) bin_edges = numpy.linspace(min_value, max_value, num=num_bins + 1) bin_centers = numpy.array( [numpy.mean(bin_edges[[k, k + 1]]) for k in range(num_bins)]) x_tick_coords = 0.5 + numpy.linspace( 0, num_bins - 1, num=num_bins, dtype=float) if target_name == example_utils.SHORTWAVE_HEATING_RATE_NAME: x_tick_labels = ['{0:.1f}'.format(c) for c in bin_centers] else: x_tick_labels = [ '{0:d}'.format(int(numpy.round(c))) for c in bin_centers ] x_tick_labels = [ x_tick_labels[k] if numpy.mod(k, 3) == 0 else ' ' for k in range(num_bins) ] figure_object, axes_object = pyplot.subplots( 1, 1, figsize=(FIGURE_WIDTH_INCHES, FIGURE_HEIGHT_INCHES)) axes_object.bar(x=x_tick_coords, height=frequency_by_bin, width=1., color=FACE_COLOUR, edgecolor=EDGE_COLOUR, linewidth=EDGE_WIDTH) axes_object.set_xlim([x_tick_coords[0] - 0.5, x_tick_coords[-1] + 0.5]) axes_object.set_xticks(x_tick_coords) axes_object.set_xticklabels(x_tick_labels, rotation=90.) axes_object.set_ylabel('Frequency') axes_object.set_xlabel(TARGET_NAME_TO_VERBOSE[target_name]) plotting_utils.label_axes(axes_object=axes_object, label_string='({0:s})'.format(letter_label)) output_file_name = '{0:s}/histogram_{1:s}.jpg'.format( output_dir_name, target_name.replace('_', '-')) 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) imagemagick_utils.trim_whitespace(input_file_name=output_file_name, output_file_name=output_file_name) imagemagick_utils.resize_image(input_file_name=output_file_name, output_file_name=output_file_name, output_size_pixels=int(2.5e6)) return output_file_name
def _plot_all_scores_one_field(latitude_matrix_deg, longitude_matrix_deg, mae_matrix, rmse_matrix, bias_matrix, mae_skill_score_matrix, mse_skill_score_matrix, correlation_matrix, kge_matrix, skewness_matrix, field_name, output_dir_name, height_m_agl=None): """Plots all evaluation scores 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 mae_matrix: M-by-N numpy array of MAE (mean absolute error) values. :param rmse_matrix: Same but for RMSE (root mean squared error). :param bias_matrix: Same but for bias. :param mae_skill_score_matrix: Same but for MAE skill score. :param mse_skill_score_matrix: Same but for MSE skill score. :param correlation_matrix: Same but for correlation. :param kge_matrix: Same but for KGE (Kling-Gupta efficiency). :param skewness_matrix: Same but for skewness. :param field_name: Name of field for which scores are being plotted. :param output_dir_name: Name of output directory. Figures will be saved here. :param height_m_agl: Height (metres above ground level). If plotting for scalar field, leave this argument alone. """ out_file_name_prefix = '{0:s}/{1:s}'.format(output_dir_name, field_name.replace('_', '-')) if height_m_agl is not None: out_file_name_prefix += '_{0:05d}metres'.format( int(numpy.round(height_m_agl))) panel_file_names = [] # Plot MAE. this_min_value = numpy.nanpercentile(mae_matrix, MIN_COLOUR_PERCENTILE) this_max_value = numpy.nanpercentile(mae_matrix, MAX_COLOUR_PERCENTILE) figure_object, axes_object = _plot_score_one_field( latitude_matrix_deg=latitude_matrix_deg, longitude_matrix_deg=longitude_matrix_deg, score_matrix=mae_matrix, colour_map_object=DEFAULT_COLOUR_MAP_OBJECT, min_colour_value=this_min_value, max_colour_value=this_max_value, taper_cbar_top=True, taper_cbar_bottom=this_min_value != 0, log_scale=False) title_string = 'MAE ({0:s})'.format(TARGET_NAME_TO_UNITS[field_name]) axes_object.set_title(title_string, fontsize=TITLE_FONT_SIZE) plotting_utils.label_axes(axes_object=axes_object, label_string='(a)', font_size=PANEL_LETTER_FONT_SIZE) panel_file_names.append('{0:s}_mae.jpg'.format(out_file_name_prefix)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Plot RMSE. this_min_value = numpy.nanpercentile(rmse_matrix, MIN_COLOUR_PERCENTILE) this_max_value = numpy.nanpercentile(rmse_matrix, MAX_COLOUR_PERCENTILE) figure_object, axes_object = _plot_score_one_field( latitude_matrix_deg=latitude_matrix_deg, longitude_matrix_deg=longitude_matrix_deg, score_matrix=rmse_matrix, colour_map_object=DEFAULT_COLOUR_MAP_OBJECT, min_colour_value=this_min_value, max_colour_value=this_max_value, taper_cbar_top=True, taper_cbar_bottom=this_min_value != 0, log_scale=False) title_string = 'RMSE ({0:s})'.format(TARGET_NAME_TO_UNITS[field_name]) axes_object.set_title(title_string, fontsize=TITLE_FONT_SIZE) plotting_utils.label_axes(axes_object=axes_object, label_string='(b)', font_size=PANEL_LETTER_FONT_SIZE) panel_file_names.append('{0:s}_rmse.jpg'.format(out_file_name_prefix)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Plot bias. this_max_value = numpy.nanpercentile(numpy.absolute(bias_matrix), MAX_COLOUR_PERCENTILE) this_min_value = -1 * this_max_value figure_object, axes_object = _plot_score_one_field( latitude_matrix_deg=latitude_matrix_deg, longitude_matrix_deg=longitude_matrix_deg, score_matrix=bias_matrix, colour_map_object=BIAS_COLOUR_MAP_OBJECT, min_colour_value=this_min_value, max_colour_value=this_max_value, taper_cbar_top=True, taper_cbar_bottom=True, log_scale=False) title_string = 'Bias ({0:s})'.format(TARGET_NAME_TO_UNITS[field_name]) axes_object.set_title(title_string, fontsize=TITLE_FONT_SIZE) plotting_utils.label_axes(axes_object=axes_object, label_string='(c)', font_size=PANEL_LETTER_FONT_SIZE) panel_file_names.append('{0:s}_bias.jpg'.format(out_file_name_prefix)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Plot MAE skill score. this_min_value = numpy.nanpercentile(mae_skill_score_matrix, MIN_COLOUR_PERCENTILE) this_max_value = numpy.nanpercentile(mae_skill_score_matrix, MAX_COLOUR_PERCENTILE) figure_object, axes_object = _plot_score_one_field( latitude_matrix_deg=latitude_matrix_deg, longitude_matrix_deg=longitude_matrix_deg, score_matrix=mae_skill_score_matrix, colour_map_object=DEFAULT_COLOUR_MAP_OBJECT, min_colour_value=this_min_value, max_colour_value=this_max_value, taper_cbar_top=this_max_value != 1, taper_cbar_bottom=True, log_scale=False) axes_object.set_title('MAE skill score', fontsize=TITLE_FONT_SIZE) plotting_utils.label_axes(axes_object=axes_object, label_string='(d)', font_size=PANEL_LETTER_FONT_SIZE) panel_file_names.append('{0:s}_maess.jpg'.format(out_file_name_prefix)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Plot MSE skill score. this_min_value = numpy.nanpercentile(mse_skill_score_matrix, MIN_COLOUR_PERCENTILE) this_max_value = numpy.nanpercentile(mse_skill_score_matrix, MAX_COLOUR_PERCENTILE) figure_object, axes_object = _plot_score_one_field( latitude_matrix_deg=latitude_matrix_deg, longitude_matrix_deg=longitude_matrix_deg, score_matrix=mse_skill_score_matrix, colour_map_object=DEFAULT_COLOUR_MAP_OBJECT, min_colour_value=this_min_value, max_colour_value=this_max_value, taper_cbar_top=this_max_value != 1, taper_cbar_bottom=True, log_scale=False) axes_object.set_title('MSE skill score', fontsize=TITLE_FONT_SIZE) plotting_utils.label_axes(axes_object=axes_object, label_string='(e)', font_size=PANEL_LETTER_FONT_SIZE) panel_file_names.append('{0:s}_msess.jpg'.format(out_file_name_prefix)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Plot correlation. this_min_value = numpy.nanpercentile(correlation_matrix, MIN_COLOUR_PERCENTILE) this_max_value = numpy.nanpercentile(correlation_matrix, MAX_COLOUR_PERCENTILE) figure_object, axes_object = _plot_score_one_field( latitude_matrix_deg=latitude_matrix_deg, longitude_matrix_deg=longitude_matrix_deg, score_matrix=correlation_matrix, colour_map_object=DEFAULT_COLOUR_MAP_OBJECT, min_colour_value=this_min_value, max_colour_value=this_max_value, taper_cbar_top=this_max_value != 1, taper_cbar_bottom=this_min_value != 0, log_scale=False) axes_object.set_title('Correlation', fontsize=TITLE_FONT_SIZE) plotting_utils.label_axes(axes_object=axes_object, label_string='(f)', font_size=PANEL_LETTER_FONT_SIZE) panel_file_names.append( '{0:s}_correlation.jpg'.format(out_file_name_prefix)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Plot KGE. this_min_value = numpy.nanpercentile(kge_matrix, MIN_COLOUR_PERCENTILE) this_max_value = numpy.nanpercentile(kge_matrix, MAX_COLOUR_PERCENTILE) figure_object, axes_object = _plot_score_one_field( latitude_matrix_deg=latitude_matrix_deg, longitude_matrix_deg=longitude_matrix_deg, score_matrix=kge_matrix, colour_map_object=DEFAULT_COLOUR_MAP_OBJECT, min_colour_value=this_min_value, max_colour_value=this_max_value, taper_cbar_top=this_max_value != 1, taper_cbar_bottom=True, log_scale=False) axes_object.set_title('Kling-Gupta efficiency', fontsize=TITLE_FONT_SIZE) plotting_utils.label_axes(axes_object=axes_object, label_string='(g)', font_size=PANEL_LETTER_FONT_SIZE) panel_file_names.append('{0:s}_kge.jpg'.format(out_file_name_prefix)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) # Plot skewness. this_max_value = numpy.nanpercentile(numpy.absolute(skewness_matrix), MAX_COLOUR_PERCENTILE) this_min_value = -1 * this_max_value figure_object, axes_object = _plot_score_one_field( latitude_matrix_deg=latitude_matrix_deg, longitude_matrix_deg=longitude_matrix_deg, score_matrix=skewness_matrix, colour_map_object=SKEWNESS_COLOUR_MAP_OBJECT, min_colour_value=this_min_value, max_colour_value=this_max_value, taper_cbar_top=True, taper_cbar_bottom=True, log_scale=False) axes_object.set_title('Skewness of actual values', fontsize=TITLE_FONT_SIZE) plotting_utils.label_axes(axes_object=axes_object, label_string='(h)', font_size=PANEL_LETTER_FONT_SIZE) panel_file_names.append('{0:s}_skewness.jpg'.format(out_file_name_prefix)) print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1])) figure_object.savefig(panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI, pad_inches=0, bbox_inches='tight') pyplot.close(figure_object) concat_file_name = '{0:s}_all.jpg'.format(out_file_name_prefix) print('Concatenating panels to: "{0:s}"...'.format(concat_file_name)) imagemagick_utils.concatenate_images(input_file_names=panel_file_names, output_file_name=concat_file_name, num_panel_rows=3, num_panel_columns=3) imagemagick_utils.resize_image(input_file_name=concat_file_name, output_file_name=concat_file_name, output_size_pixels=CONCAT_FIGURE_SIZE_PX) for this_file_name in panel_file_names: os.remove(this_file_name)