def plot_error_dist_many_heights(error_matrix, heights_m_agl, min_error_to_plot, max_error_to_plot, axes_object): """Plots error distribution at each height on the same axes. E = number of examples H = number of heights :param error_matrix: E-by-H numpy array of signed errors. :param heights_m_agl: length-H numpy array of heights (metres above ground level). :param min_error_to_plot: Lower limit for x-axis. :param max_error_to_plot: Upper limit for x-axis. :param axes_object: Will plot on these axes (instance of `matplotlib.axes._subplots.AxesSubplot`). """ error_checking.assert_is_numpy_array_without_nan(error_matrix) error_checking.assert_is_numpy_array(error_matrix, num_dimensions=2) num_heights = error_matrix.shape[1] error_checking.assert_is_geq_numpy_array(heights_m_agl, 0.) error_checking.assert_is_numpy_array(heights_m_agl, exact_dimensions=numpy.array( [num_heights], dtype=int)) error_checking.assert_is_greater(max_error_to_plot, min_error_to_plot) boxplot_style_dict = {'color': 'k', 'linewidth': 2} y_values = numpy.linspace(0, num_heights - 1, num=num_heights, dtype=float) for j in range(num_heights): axes_object.boxplot(error_matrix[:, j], widths=0.9, vert=False, notch=False, sym='o', whis=(5, 95), medianprops=boxplot_style_dict, boxprops=boxplot_style_dict, whiskerprops=boxplot_style_dict, capprops=boxplot_style_dict, positions=y_values[[j]]) axes_object.set_xlim(min_error_to_plot, max_error_to_plot) y_tick_strings = profile_plotting.create_height_labels( tick_values_km_agl=METRES_TO_KM * heights_m_agl, use_log_scale=False) for j in range(len(y_tick_strings)): if numpy.mod(j, 5) == 0: continue y_tick_strings[j] = ' ' axes_object.set_yticklabels(y_tick_strings) axes_object.set_ylabel('Height (km AGL)')
def test_create_height_labels_linear(self): """Ensures correct output from create_height_labels. In this case, assuming that height axis is linear. """ these_tick_strings = profile_plotting.create_height_labels( tick_values_km_agl=TICK_VALUES_KM_AGL, use_log_scale=False) self.assertTrue(these_tick_strings == TICK_STRINGS_LINEAR_SCALE)
def _plot_one_example( gradcam_dict, example_index, model_metadata_dict, use_log_scale, title_string, output_dir_name): """Plots class-activation map for one example. :param gradcam_dict: Dictionary read by `gradcam.read_file`. :param example_index: Will plot class-activation map for example with this array index. :param model_metadata_dict: Dictionary read by `neural_net.read_metafile`. :param use_log_scale: See documentation at top of file. :param title_string: Figure title. :param output_dir_name: Name of output directory. Figure will be saved here. """ figure_object, axes_object = pyplot.subplots( 1, 1, figsize=(FIGURE_WIDTH_INCHES, FIGURE_HEIGHT_INCHES) ) if use_log_scale: axes_object.set_yscale('log') class_activations = ( gradcam_dict[gradcam.CLASS_ACTIVATIONS_KEY][example_index, ...] ) example_id_string = gradcam_dict[gradcam.EXAMPLE_IDS_KEY][example_index] generator_option_dict = model_metadata_dict[neural_net.TRAINING_OPTIONS_KEY] heights_km_agl = METRES_TO_KM * ( generator_option_dict[neural_net.HEIGHTS_KEY] ) axes_object.plot( class_activations, heights_km_agl, color=LINE_COLOUR, linewidth=LINE_WIDTH ) y_tick_strings = profile_plotting.create_height_labels( tick_values_km_agl=axes_object.get_yticks(), use_log_scale=use_log_scale ) axes_object.set_yticklabels(y_tick_strings) axes_object.set_xlabel('Class activation') axes_object.set_ylabel('Height (km AGL)') axes_object.set_title(title_string, fontsize=TITLE_FONT_SIZE) output_file_name = '{0:s}/{1:s}.jpg'.format( output_dir_name, example_id_string.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)
def _plot_saliency_one_example(saliency_dict, example_index, model_metadata_dict, colour_map_object, max_colour_percentile, output_dir_name): """Plots saliency maps for one example. :param saliency_dict: Dictionary read by `saliency.read_all_targets_file`. :param example_index: Will plot saliency maps for example with this array index. :param model_metadata_dict: Dictionary read by `neural_net.read_metafile`. :param colour_map_object: See documentation at top of file. :param max_colour_percentile: Same. :param output_dir_name: Same. """ generator_option_dict = model_metadata_dict[ neural_net.TRAINING_OPTIONS_KEY] scalar_predictor_names = ( generator_option_dict[neural_net.SCALAR_PREDICTOR_NAMES_KEY]) scalar_target_names = ( generator_option_dict[neural_net.SCALAR_TARGET_NAMES_KEY]) vector_predictor_names = ( generator_option_dict[neural_net.VECTOR_PREDICTOR_NAMES_KEY]) vector_target_names = ( generator_option_dict[neural_net.VECTOR_TARGET_NAMES_KEY]) heights_km_agl = (METRES_TO_KM * generator_option_dict[neural_net.HEIGHTS_KEY]) height_labels = profile_plotting.create_height_labels( tick_values_km_agl=heights_km_agl, use_log_scale=False) height_labels = [ height_labels[k] if numpy.mod(k, 4) == 0 else ' ' for k in range(len(height_labels)) ] example_id_string = saliency_dict[saliency.EXAMPLE_IDS_KEY][example_index] this_matrix = ( saliency_dict[saliency.SALIENCY_SCALAR_P_SCALAR_T_KEY][example_index, ...]) is_dense_net = len(this_matrix.shape) == 2 if this_matrix.size > 0: if is_dense_net: _plot_saliency_scalar_p_scalar_t( saliency_matrix=this_matrix, predictor_names=scalar_predictor_names, target_names=scalar_target_names, example_id_string=example_id_string, colour_map_object=colour_map_object, max_colour_percentile=max_colour_percentile, output_dir_name=output_dir_name) else: _plot_saliency_vector_p_scalar_t( saliency_matrix=this_matrix, predictor_names=scalar_predictor_names, target_names=scalar_target_names, height_labels=height_labels, example_id_string=example_id_string, colour_map_object=colour_map_object, max_colour_percentile=max_colour_percentile, output_dir_name=output_dir_name) this_matrix = ( saliency_dict[saliency.SALIENCY_VECTOR_P_SCALAR_T_KEY][example_index, ...]) if this_matrix.size > 0: _plot_saliency_vector_p_scalar_t( saliency_matrix=this_matrix, predictor_names=vector_predictor_names, target_names=scalar_target_names, height_labels=height_labels, example_id_string=example_id_string, colour_map_object=colour_map_object, max_colour_percentile=max_colour_percentile, output_dir_name=output_dir_name) this_matrix = ( saliency_dict[saliency.SALIENCY_SCALAR_P_VECTOR_T_KEY][example_index, ...]) if this_matrix.size > 0: if is_dense_net: _plot_saliency_scalar_p_vector_t( saliency_matrix=this_matrix, predictor_names=scalar_predictor_names, target_names=vector_target_names, height_labels=height_labels, example_id_string=example_id_string, colour_map_object=colour_map_object, max_colour_percentile=max_colour_percentile, output_dir_name=output_dir_name) else: _plot_saliency_vector_p_vector_t( saliency_matrix=this_matrix, predictor_names=scalar_predictor_names, target_names=vector_target_names, height_labels=height_labels, example_id_string=example_id_string, colour_map_object=colour_map_object, max_colour_percentile=max_colour_percentile, output_dir_name=output_dir_name) this_matrix = ( saliency_dict[saliency.SALIENCY_VECTOR_P_VECTOR_T_KEY][example_index, ...]) if this_matrix.size > 0: _plot_saliency_vector_p_vector_t( saliency_matrix=this_matrix, predictor_names=vector_predictor_names, target_names=vector_target_names, height_labels=height_labels, example_id_string=example_id_string, colour_map_object=colour_map_object, max_colour_percentile=max_colour_percentile, output_dir_name=output_dir_name)
def plot_taylor_diagram_many_heights( target_stdevs, prediction_stdevs, correlations, heights_m_agl, figure_object, colour_map_object=DEFAULT_HEIGHT_CMAP_OBJECT): """Plots Taylor diagram for many heights on the same axes. Each point should be for the same variable, just at different heights. H = number of heights :param target_stdevs: length-H numpy array with standard deviations of target (actual) values. :param prediction_stdevs: length-H numpy array with standard deviations of predicted values. :param correlations: length-H numpy array of correlations. :param heights_m_agl: length-H numpy array of heights (metres above ground level). :param figure_object: Will plot on this figure (instance of `matplotlib.figure.Figure`). :param colour_map_object: Colour map (instance of `matplotlib.pyplot.cm` or similar). Will be used to colour points in Taylor diagram by height. :return: taylor_diagram_object: Handle for Taylor diagram (instance of `taylor_diagram.TaylorDiagram`). """ error_checking.assert_is_geq_numpy_array(target_stdevs, 0.) error_checking.assert_is_numpy_array(target_stdevs, num_dimensions=1) num_heights = len(target_stdevs) expected_dim = numpy.array([num_heights], dtype=int) error_checking.assert_is_geq_numpy_array(prediction_stdevs, 0.) error_checking.assert_is_numpy_array(prediction_stdevs, exact_dimensions=expected_dim) error_checking.assert_is_geq_numpy_array(correlations, -1., allow_nan=True) error_checking.assert_is_leq_numpy_array(correlations, 1., allow_nan=True) error_checking.assert_is_numpy_array(correlations, exact_dimensions=expected_dim) error_checking.assert_is_geq_numpy_array(heights_m_agl, 0.) error_checking.assert_is_numpy_array(heights_m_agl, exact_dimensions=expected_dim) heights_km_agl = heights_m_agl * METRES_TO_KM colour_norm_object = matplotlib.colors.LogNorm( vmin=numpy.min(heights_km_agl), vmax=numpy.max(heights_km_agl)) mean_target_stdev = numpy.mean(target_stdevs) this_ratio = numpy.maximum( numpy.max(target_stdevs), numpy.max(prediction_stdevs)) / mean_target_stdev taylor_diagram_object = taylor_diagram.TaylorDiagram( refstd=mean_target_stdev, fig=figure_object, srange=(0, this_ratio), extend=False, plot_reference_line=False) this_marker_object = taylor_diagram_object.samplePoints[0] this_marker_object.set_visible(False) for j in range(num_heights): if numpy.isnan(correlations[j]): continue this_colour = colour_map_object(colour_norm_object(heights_km_agl[j])) taylor_diagram_object.add_sample(stddev=target_stdevs[j], corrcoef=1.) this_marker_object = taylor_diagram_object.samplePoints[-1] this_marker_object.set_marker(TAYLOR_TARGET_MARKER_TYPE) this_marker_object.set_markersize(TAYLOR_TARGET_MARKER_SIZE) this_marker_object.set_markerfacecolor(this_colour) this_marker_object.set_markeredgewidth(0) taylor_diagram_object.add_sample(stddev=prediction_stdevs[j], corrcoef=correlations[j]) this_marker_object = taylor_diagram_object.samplePoints[-1] this_marker_object.set_marker(TAYLOR_PREDICTION_MARKER_TYPE) this_marker_object.set_markersize(TAYLOR_PREDICTION_MARKER_SIZE) this_marker_object.set_markerfacecolor(this_colour) this_marker_object.set_markeredgewidth(0) crmse_contour_object = taylor_diagram_object.add_contours(levels=5, colors='0.5') pyplot.clabel(crmse_contour_object, inline=1, fmt='%.0f') taylor_diagram_object.add_grid() taylor_diagram_object._ax.axis[:].major_ticks.set_tick_out(True) colour_bar_object = plotting_utils.plot_colour_bar( axes_object_or_matrix=figure_object.axes[0], data_matrix=heights_km_agl, colour_map_object=colour_map_object, colour_norm_object=colour_norm_object, orientation_string='vertical', extend_min=False, extend_max=False, fraction_of_axis_length=0.85, font_size=FONT_SIZE) tick_values = colour_bar_object.get_ticks() tick_strings = profile_plotting.create_height_labels( tick_values_km_agl=tick_values, use_log_scale=True) colour_bar_object.set_ticks(tick_values) colour_bar_object.set_ticklabels(tick_strings) colour_bar_object.set_label('Height (km AGL)', fontsize=FONT_SIZE) return taylor_diagram_object
def plot_rel_curve_many_heights(mean_target_matrix, mean_prediction_matrix, heights_m_agl, min_value_to_plot, max_value_to_plot, axes_object, colour_map_object=DEFAULT_HEIGHT_CMAP_OBJECT): """Plots reliability curves for many heights on the same axes. Reliability curves should be for the same variable, just at different heights. B = number of forecast bins H = number of heights :param mean_target_matrix: H-by-B numpy array of mean target (actual) values. :param mean_prediction_matrix: H-by-B numpy array of mean predicted values. :param heights_m_agl: length-H numpy array of heights (metres above ground level). :param min_value_to_plot: Minimum value to plot (for both x- and y-axes). :param max_value_to_plot: Max value to plot (for both x- and y-axes). :param axes_object: Will plot on these axes (instance of `matplotlib.axes._subplots.AxesSubplot`). :param colour_map_object: Colour map (instance of `matplotlib.pyplot.cm` or similar). Will be used to colour reliability curves by height. """ error_checking.assert_is_numpy_array(mean_target_matrix, num_dimensions=2) error_checking.assert_is_numpy_array(mean_prediction_matrix, exact_dimensions=numpy.array( mean_target_matrix.shape, dtype=int)) num_heights = mean_target_matrix.shape[0] error_checking.assert_is_geq_numpy_array(heights_m_agl, 0.) error_checking.assert_is_numpy_array(heights_m_agl, exact_dimensions=numpy.array( [num_heights], dtype=int)) error_checking.assert_is_greater(max_value_to_plot, min_value_to_plot) heights_km_agl = heights_m_agl * METRES_TO_KM colour_norm_object = matplotlib.colors.LogNorm( vmin=numpy.min(heights_km_agl), vmax=numpy.max(heights_km_agl)) for j in range(num_heights): this_colour = colour_map_object(colour_norm_object(heights_km_agl[j])) _plot_reliability_curve(axes_object=axes_object, mean_predictions=mean_prediction_matrix[j, :], mean_observations=mean_target_matrix[j, :], line_colour=this_colour, min_value_to_plot=min_value_to_plot, max_value_to_plot=max_value_to_plot) axes_object.set_xlim(min_value_to_plot, max_value_to_plot) axes_object.set_ylim(min_value_to_plot, max_value_to_plot) colour_bar_object = plotting_utils.plot_colour_bar( axes_object_or_matrix=axes_object, data_matrix=heights_km_agl, colour_map_object=colour_map_object, colour_norm_object=colour_norm_object, orientation_string='vertical', extend_min=False, extend_max=False, font_size=FONT_SIZE) tick_values = colour_bar_object.get_ticks() tick_strings = profile_plotting.create_height_labels( tick_values_km_agl=tick_values, use_log_scale=True) colour_bar_object.set_ticks(tick_values) colour_bar_object.set_ticklabels(tick_strings) colour_bar_object.set_label('Height (km AGL)', fontsize=FONT_SIZE)
def plot_score_profile(heights_m_agl, score_values, score_name, line_colour, line_width, use_log_scale, axes_object, are_axes_new, line_style='solid'): """Plots vertical profile of one score. H = number of heights :param heights_m_agl: length-H numpy array of heights (metres above ground level). :param score_values: length-H numpy array with values of score. :param score_name: Name of score (must be accepted by `_check_score_name`). :param line_colour: Line colour (in any format accepted by matplotlib). :param line_width: Line width (in any format accepted by matplotlib). :param use_log_scale: Boolean flag. If True, will plot height (y-axis) in logarithmic scale. If False, will plot height in linear scale. :param axes_object: Will plot on these axes (instance of `matplotlib.axes._subplots.AxesSubplot`). :param are_axes_new: Boolean flag. If True, axes are new (do not already contain plot). :param line_style: Line style (in any format accepted by matplotlib). :return: main_line_handle: Handle for main line (score profile). """ error_checking.assert_is_numpy_array(heights_m_agl, num_dimensions=1) error_checking.assert_is_geq_numpy_array(heights_m_agl, 0.) num_heights = len(heights_m_agl) error_checking.assert_is_numpy_array(score_values, exact_dimensions=numpy.array( [num_heights], dtype=int)) _check_score_name(score_name) error_checking.assert_is_boolean(use_log_scale) error_checking.assert_is_boolean(are_axes_new) if are_axes_new: orig_x_limits = [] orig_y_limits = [] else: orig_x_limits = axes_object.get_xlim() orig_y_limits = axes_object.get_ylim() if use_log_scale: axes_object.set_yscale('log') heights_km_agl = heights_m_agl * METRES_TO_KM min_height_km_agl = numpy.min(heights_km_agl) max_height_km_agl = numpy.max(heights_km_agl) if not are_axes_new: min_height_km_agl = numpy.minimum(min_height_km_agl, orig_y_limits[0]) max_height_km_agl = numpy.maximum(max_height_km_agl, orig_y_limits[1]) skill_score_names = [MAE_SKILL_SCORE_NAME, MSE_SKILL_SCORE_NAME] possibly_negative_score_names = (skill_score_names + [BIAS_NAME, CORRELATION_NAME, KGE_NAME]) if score_name in possibly_negative_score_names: reference_x_coords = numpy.full(2, 0.) reference_y_coords = numpy.array([0, max_height_km_agl], dtype=float) axes_object.plot(reference_x_coords, reference_y_coords, color=REFERENCE_LINE_COLOUR, linestyle='dashed', linewidth=REFERENCE_LINE_WIDTH) finite_indices = numpy.where(numpy.isfinite(score_values))[0] main_line_handle = axes_object.plot(score_values[finite_indices], heights_km_agl[finite_indices], color=line_colour, linestyle=line_style, linewidth=line_width)[0] x_max = numpy.maximum(numpy.max(score_values[finite_indices]), 0.) if not are_axes_new: x_max = numpy.maximum(x_max, orig_x_limits[1]) if score_name in possibly_negative_score_names: x_min = numpy.minimum(numpy.min(score_values[finite_indices]), 0.) if not are_axes_new: x_min = numpy.minimum(x_min, orig_x_limits[0]) if score_name in skill_score_names: x_min = numpy.maximum(x_min, -1.) else: x_min = 0. axes_object.set_xlim(x_min, x_max) if use_log_scale: axes_object.set_ylim(min_height_km_agl, max_height_km_agl) else: axes_object.set_ylim(0, max_height_km_agl) y_tick_strings = profile_plotting.create_height_labels( tick_values_km_agl=axes_object.get_yticks(), use_log_scale=use_log_scale) axes_object.set_yticklabels(y_tick_strings) axes_object.set_ylabel('Height (km AGL)') return main_line_handle
def _plot_gradcam_one_example( gradcam_dict, example_index, model_metadata_dict, colour_map_object, max_colour_percentile, output_dir_name): """Plots class-activation map for one example, all target variables. :param gradcam_dict: Dictionary read by `gradcam.read_all_targets_file`. :param example_index: Will plot class-activation maps for example with this array index. :param model_metadata_dict: Dictionary read by `neural_net.read_metafile`. :param colour_map_object: See documentation at top of file. :param max_colour_percentile: Same. :param output_dir_name: Same. """ generator_option_dict = model_metadata_dict[neural_net.TRAINING_OPTIONS_KEY] target_names = generator_option_dict[neural_net.VECTOR_TARGET_NAMES_KEY] target_names_verbose = [ TARGET_NAME_TO_VERBOSE[n] for n in target_names ] heights_km_agl = ( METRES_TO_KM * generator_option_dict[neural_net.HEIGHTS_KEY] ) height_labels = profile_plotting.create_height_labels( tick_values_km_agl=heights_km_agl, use_log_scale=False ) height_labels = [ height_labels[k] if numpy.mod(k, 4) == 0 else ' ' for k in range(len(height_labels)) ] example_id_string = gradcam_dict[gradcam.EXAMPLE_IDS_KEY][example_index] class_activation_matrix_3d = ( gradcam_dict[gradcam.CLASS_ACTIVATIONS_KEY][example_index, ...] ) num_targets = len(target_names) num_heights = len(height_labels) for k in range(num_targets): class_activation_matrix_2d = class_activation_matrix_3d[..., k] max_colour_value = numpy.percentile( class_activation_matrix_2d, max_colour_percentile ) max_colour_value = numpy.maximum(max_colour_value, 0.001) figure_object, axes_object = pyplot.subplots( 1, 1, figsize=(FIGURE_WIDTH_INCHES, FIGURE_HEIGHT_INCHES) ) axes_object.imshow( numpy.transpose(class_activation_matrix_2d), cmap=colour_map_object, vmin=0., vmax=max_colour_value, origin='lower' ) tick_values = numpy.linspace( 0, num_heights - 1, num=num_heights, dtype=float ) axes_object.set_xticks(tick_values) axes_object.set_yticks(tick_values) axes_object.set_xticklabels( height_labels, fontsize=TICK_LABEL_FONT_SIZE, rotation=90. ) axes_object.set_yticklabels( height_labels, fontsize=TICK_LABEL_FONT_SIZE ) axes_object.set_xlabel('Predictor height (km AGL)') axes_object.set_ylabel('Target height (km AGL)') axes_object.plot( axes_object.get_xlim(), axes_object.get_ylim(), color=REFERENCE_LINE_COLOUR, linestyle='dashed', linewidth=REFERENCE_LINE_WIDTH ) colour_bar_object = plotting_utils.plot_linear_colour_bar( axes_object_or_matrix=axes_object, data_matrix=class_activation_matrix_2d, colour_map_object=colour_map_object, min_value=0., max_value=max_colour_value, orientation_string='horizontal', padding=0.1, extend_min=False, extend_max=True, fraction_of_axis_length=0.8, font_size=DEFAULT_FONT_SIZE ) tick_values = colour_bar_object.get_ticks() tick_strings = ['{0:.1f}'.format(v) for v in tick_values] colour_bar_object.set_ticks(tick_values) colour_bar_object.set_ticklabels(tick_strings) title_string = 'Class-activation map for {0:s}'.format( target_names_verbose[k] ) axes_object.set_title(title_string, fontsize=DEFAULT_FONT_SIZE) output_file_name = '{0:s}/{1:s}_{2:s}.jpg'.format( output_dir_name, example_id_string.replace('_', '-'), target_names[k].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)