def _write_sounding_figure(figure_object, title_string, output_file_name):
    """Writes sounding figure to file.

    :param figure_object: Figure handle (instance of
        `matplotlib.figure.Figure`).
    :param title_string: Figure title.
    :param output_file_name: Path to output file (figure will be saved as image
        here).
    """

    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.resize_image(input_file_name=output_file_name,
                                   output_file_name=output_file_name,
                                   output_size_pixels=SOUNDING_FIGURE_SIZE_PX)

    imagemagick_utils.trim_whitespace(input_file_name=output_file_name,
                                      output_file_name=output_file_name,
                                      border_width_pixels=TITLE_FONT_SIZE + 25)

    _overlay_text(image_file_name=output_file_name,
                  text_string=title_string,
                  x_offset_from_center_px=0,
                  y_offset_from_top_px=0)

    imagemagick_utils.trim_whitespace(input_file_name=output_file_name,
                                      output_file_name=output_file_name,
                                      border_width_pixels=10)
def _run(input_dir_name, output_dir_name):
    """Creates figure showing overall model evaluation.

    This is effectively the main method.

    :param input_dir_name: See documentation at top of file.
    :param output_dir_name: Same.
    """

    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=output_dir_name)

    panel_file_names = [
        '{0:s}/{1:s}'.format(input_dir_name, p)
        for p in PATHLESS_INPUT_FILE_NAMES
    ]
    resized_panel_file_names = [
        '{0:s}/{1:s}'.format(output_dir_name, p)
        for p in PATHLESS_INPUT_FILE_NAMES
    ]

    letter_label = None

    for i in range(len(panel_file_names)):
        print('Resizing panel and saving to: "{0:s}"...'.format(
            resized_panel_file_names[i]))

        imagemagick_utils.trim_whitespace(
            input_file_name=panel_file_names[i],
            output_file_name=resized_panel_file_names[i])

        if letter_label is None:
            letter_label = 'a'
        else:
            letter_label = chr(ord(letter_label) + 1)

        _overlay_text(image_file_name=resized_panel_file_names[i],
                      x_offset_from_left_px=0,
                      y_offset_from_top_px=TITLE_FONT_SIZE,
                      text_string='({0:s})'.format(letter_label))
        imagemagick_utils.resize_image(
            input_file_name=resized_panel_file_names[i],
            output_file_name=resized_panel_file_names[i],
            output_size_pixels=PANEL_SIZE_PX)

    concat_figure_file_name = '{0:s}/overall_evaluation.jpg'.format(
        output_dir_name)
    print(
        'Concatenating panels to: "{0:s}"...'.format(concat_figure_file_name))

    imagemagick_utils.concatenate_images(
        input_file_names=resized_panel_file_names,
        output_file_name=concat_figure_file_name,
        num_panel_rows=NUM_PANEL_ROWS,
        num_panel_columns=NUM_PANEL_COLUMNS)
    imagemagick_utils.resize_image(input_file_name=concat_figure_file_name,
                                   output_file_name=concat_figure_file_name,
                                   output_size_pixels=CONCAT_FIGURE_SIZE_PX)
Exemplo n.º 3
0
def _run(input_dir_name, output_dir_name):
    """Creates figure showing model performance as a function of hyperparams.

    This is effectively the main method.

    :param input_dir_name: See documentation at top of file.
    :param output_dir_name: Same.
    """

    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=output_dir_name)

    num_scores = len(SCORE_NAMES)
    num_dense_layer_counts = len(DENSE_LAYER_COUNTS)

    for j in range(num_scores):
        panel_file_names = [
            '{0:s}/num-dense-layers={1:d}_{2:s}_grid.jpg'.format(
                input_dir_name, d, SCORE_NAMES[j]) for d in DENSE_LAYER_COUNTS
        ]
        resized_panel_file_names = [
            '{0:s}/num-dense-layers={1:d}_{2:s}_grid.jpg'.format(
                output_dir_name, d, SCORE_NAMES[j]) for d in DENSE_LAYER_COUNTS
        ]

        for i in range(num_dense_layer_counts):
            imagemagick_utils.trim_whitespace(
                input_file_name=panel_file_names[i],
                output_file_name=resized_panel_file_names[i])
            imagemagick_utils.resize_image(
                input_file_name=resized_panel_file_names[i],
                output_file_name=resized_panel_file_names[i],
                output_size_pixels=PANEL_SIZE_PX)

        concat_figure_file_name = '{0:s}/{1:s}_grid.jpg'.format(
            output_dir_name, SCORE_NAMES[j])
        print('Concatenating panels to: "{0:s}"...'.format(
            concat_figure_file_name))

        imagemagick_utils.concatenate_images(
            input_file_names=resized_panel_file_names,
            output_file_name=concat_figure_file_name,
            num_panel_rows=NUM_PANEL_ROWS,
            num_panel_columns=NUM_PANEL_COLUMNS)
        imagemagick_utils.resize_image(
            input_file_name=concat_figure_file_name,
            output_file_name=concat_figure_file_name,
            output_size_pixels=CONCAT_FIGURE_SIZE_PX)
        imagemagick_utils.trim_whitespace(
            input_file_name=concat_figure_file_name,
            output_file_name=concat_figure_file_name)
Exemplo n.º 4
0
def _run():
    """Plots dilation of WPC fronts.

    This is effectively the main method.
    """

    print 'Reading data from: "{0:s}"...'.format(FRONT_LINE_FILE_NAME)
    front_line_table = fronts_io.read_polylines_from_file(FRONT_LINE_FILE_NAME)

    print 'Reading data from: "{0:s}"...'.format(FRONTAL_GRID_FILE_NAME)
    frontal_grid_table = fronts_io.read_narr_grids_from_file(
        FRONTAL_GRID_FILE_NAME)

    num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions(
        model_name=nwp_model_utils.NARR_MODEL_NAME)

    ternary_front_matrix = ml_utils.front_table_to_images(
        frontal_grid_table=frontal_grid_table,
        num_rows_per_image=num_grid_rows,
        num_columns_per_image=num_grid_columns)

    _plot_fronts(front_line_table=front_line_table,
                 ternary_front_matrix=ternary_front_matrix,
                 title_string='Observed fronts before dilation',
                 annotation_string='(a)',
                 output_file_name=BEFORE_FILE_NAME)

    ternary_front_matrix = ml_utils.dilate_ternary_target_images(
        target_matrix=ternary_front_matrix,
        dilation_distance_metres=DILATION_DISTANCE_METRES,
        verbose=False)

    _plot_fronts(front_line_table=front_line_table,
                 ternary_front_matrix=ternary_front_matrix,
                 title_string='Observed fronts after dilation',
                 annotation_string='(b)',
                 output_file_name=AFTER_FILE_NAME)

    print 'Concatenating figures to: "{0:s}"...'.format(CONCAT_FILE_NAME)

    imagemagick_utils.concatenate_images(
        input_file_names=[BEFORE_FILE_NAME, AFTER_FILE_NAME],
        output_file_name=CONCAT_FILE_NAME,
        num_panel_rows=1,
        num_panel_columns=2)

    imagemagick_utils.resize_image(input_file_name=CONCAT_FILE_NAME,
                                   output_file_name=CONCAT_FILE_NAME,
                                   output_size_pixels=CONCAT_SIZE_PIXELS)
def _run():
    """Concatenates figures showing dilation procedure and double penalty.

    This is effectively the main method.
    """

    dilation_image_object = Image.open(DILATION_FILE_NAME)
    double_penalty_image_object = Image.open(DOUBLE_PENALTY_FILE_NAME)

    new_dilation_width_px = double_penalty_image_object.size[0]
    width_ratio = (float(new_dilation_width_px) /
                   dilation_image_object.size[0])
    new_dilation_height_px = int(
        numpy.round(dilation_image_object.size[1] * width_ratio))

    small_dilation_file_name = DILATION_FILE_NAME.replace(
        '.jpg', '_resized.jpg')

    print 'Resizing dilation figure to: "{0:s}"...'.format(
        small_dilation_file_name)

    command_string = (
        '/usr/bin/convert "{0:s}" -resize {1:d}x{2:d} "{3:s}"').format(
            DILATION_FILE_NAME, new_dilation_width_px, new_dilation_height_px,
            small_dilation_file_name)

    os.system(command_string)

    print('Concatenating dilation and double-penalty figures to: "{0:s}"...'
          ).format(CONCAT_FILE_NAME)

    imagemagick_utils.concatenate_images(
        input_file_names=[small_dilation_file_name, DOUBLE_PENALTY_FILE_NAME],
        output_file_name=CONCAT_FILE_NAME,
        num_panel_rows=2,
        num_panel_columns=1)

    imagemagick_utils.trim_whitespace(input_file_name=CONCAT_FILE_NAME,
                                      output_file_name=CONCAT_FILE_NAME)

    imagemagick_utils.resize_image(input_file_name=CONCAT_FILE_NAME,
                                   output_file_name=CONCAT_FILE_NAME,
                                   output_size_pixels=CONCAT_SIZE_PIXELS)

    os.remove(small_dilation_file_name)
Exemplo n.º 6
0
def _run():
    """Plots determinization of front probabilities.

    This is effectively the main method.
    """

    prediction_dict = ml_utils.read_gridded_predictions(PREDICTION_FILE_NAME)
    class_probability_matrix = prediction_dict[ml_utils.PROBABILITY_MATRIX_KEY]

    for this_id in front_utils.VALID_INTEGER_IDS:
        if this_id == front_utils.NO_FRONT_INTEGER_ID:
            class_probability_matrix[..., this_id][numpy.isnan(
                class_probability_matrix[..., this_id])] = 1.
        else:
            class_probability_matrix[..., this_id][numpy.isnan(
                class_probability_matrix[..., this_id])] = 0.

    _plot_predictions(output_file_name=BEFORE_FILE_NAME,
                      title_string='Probabilities',
                      annotation_string='(a)',
                      class_probability_matrix=class_probability_matrix)

    predicted_label_matrix = object_eval.determinize_probabilities(
        class_probability_matrix=class_probability_matrix,
        binarization_threshold=BINARIZATION_THRESHOLD)

    _plot_predictions(output_file_name=AFTER_FILE_NAME,
                      title_string='Deterministic predictions',
                      annotation_string='(b)',
                      predicted_label_matrix=predicted_label_matrix)

    print 'Concatenating figures to: "{0:s}"...'.format(CONCAT_FILE_NAME)

    imagemagick_utils.concatenate_images(
        input_file_names=[BEFORE_FILE_NAME, AFTER_FILE_NAME],
        output_file_name=CONCAT_FILE_NAME,
        num_panel_rows=2,
        num_panel_columns=1)

    imagemagick_utils.resize_image(input_file_name=CONCAT_FILE_NAME,
                                   output_file_name=CONCAT_FILE_NAME,
                                   output_size_pixels=CONCAT_SIZE_PIXELS)
Exemplo n.º 7
0
def _run(evaluation_dir_name, num_months_per_chunk, num_hours_per_chunk,
         confidence_level, output_dir_name):
    """Plots temporally subset model evaluation.

    This is effectively the main method.

    :param evaluation_dir_name: See documentation at top of file.
    :param num_months_per_chunk: Same.
    :param num_hours_per_chunk: Same.
    :param confidence_level: Same.
    :param output_dir_name: Same.
    """

    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=output_dir_name)

    panel_file_names = _plot_by_month(
        evaluation_dir_name=evaluation_dir_name,
        num_months_per_chunk=num_months_per_chunk,
        confidence_level=confidence_level,
        output_dir_name=output_dir_name)

    panel_file_names += _plot_by_hour(evaluation_dir_name=evaluation_dir_name,
                                      num_hours_per_chunk=num_hours_per_chunk,
                                      confidence_level=confidence_level,
                                      output_dir_name=output_dir_name)

    concat_file_name = '{0:s}/temporally_subset_eval.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 _write_radar_figures(figure_objects, field_names, composite_name,
                         concat_title_string, output_dir_name):
    """Writes radar figures to file.

    F = number of radar fields

    :param figure_objects: length-F list of figure handles (each an instance of
        `matplotlib.figure.Figure`).
    :param field_names: length-F list of field names.
    :param composite_name: Name of composite (e.g., "after" or "difference").
    :param concat_title_string: Title for concatenated figure.
    :param output_dir_name: Name of output directory (figures will be saved
        here).
    :return: concat_figure_file_name: Path to image file with concatenated
        figure.
    """

    num_fields = len(field_names)
    panel_file_names = [None] * num_fields

    for k in range(num_fields):
        panel_file_names[k] = '{0:s}/{1:s}_{2:s}.jpg'.format(
            output_dir_name, field_names[k].replace('_', '-'), composite_name)

        print('Saving figure to: "{0:s}"...'.format(panel_file_names[k]))

        figure_objects[k].savefig(panel_file_names[k],
                                  dpi=FIGURE_RESOLUTION_DPI,
                                  pad_inches=0,
                                  bbox_inches='tight')
        pyplot.close(figure_objects[k])

    concat_figure_file_name = '{0:s}/radar_{1:s}.jpg'.format(
        output_dir_name, composite_name)

    print(
        'Concatenating panels to: "{0:s}"...'.format(concat_figure_file_name))

    imagemagick_utils.concatenate_images(
        input_file_names=panel_file_names,
        output_file_name=concat_figure_file_name,
        num_panel_rows=1,
        num_panel_columns=num_fields,
        border_width_pixels=50)

    imagemagick_utils.resize_image(input_file_name=concat_figure_file_name,
                                   output_file_name=concat_figure_file_name,
                                   output_size_pixels=CONCAT_FIGURE_SIZE_PX)

    imagemagick_utils.trim_whitespace(input_file_name=concat_figure_file_name,
                                      output_file_name=concat_figure_file_name,
                                      border_width_pixels=TITLE_FONT_SIZE + 25)

    _overlay_text(image_file_name=concat_figure_file_name,
                  text_string=concat_title_string,
                  x_offset_from_center_px=0,
                  y_offset_from_top_px=0)

    imagemagick_utils.trim_whitespace(input_file_name=concat_figure_file_name,
                                      output_file_name=concat_figure_file_name,
                                      border_width_pixels=10)

    return concat_figure_file_name
Exemplo n.º 9
0
def plot_many_soundings(list_of_metpy_dictionaries,
                        title_strings,
                        num_panel_rows,
                        output_file_name,
                        temp_directory_name=None,
                        option_dict=None):
    """Creates paneled figure with many soundings.

    N = number of soundings to plot

    :param list_of_metpy_dictionaries: length-N list of dictionaries.  Each
        dictionary must satisfy the input format for `sounding_dict_for_metpy`
        in `plot_sounding`.
    :param title_strings: length-N list of titles.
    :param num_panel_rows: Number of rows in paneled figure.
    :param output_file_name: Path to output (image) file.
    :param temp_directory_name: Name of temporary directory.  Each panel will be
        stored here, then deleted after the panels have been concatenated into
        the final image.  If `temp_directory_name is None`, will use the default
        temp directory on the local machine.
    :param option_dict: See doc for `plot_sounding`.
    """

    error_checking.assert_is_numpy_array(numpy.array(title_strings),
                                         num_dimensions=1)
    num_soundings = len(title_strings)

    error_checking.assert_is_list(list_of_metpy_dictionaries)
    error_checking.assert_is_geq(len(list_of_metpy_dictionaries),
                                 num_soundings)
    error_checking.assert_is_leq(len(list_of_metpy_dictionaries),
                                 num_soundings)

    error_checking.assert_is_integer(num_panel_rows)
    error_checking.assert_is_geq(num_panel_rows, 1)
    error_checking.assert_is_leq(num_panel_rows, num_soundings)

    file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name)
    if temp_directory_name is not None:
        file_system_utils.mkdir_recursive_if_necessary(
            directory_name=temp_directory_name)

    temp_file_names = [None] * num_soundings
    num_panel_columns = int(numpy.ceil(float(num_soundings) / num_panel_rows))

    for i in range(num_panel_rows):
        for j in range(num_panel_columns):
            this_sounding_index = i * num_panel_columns + j
            if this_sounding_index >= num_soundings:
                break

            plot_sounding(sounding_dict_for_metpy=list_of_metpy_dictionaries[
                this_sounding_index],
                          title_string=title_strings[this_sounding_index],
                          option_dict=option_dict)

            temp_file_names[this_sounding_index] = '{0:s}.jpg'.format(
                tempfile.NamedTemporaryFile(dir=temp_directory_name,
                                            delete=False).name)

            print('Saving sounding to: "{0:s}"...'.format(
                temp_file_names[this_sounding_index]))

            pyplot.savefig(temp_file_names[this_sounding_index],
                           dpi=DOTS_PER_INCH)
            pyplot.close()

            imagemagick_utils.trim_whitespace(
                input_file_name=temp_file_names[this_sounding_index],
                output_file_name=temp_file_names[this_sounding_index],
                border_width_pixels=SINGLE_IMAGE_BORDER_WIDTH_PX)

            imagemagick_utils.resize_image(
                input_file_name=temp_file_names[this_sounding_index],
                output_file_name=temp_file_names[this_sounding_index],
                output_size_pixels=SINGLE_IMAGE_SIZE_PX)

    print('Concatenating panels into one figure: "{0:s}"...'.format(
        output_file_name))

    imagemagick_utils.concatenate_images(
        input_file_names=temp_file_names,
        output_file_name=output_file_name,
        num_panel_rows=num_panel_rows,
        num_panel_columns=num_panel_columns,
        border_width_pixels=PANELED_IMAGE_BORDER_WIDTH_PX)

    for i in range(num_soundings):
        os.remove(temp_file_names[i])
def _run():
    """Plots weird WPC fronts, along with theta_w and wind barbs from NARR.
    This is effectively the main method.
    """

    narr_latitude_matrix_deg, narr_longitude_matrix_deg = (
        nwp_model_utils.get_latlng_grid_point_matrices(
            model_name=nwp_model_utils.NARR_MODEL_NAME))

    narr_rotation_cos_matrix, narr_rotation_sin_matrix = (
        nwp_model_utils.get_wind_rotation_angles(
            latitudes_deg=narr_latitude_matrix_deg,
            longitudes_deg=narr_longitude_matrix_deg,
            model_name=nwp_model_utils.NARR_MODEL_NAME))

    num_panels = len(VALID_TIME_STRINGS)
    panel_file_names = [''] * num_panels
    this_annotation_string = None

    for i in range(num_panels):
        this_time_unix_sec = time_conversion.string_to_unix_sec(
            VALID_TIME_STRINGS[i], DEFAULT_TIME_FORMAT)
        this_title_string = time_conversion.unix_sec_to_string(
            this_time_unix_sec, NICE_TIME_FORMAT)

        if PRESSURE_LEVELS_MB[i] == 1000:
            this_title_string += ' at 1000 mb'
        else:
            this_title_string += ' at surface'

        if this_annotation_string is None:
            this_annotation_string = '(a)'
        else:
            this_orig_character = this_annotation_string[1]
            this_new_character = chr(ord(this_orig_character) + 1)
            this_annotation_string = this_annotation_string.replace(
                this_orig_character, this_new_character)

        this_file_name = _plot_one_time(
            valid_time_string=VALID_TIME_STRINGS[i],
            pressure_level_mb=PRESSURE_LEVELS_MB[i],
            title_string=this_title_string,
            annotation_string=this_annotation_string,
            narr_rotation_cos_matrix=narr_rotation_cos_matrix,
            narr_rotation_sin_matrix=narr_rotation_sin_matrix)

        panel_file_names[i] = this_file_name
        print '\n'

    concat_file_name = '{0:s}/weird_fronts.jpg'.format(OUTPUT_DIR_NAME)

    print 'Concatenating figures to: "{0:s}"...'.format(concat_file_name)

    num_panels = len(panel_file_names)
    num_panel_columns = int(numpy.ceil(float(num_panels) / 2))

    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.trim_whitespace(input_file_name=concat_file_name,
                                      output_file_name=concat_file_name)

    imagemagick_utils.resize_image(input_file_name=concat_file_name,
                                   output_file_name=concat_file_name,
                                   output_size_pixels=CONCAT_SIZE_PIXELS)
Exemplo n.º 11
0
def _run(valid_time_string, smoothing_radius_pixels, front_percentile,
         num_closing_iters, pressure_level_mb, top_narr_directory_name,
         narr_mask_file_name, output_dir_name):
    """Plots NFA (numerical frontal analysis) procedure.

    This is effectively the main method.

    :param valid_time_string: See documentation at top of file.
    :param smoothing_radius_pixels: Same.
    :param front_percentile: Same.
    :param num_closing_iters: Same.
    :param pressure_level_mb: Same.
    :param top_narr_directory_name: Same.
    :param narr_mask_file_name: Same.
    :param output_dir_name: Same.
    """

    cutoff_radius_pixels = 4 * smoothing_radius_pixels
    valid_time_unix_sec = time_conversion.string_to_unix_sec(
        valid_time_string, INPUT_TIME_FORMAT)
    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=output_dir_name)

    if narr_mask_file_name == '':
        num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions(
            model_name=nwp_model_utils.NARR_MODEL_NAME)
        narr_mask_matrix = numpy.full(
            (num_grid_rows, num_grid_columns), 1, dtype=int)
    else:
        print 'Reading mask from: "{0:s}"...\n'.format(narr_mask_file_name)
        narr_mask_matrix = ml_utils.read_narr_mask(narr_mask_file_name)

    wet_bulb_theta_file_name = processed_narr_io.find_file_for_one_time(
        top_directory_name=top_narr_directory_name,
        field_name=processed_narr_io.WET_BULB_THETA_NAME,
        pressure_level_mb=pressure_level_mb,
        valid_time_unix_sec=valid_time_unix_sec)

    print 'Reading data from: "{0:s}"...'.format(wet_bulb_theta_file_name)
    wet_bulb_theta_matrix_kelvins = processed_narr_io.read_fields_from_file(
        wet_bulb_theta_file_name)[0][0, ...]
    wet_bulb_theta_matrix_kelvins = general_utils.fill_nans(
        wet_bulb_theta_matrix_kelvins)

    u_wind_file_name = processed_narr_io.find_file_for_one_time(
        top_directory_name=top_narr_directory_name,
        field_name=processed_narr_io.U_WIND_GRID_RELATIVE_NAME,
        pressure_level_mb=pressure_level_mb,
        valid_time_unix_sec=valid_time_unix_sec)

    print 'Reading data from: "{0:s}"...'.format(u_wind_file_name)
    u_wind_matrix_m_s01 = processed_narr_io.read_fields_from_file(
        u_wind_file_name)[0][0, ...]
    u_wind_matrix_m_s01 = general_utils.fill_nans(u_wind_matrix_m_s01)

    v_wind_file_name = processed_narr_io.find_file_for_one_time(
        top_directory_name=top_narr_directory_name,
        field_name=processed_narr_io.V_WIND_GRID_RELATIVE_NAME,
        pressure_level_mb=pressure_level_mb,
        valid_time_unix_sec=valid_time_unix_sec)

    print 'Reading data from: "{0:s}"...'.format(v_wind_file_name)
    v_wind_matrix_m_s01 = processed_narr_io.read_fields_from_file(
        v_wind_file_name)[0][0, ...]
    v_wind_matrix_m_s01 = general_utils.fill_nans(v_wind_matrix_m_s01)

    unsmoothed_narr_file_name = '{0:s}/unsmoothed_narr_fields.jpg'.format(
        output_dir_name)
    _plot_narr_fields(
        wet_bulb_theta_matrix_kelvins=wet_bulb_theta_matrix_kelvins,
        u_wind_matrix_m_s01=u_wind_matrix_m_s01,
        v_wind_matrix_m_s01=v_wind_matrix_m_s01,
        title_string='Predictors before smoothing', annotation_string='(a)',
        output_file_name=unsmoothed_narr_file_name)

    wet_bulb_theta_matrix_kelvins = nfa.gaussian_smooth_2d_field(
        field_matrix=wet_bulb_theta_matrix_kelvins,
        standard_deviation_pixels=smoothing_radius_pixels,
        cutoff_radius_pixels=cutoff_radius_pixels)

    u_wind_matrix_m_s01 = nfa.gaussian_smooth_2d_field(
        field_matrix=u_wind_matrix_m_s01,
        standard_deviation_pixels=smoothing_radius_pixels,
        cutoff_radius_pixels=cutoff_radius_pixels)

    v_wind_matrix_m_s01 = nfa.gaussian_smooth_2d_field(
        field_matrix=v_wind_matrix_m_s01,
        standard_deviation_pixels=smoothing_radius_pixels,
        cutoff_radius_pixels=cutoff_radius_pixels)

    smoothed_narr_file_name = '{0:s}/smoothed_narr_fields.jpg'.format(
        output_dir_name)
    _plot_narr_fields(
        wet_bulb_theta_matrix_kelvins=wet_bulb_theta_matrix_kelvins,
        u_wind_matrix_m_s01=u_wind_matrix_m_s01,
        v_wind_matrix_m_s01=v_wind_matrix_m_s01,
        title_string='Predictors after smoothing', annotation_string='(b)',
        output_file_name=smoothed_narr_file_name)

    x_spacing_metres, y_spacing_metres = nwp_model_utils.get_xy_grid_spacing(
        model_name=nwp_model_utils.NARR_MODEL_NAME)

    tfp_matrix_kelvins_m02 = nfa.get_thermal_front_param(
        thermal_field_matrix_kelvins=wet_bulb_theta_matrix_kelvins,
        x_spacing_metres=x_spacing_metres, y_spacing_metres=y_spacing_metres)
    tfp_matrix_kelvins_m02[narr_mask_matrix == 0] = 0.

    tfp_file_name = '{0:s}/tfp.jpg'.format(output_dir_name)
    tfp_title_string = (
        r'Thermal front parameter ($\times$ 10$^{-10}$ K m$^{-2}$)')
    _plot_tfp(tfp_matrix_kelvins_m02=tfp_matrix_kelvins_m02,
              title_string=tfp_title_string, annotation_string='(c)',
              output_file_name=tfp_file_name)

    proj_velocity_matrix_m_s01 = nfa.project_wind_to_thermal_gradient(
        u_matrix_grid_relative_m_s01=u_wind_matrix_m_s01,
        v_matrix_grid_relative_m_s01=v_wind_matrix_m_s01,
        thermal_field_matrix_kelvins=wet_bulb_theta_matrix_kelvins,
        x_spacing_metres=x_spacing_metres, y_spacing_metres=y_spacing_metres)

    locating_var_matrix_m01_s01 = nfa.get_locating_variable(
        tfp_matrix_kelvins_m02=tfp_matrix_kelvins_m02,
        projected_velocity_matrix_m_s01=proj_velocity_matrix_m_s01)

    locating_var_file_name = '{0:s}/locating_variable.jpg'.format(
        output_dir_name)
    locating_var_title_string = (
        r'Locating variable ($\times$ 10$^{-9}$ K m$^{-1}$ s$^{-1}$)')
    _plot_locating_variable(
        locating_var_matrix_m01_s01=locating_var_matrix_m01_s01,
        title_string=locating_var_title_string, annotation_string='(d)',
        output_file_name=locating_var_file_name)

    predicted_label_matrix = nfa.get_front_types(
        locating_var_matrix_m01_s01=locating_var_matrix_m01_s01,
        warm_front_percentile=front_percentile,
        cold_front_percentile=front_percentile)

    unclosed_fronts_file_name = '{0:s}/unclosed_fronts.jpg'.format(
        output_dir_name)
    _plot_front_types(
        predicted_label_matrix=predicted_label_matrix,
        title_string='Frontal regions before closing', annotation_string='(e)',
        output_file_name=unclosed_fronts_file_name)

    predicted_label_matrix = front_utils.close_frontal_image(
        ternary_image_matrix=predicted_label_matrix,
        num_iterations=num_closing_iters)

    closed_fronts_file_name = '{0:s}/closed_fronts.jpg'.format(output_dir_name)
    _plot_front_types(
        predicted_label_matrix=predicted_label_matrix,
        title_string='Frontal regions after closing', annotation_string='(f)',
        output_file_name=closed_fronts_file_name)

    concat_file_name = '{0:s}/nfa_procedure.jpg'.format(output_dir_name)
    print 'Concatenating figures to: "{0:s}"...'.format(concat_file_name)

    panel_file_names = [
        unsmoothed_narr_file_name, smoothed_narr_file_name, tfp_file_name,
        locating_var_file_name, unclosed_fronts_file_name,
        closed_fronts_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)

    imagemagick_utils.resize_image(
        input_file_name=concat_file_name, output_file_name=concat_file_name,
        output_size_pixels=CONCAT_SIZE_PIXELS)
Exemplo n.º 12
0
def _plot_one_composite(gradcam_file_name, monte_carlo_file_name,
                        composite_name_abbrev, composite_name_verbose,
                        colour_map_object, min_colour_value, max_colour_value,
                        num_contours, smoothing_radius_grid_cells,
                        monte_carlo_max_fdr, output_dir_name):
    """Plots class-activation map for one composite.

    :param gradcam_file_name: Path to input file (will be read by
        `gradcam.read_file`).
    :param monte_carlo_file_name: Path to Monte Carlo file (will be read by
        `_read_monte_carlo_file`).
    :param composite_name_abbrev: Abbrev composite name (will be used in file
        names).
    :param composite_name_verbose: Verbose composite name (will be used in
        figure title).
    :param colour_map_object: See documentation at top of file.
    :param min_colour_value: Minimum value in colour bar (may be NaN).
    :param max_colour_value: Max value in colour bar (may be NaN).
    :param num_contours: See documentation at top of file.
    :param smoothing_radius_grid_cells: Same.
    :param monte_carlo_max_fdr: Same.
    :param output_dir_name: Name of output directory (figures will be saved
        here).
    :return: main_figure_file_name: Path to main image file created by this
        method.
    :return: min_colour_value: Same as input but cannot be None.
    :return: max_colour_value: Same as input but cannot be None.
    """

    (mean_radar_matrix, mean_class_activn_matrix, significance_matrix,
     model_metadata_dict) = _read_one_composite(
         gradcam_file_name=gradcam_file_name,
         smoothing_radius_grid_cells=smoothing_radius_grid_cells,
         monte_carlo_file_name=monte_carlo_file_name,
         monte_carlo_max_fdr=monte_carlo_max_fdr)

    if numpy.isnan(min_colour_value) or numpy.isnan(max_colour_value):
        min_colour_value_log10 = numpy.log10(
            numpy.percentile(mean_class_activn_matrix, 1.))
        max_colour_value_log10 = numpy.log10(
            numpy.percentile(mean_class_activn_matrix, 99.))

        min_colour_value_log10 = max([min_colour_value_log10, -2.])
        max_colour_value_log10 = max([max_colour_value_log10, -1.])

        min_colour_value_log10 = min([min_colour_value_log10, 1.])
        max_colour_value_log10 = min([max_colour_value_log10, 2.])

        min_colour_value = 10**min_colour_value_log10
        max_colour_value = 10**max_colour_value_log10
    else:
        min_colour_value_log10 = numpy.log10(min_colour_value)
        max_colour_value_log10 = numpy.log10(max_colour_value)

    contour_interval_log10 = (
        (max_colour_value_log10 - min_colour_value_log10) / (num_contours - 1))
    mean_activn_matrix_log10 = numpy.log10(mean_class_activn_matrix)

    training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY]
    field_names = training_option_dict[trainval_io.RADAR_FIELDS_KEY]

    num_fields = mean_radar_matrix.shape[-1]
    num_heights = mean_radar_matrix.shape[-2]

    handle_dict = plot_examples.plot_one_example(
        list_of_predictor_matrices=[mean_radar_matrix],
        model_metadata_dict=model_metadata_dict,
        pmm_flag=True,
        allow_whitespace=True,
        plot_panel_names=True,
        panel_name_font_size=PANEL_NAME_FONT_SIZE,
        add_titles=False,
        label_colour_bars=True,
        colour_bar_length=COLOUR_BAR_LENGTH,
        colour_bar_font_size=COLOUR_BAR_FONT_SIZE,
        num_panel_rows=num_heights)

    figure_objects = handle_dict[plot_examples.RADAR_FIGURES_KEY]
    axes_object_matrices = handle_dict[plot_examples.RADAR_AXES_KEY]

    for k in range(num_fields):
        cam_plotting.plot_many_2d_grids(
            class_activation_matrix_3d=numpy.flip(
                mean_activn_matrix_log10[0, ...], axis=0),
            axes_object_matrix=axes_object_matrices[k],
            colour_map_object=colour_map_object,
            min_contour_level=min_colour_value_log10,
            max_contour_level=max_colour_value_log10,
            contour_interval=contour_interval_log10)

        significance_plotting.plot_many_2d_grids_without_coords(
            significance_matrix=numpy.flip(significance_matrix[0, ...],
                                           axis=0),
            axes_object_matrix=axes_object_matrices[k])

    panel_file_names = [None] * num_fields

    for k in range(num_fields):
        panel_file_names[k] = '{0:s}/{1:s}_{2:s}.jpg'.format(
            output_dir_name, composite_name_abbrev,
            field_names[k].replace('_', '-'))

        print('Saving figure to: "{0:s}"...'.format(panel_file_names[k]))

        figure_objects[k].savefig(panel_file_names[k],
                                  dpi=FIGURE_RESOLUTION_DPI,
                                  pad_inches=0,
                                  bbox_inches='tight')
        pyplot.close(figure_objects[k])

    main_figure_file_name = '{0:s}/{1:s}_gradcam.jpg'.format(
        output_dir_name, composite_name_abbrev)

    print('Concatenating panels to: "{0:s}"...'.format(main_figure_file_name))
    imagemagick_utils.concatenate_images(
        input_file_names=panel_file_names,
        output_file_name=main_figure_file_name,
        num_panel_rows=1,
        num_panel_columns=num_fields,
        border_width_pixels=50)
    imagemagick_utils.resize_image(input_file_name=main_figure_file_name,
                                   output_file_name=main_figure_file_name,
                                   output_size_pixels=CONCAT_FIGURE_SIZE_PX)
    imagemagick_utils.trim_whitespace(input_file_name=main_figure_file_name,
                                      output_file_name=main_figure_file_name,
                                      border_width_pixels=TITLE_FONT_SIZE + 25)
    _overlay_text(image_file_name=main_figure_file_name,
                  x_offset_from_center_px=0,
                  y_offset_from_top_px=0,
                  text_string=composite_name_verbose)
    imagemagick_utils.trim_whitespace(input_file_name=main_figure_file_name,
                                      output_file_name=main_figure_file_name,
                                      border_width_pixels=10)

    return main_figure_file_name, min_colour_value, max_colour_value
Exemplo n.º 13
0
def _run():
    """Plots conversion of gridded probabilities into objects.

    This is effectively the main method.
    """

    prediction_dict = ml_utils.read_gridded_predictions(PREDICTION_FILE_NAME)
    class_probability_matrix = prediction_dict[ml_utils.PROBABILITY_MATRIX_KEY]

    for this_id in front_utils.VALID_INTEGER_IDS:
        if this_id == front_utils.NO_FRONT_INTEGER_ID:
            class_probability_matrix[..., this_id][numpy.isnan(
                class_probability_matrix[..., this_id])] = 1.
        else:
            class_probability_matrix[..., this_id][numpy.isnan(
                class_probability_matrix[..., this_id])] = 0.

    predicted_label_matrix = object_eval.determinize_probabilities(
        class_probability_matrix=class_probability_matrix,
        binarization_threshold=BINARIZATION_THRESHOLD)

    _plot_predictions(predicted_label_matrix=predicted_label_matrix,
                      title_string='All frontal regions',
                      annotation_string='(b)',
                      output_file_name=ALL_REGIONS_FILE_NAME)

    valid_time_unix_sec = time_conversion.string_to_unix_sec(
        VALID_TIME_STRING, TIME_FORMAT)
    valid_times_unix_sec = numpy.array([valid_time_unix_sec], dtype=int)
    predicted_region_table = object_eval.images_to_regions(
        predicted_label_matrix=predicted_label_matrix,
        image_times_unix_sec=valid_times_unix_sec)

    num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions(
        model_name=nwp_model_utils.NARR_MODEL_NAME)
    grid_spacing_metres = nwp_model_utils.get_xy_grid_spacing(
        model_name=nwp_model_utils.NARR_MODEL_NAME)[0]

    predicted_region_table = object_eval.discard_regions_with_small_area(
        predicted_region_table=predicted_region_table,
        x_grid_spacing_metres=grid_spacing_metres,
        y_grid_spacing_metres=grid_spacing_metres,
        min_area_metres2=MIN_REGION_AREA_METRES2)
    predicted_label_matrix = object_eval.regions_to_images(
        predicted_region_table=predicted_region_table,
        num_grid_rows=num_grid_rows,
        num_grid_columns=num_grid_columns)

    _plot_predictions(predicted_label_matrix=predicted_label_matrix,
                      title_string='Large frontal regions',
                      annotation_string='(c)',
                      output_file_name=LARGE_REGIONS_FILE_NAME)

    predicted_region_table = object_eval.skeletonize_frontal_regions(
        predicted_region_table=predicted_region_table,
        num_grid_rows=num_grid_rows,
        num_grid_columns=num_grid_columns)
    predicted_label_matrix = object_eval.regions_to_images(
        predicted_region_table=predicted_region_table,
        num_grid_rows=num_grid_rows,
        num_grid_columns=num_grid_columns)

    _plot_predictions(predicted_label_matrix=predicted_label_matrix,
                      title_string='All skeleton lines',
                      annotation_string='(d)',
                      output_file_name=ALL_SKELETONS_FILE_NAME)

    predicted_region_table = object_eval.find_main_skeletons(
        predicted_region_table=predicted_region_table,
        image_times_unix_sec=valid_times_unix_sec,
        num_grid_rows=num_grid_rows,
        num_grid_columns=num_grid_columns,
        x_grid_spacing_metres=grid_spacing_metres,
        y_grid_spacing_metres=grid_spacing_metres,
        min_endpoint_length_metres=MIN_ENDPOINT_LENGTH_METRES)

    predicted_label_matrix = object_eval.regions_to_images(
        predicted_region_table=predicted_region_table,
        num_grid_rows=num_grid_rows,
        num_grid_columns=num_grid_columns)

    _plot_predictions(predicted_label_matrix=predicted_label_matrix,
                      title_string='Main skeleton lines',
                      annotation_string='(e)',
                      output_file_name=MAIN_SKELETONS_FILE_NAME)

    print 'Concatenating figures to: "{0:s}"...'.format(CONCAT_FILE_NAME)

    panel_file_names = [
        PROBABILITY_FILE_NAME, ALL_REGIONS_FILE_NAME, LARGE_REGIONS_FILE_NAME,
        ALL_SKELETONS_FILE_NAME, MAIN_SKELETONS_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_SIZE_PIXELS)
Exemplo n.º 14
0
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
Exemplo n.º 15
0
def _run(input_dir_name, site_names_for_reliability, site_name_for_histogram,
         output_dir_name):
    """Creates figure showing overall model evaluation.

    This is effectively the main method.

    :param input_dir_name: See documentation at top of file.
    :param site_names_for_reliability: Same.
    :param site_name_for_histogram: Same.
    :param output_dir_name: Same.
    """

    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=output_dir_name)

    pathless_input_file_names = [
        'shortwave-surface-down-flux-w-m02_attributes_{0:s}.jpg'.format(
            site_name_for_histogram),
        'shortwave-toa-up-flux-w-m02_attributes_{0:s}.jpg'.format(
            site_name_for_histogram),
        'net-shortwave-flux-w-m02_attributes_{0:s}.jpg'.format(
            site_name_for_histogram),
        'shortwave-heating-rate-k-day01_bias_profile.jpg',
        'shortwave-heating-rate-k-day01_mean-absolute-error_profile.jpg',
        'shortwave-heating-rate-k-day01_mae-skill-score_profile.jpg'
    ]

    num_sites_for_relia = len(site_names_for_reliability)

    for j in range(num_sites_for_relia):
        this_file_name = (
            'shortwave-heating-rate-k-day01_reliability_{0:s}.jpg').format(
                site_names_for_reliability[j])

        pathless_input_file_names.append(this_file_name)

    panel_file_names = [
        '{0:s}/{1:s}'.format(input_dir_name, p)
        for p in pathless_input_file_names
    ]
    resized_panel_file_names = [
        '{0:s}/{1:s}'.format(output_dir_name, p)
        for p in pathless_input_file_names
    ]

    letter_label = None

    for i in range(len(panel_file_names)):
        print('Resizing panel and saving to: "{0:s}"...'.format(
            resized_panel_file_names[i]))

        imagemagick_utils.trim_whitespace(
            input_file_name=panel_file_names[i],
            output_file_name=resized_panel_file_names[i])

        if letter_label is None:
            letter_label = 'a'
        else:
            letter_label = chr(ord(letter_label) + 1)

        _overlay_text(image_file_name=resized_panel_file_names[i],
                      x_offset_from_left_px=0,
                      y_offset_from_top_px=TITLE_FONT_SIZE,
                      text_string='({0:s})'.format(letter_label))
        imagemagick_utils.resize_image(
            input_file_name=resized_panel_file_names[i],
            output_file_name=resized_panel_file_names[i],
            output_size_pixels=PANEL_SIZE_PX)

    concat_figure_file_name = '{0:s}/evaluation_by_site.jpg'.format(
        output_dir_name)
    print(
        'Concatenating panels to: "{0:s}"...'.format(concat_figure_file_name))

    imagemagick_utils.concatenate_images(
        input_file_names=resized_panel_file_names,
        output_file_name=concat_figure_file_name,
        num_panel_rows=NUM_PANEL_ROWS,
        num_panel_columns=NUM_PANEL_COLUMNS)
    imagemagick_utils.resize_image(input_file_name=concat_figure_file_name,
                                   output_file_name=concat_figure_file_name,
                                   output_size_pixels=CONCAT_FIGURE_SIZE_PX)
def _run(saliency_file_names, monte_carlo_file_names, composite_names,
         colour_map_name, max_colour_values, half_num_contours,
         smoothing_radius_grid_cells, output_dir_name):
    """Makes figure with sanity checks for saliency maps.

    This is effectively the main method.

    :param saliency_file_names: See documentation at top of file.
    :param monte_carlo_file_names: Same.
    :param composite_names: Same.
    :param colour_map_name: Same.
    :param max_colour_values: Same.
    :param half_num_contours: Same.
    :param smoothing_radius_grid_cells: Same.
    :param output_dir_name: Same.
    """

    # Process input args.
    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=output_dir_name)

    if smoothing_radius_grid_cells <= 0:
        smoothing_radius_grid_cells = None

    colour_map_object = pyplot.cm.get_cmap(colour_map_name)
    error_checking.assert_is_geq(half_num_contours, 5)

    num_composites = len(saliency_file_names)
    expected_dim = numpy.array([num_composites], dtype=int)
    error_checking.assert_is_numpy_array(numpy.array(composite_names),
                                         exact_dimensions=expected_dim)
    error_checking.assert_is_numpy_array(numpy.array(monte_carlo_file_names),
                                         exact_dimensions=expected_dim)

    monte_carlo_file_names = [
        None if f in NONE_STRINGS else f for f in monte_carlo_file_names
    ]

    max_colour_values[max_colour_values <= 0] = numpy.nan
    error_checking.assert_is_numpy_array(max_colour_values,
                                         exact_dimensions=expected_dim)

    composite_names_abbrev = [
        n.replace('_', '-').lower() for n in composite_names
    ]
    composite_names_verbose = [
        '({0:s}) {1:s}'.format(chr(ord('a') + i),
                               composite_names[i].replace('_', ' '))
        for i in range(num_composites)
    ]

    panel_file_names = [None] * num_composites

    for i in range(num_composites):
        panel_file_names[i], max_colour_values[i] = _plot_one_composite(
            saliency_file_name=saliency_file_names[i],
            monte_carlo_file_name=monte_carlo_file_names[i],
            composite_name_abbrev=composite_names_abbrev[i],
            composite_name_verbose=composite_names_verbose[i],
            colour_map_object=colour_map_object,
            max_colour_value=max_colour_values[i],
            half_num_contours=half_num_contours,
            smoothing_radius_grid_cells=smoothing_radius_grid_cells,
            output_dir_name=output_dir_name)

        _add_colour_bar(figure_file_name=panel_file_names[i],
                        colour_map_object=colour_map_object,
                        max_colour_value=max_colour_values[i],
                        temporary_dir_name=output_dir_name)

        print('\n')

    figure_file_name = '{0:s}/saliency_concat.jpg'.format(output_dir_name)
    print('Concatenating panels to: "{0:s}"...'.format(figure_file_name))

    num_panel_rows = int(numpy.ceil(numpy.sqrt(num_composites)))
    num_panel_columns = int(numpy.floor(
        float(num_composites) / num_panel_rows))

    imagemagick_utils.concatenate_images(input_file_names=panel_file_names,
                                         output_file_name=figure_file_name,
                                         border_width_pixels=100,
                                         num_panel_rows=num_panel_rows,
                                         num_panel_columns=num_panel_columns)
    imagemagick_utils.trim_whitespace(input_file_name=figure_file_name,
                                      output_file_name=figure_file_name,
                                      border_width_pixels=10)
    imagemagick_utils.resize_image(input_file_name=figure_file_name,
                                   output_file_name=figure_file_name,
                                   output_size_pixels=CONCAT_FIGURE_SIZE_PX)
def _plot_sounding_saliency(
        saliency_matrix, colour_map_object, max_colour_value, sounding_matrix,
        saliency_dict, model_metadata_dict, output_dir_name, pmm_flag,
        example_index=None):
    """Plots saliency for sounding.

    H = number of sounding heights
    F = number of sounding fields

    If plotting a composite rather than one example, `full_storm_id_string` and
    `storm_time_unix_sec` can be None.

    :param saliency_matrix: H-by-F numpy array of saliency values.
    :param colour_map_object: See documentation at top of file.
    :param max_colour_value: Max value in colour scheme for saliency.
    :param sounding_matrix: H-by-F numpy array of actual sounding values.
    :param saliency_dict: Dictionary returned from
        `saliency_maps.read_standard_file` or `saliency_maps.read_pmm_file`.
    :param model_metadata_dict: Dictionary returned by
        `cnn.read_model_metadata`.
    :param output_dir_name: Path to output directory.  Figure will be saved
        here.
    :param pmm_flag: Boolean flag.  If True, will plot composite rather than one
        example.
    :param example_index: [used only if `pmm_flag == False`]
        Will plot the [i]th example, where i = `example_index`.
    """

    if pmm_flag:
        example_index = 0

    training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY]
    sounding_field_names = training_option_dict[trainval_io.SOUNDING_FIELDS_KEY]
    sounding_heights_m_agl = training_option_dict[
        trainval_io.SOUNDING_HEIGHTS_KEY]

    sounding_matrix = numpy.expand_dims(sounding_matrix, axis=0)

    if saliency_maps.SOUNDING_PRESSURES_KEY in saliency_dict:
        pressure_matrix_pascals = numpy.expand_dims(
            saliency_dict[saliency_maps.SOUNDING_PRESSURES_KEY], axis=-1
        )

        pressure_matrix_pascals = pressure_matrix_pascals[[example_index], ...]
        sounding_matrix = numpy.concatenate(
            (sounding_matrix, pressure_matrix_pascals), axis=-1
        )

        sounding_dict_for_metpy = dl_utils.soundings_to_metpy_dictionaries(
            sounding_matrix=sounding_matrix,
            field_names=sounding_field_names + [soundings.PRESSURE_NAME]
        )[0]
    else:
        sounding_dict_for_metpy = dl_utils.soundings_to_metpy_dictionaries(
            sounding_matrix=sounding_matrix, field_names=sounding_field_names,
            height_levels_m_agl=sounding_heights_m_agl,
            storm_elevations_m_asl=numpy.array([0.])
        )[0]

    if pmm_flag:
        full_storm_id_string = None
        storm_time_unix_sec = None
        title_string = 'PMM composite'
    else:
        full_storm_id_string = saliency_dict[saliency_maps.FULL_IDS_KEY][
            example_index]
        storm_time_unix_sec = saliency_dict[saliency_maps.STORM_TIMES_KEY][
            example_index]

        title_string = 'Storm "{0:s}" at {1:s}'.format(
            full_storm_id_string,
            time_conversion.unix_sec_to_string(
                storm_time_unix_sec, plot_input_examples.TIME_FORMAT)
        )

    sounding_plotting.plot_sounding(
        sounding_dict_for_metpy=sounding_dict_for_metpy,
        title_string=title_string)

    left_panel_file_name = plot_input_examples.metadata_to_file_name(
        output_dir_name=output_dir_name, is_sounding=False, pmm_flag=pmm_flag,
        full_storm_id_string=full_storm_id_string,
        storm_time_unix_sec=storm_time_unix_sec,
        radar_field_name='sounding-actual')

    print('Saving figure to file: "{0:s}"...'.format(left_panel_file_name))
    pyplot.savefig(left_panel_file_name, dpi=FIGURE_RESOLUTION_DPI)
    pyplot.close()

    imagemagick_utils.trim_whitespace(
        input_file_name=left_panel_file_name,
        output_file_name=left_panel_file_name)

    saliency_plotting.plot_saliency_for_sounding(
        saliency_matrix=saliency_matrix,
        sounding_field_names=sounding_field_names,
        pressure_levels_mb=sounding_dict_for_metpy[
            soundings.PRESSURE_COLUMN_METPY],
        colour_map_object=colour_map_object,
        max_absolute_colour_value=max_colour_value)

    right_panel_file_name = plot_input_examples.metadata_to_file_name(
        output_dir_name=output_dir_name, is_sounding=False, pmm_flag=pmm_flag,
        full_storm_id_string=full_storm_id_string,
        storm_time_unix_sec=storm_time_unix_sec,
        radar_field_name='sounding-saliency')

    print('Saving figure to file: "{0:s}"...'.format(right_panel_file_name))
    pyplot.savefig(right_panel_file_name, dpi=FIGURE_RESOLUTION_DPI)
    pyplot.close()

    imagemagick_utils.trim_whitespace(
        input_file_name=right_panel_file_name,
        output_file_name=right_panel_file_name)

    concat_file_name = plot_input_examples.metadata_to_file_name(
        output_dir_name=output_dir_name, is_sounding=True, pmm_flag=pmm_flag,
        full_storm_id_string=full_storm_id_string,
        storm_time_unix_sec=storm_time_unix_sec)

    print('Concatenating figures to: "{0:s}"...\n'.format(concat_file_name))
    imagemagick_utils.concatenate_images(
        input_file_names=[left_panel_file_name, right_panel_file_name],
        output_file_name=concat_file_name, num_panel_rows=1,
        num_panel_columns=2)

    imagemagick_utils.resize_image(
        input_file_name=concat_file_name, output_file_name=concat_file_name,
        output_size_pixels=SOUNDING_IMAGE_SIZE_PX)

    os.remove(left_panel_file_name)
    os.remove(right_panel_file_name)
Exemplo n.º 18
0
def _run(input_dir_name, heights_m_agl, output_dir_name):
    """Creates figure showing overall model evaluation.

    This is effectively the main method.

    :param input_dir_name: See documentation at top of file.
    :param heights_m_agl: Same.
    :param output_dir_name: Same.
    """

    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=output_dir_name)

    num_heights = len(heights_m_agl)
    pathless_input_file_names = []

    for j in range(num_heights):
        first_file_name = (
            'shortwave-heating-rate-k-day01_{0:05d}metres_scores_without_units'
            '.jpg').format(heights_m_agl[j])

        second_file_name = (
            'shortwave-heating-rate-k-day01_{0:05d}metres_scores_with_units.jpg'
        ).format(heights_m_agl[j])

        pathless_input_file_names += [first_file_name, second_file_name]

    pathless_input_file_names += [
        'net-shortwave-flux-w-m02_scores_without_units.jpg',
        'net-shortwave-flux-w-m02_scores_with_units.jpg'
    ]

    panel_file_names = [
        '{0:s}/{1:s}'.format(input_dir_name, p)
        for p in pathless_input_file_names
    ]
    resized_panel_file_names = [
        '{0:s}/{1:s}'.format(output_dir_name, p)
        for p in pathless_input_file_names
    ]

    letter_label = None

    for i in range(len(panel_file_names)):
        print('Resizing panel and saving to: "{0:s}"...'.format(
            resized_panel_file_names[i]))

        imagemagick_utils.trim_whitespace(
            input_file_name=panel_file_names[i],
            output_file_name=resized_panel_file_names[i])

        if letter_label is None:
            letter_label = 'a'
        else:
            letter_label = chr(ord(letter_label) + 1)

        image_matrix = Image.open(resized_panel_file_names[i])
        _, figure_height_px = image_matrix.size

        _overlay_text(image_file_name=resized_panel_file_names[i],
                      x_offset_from_left_px=0,
                      y_offset_from_top_px=figure_height_px - 50,
                      text_string='({0:s})'.format(letter_label))
        imagemagick_utils.resize_image(
            input_file_name=resized_panel_file_names[i],
            output_file_name=resized_panel_file_names[i],
            output_size_pixels=PANEL_SIZE_PX)

    concat_figure_file_name = '{0:s}/evaluation_by_time.jpg'.format(
        output_dir_name)
    print(
        'Concatenating panels to: "{0:s}"...'.format(concat_figure_file_name))

    imagemagick_utils.concatenate_images(
        input_file_names=resized_panel_file_names,
        output_file_name=concat_figure_file_name,
        num_panel_rows=num_heights + 1,
        num_panel_columns=NUM_PANEL_COLUMNS)
    imagemagick_utils.resize_image(input_file_name=concat_figure_file_name,
                                   output_file_name=concat_figure_file_name,
                                   output_size_pixels=CONCAT_FIGURE_SIZE_PX)
def _plot_one_example(
        radar_matrix, sounding_matrix, sounding_pressures_pascals,
        full_storm_id_string, storm_time_unix_sec, model_metadata_dict,
        output_dir_name):
    """Plots predictors for one example.

    M = number of rows in radar grid
    N = number of columns in radar grid
    H_r = number of heights in radar grid
    F_r = number of radar fields
    H_s = number of sounding heights
    F_s = number of sounding fields

    :param radar_matrix: numpy array (1 x M x N x H_r x F_r) of radar values.
    :param sounding_matrix: numpy array (1 x H_s x F_s) of sounding values.
    :param sounding_pressures_pascals: numpy array (length H_s) of sounding
        pressures.
    :param full_storm_id_string: Full storm ID.
    :param storm_time_unix_sec: Valid time.
    :param model_metadata_dict: Dictionary returned by
        `cnn.read_model_metadata`.
    :param output_dir_name: Name of output directory (figures will be saved
        here).
    :return: radar_figure_file_name: Path to radar figure created by this
        method.
    """

    training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY]
    radar_field_names = training_option_dict[trainval_io.RADAR_FIELDS_KEY]

    num_radar_fields = radar_matrix.shape[-1]
    num_radar_heights = radar_matrix.shape[-2]

    handle_dict = plot_examples.plot_one_example(
        list_of_predictor_matrices=[radar_matrix, sounding_matrix],
        model_metadata_dict=model_metadata_dict,
        pmm_flag=False, example_index=0, plot_sounding=True,
        sounding_pressures_pascals=sounding_pressures_pascals,
        allow_whitespace=True, plot_panel_names=True,
        panel_name_font_size=PANEL_NAME_FONT_SIZE,
        add_titles=False, label_colour_bars=True,
        colour_bar_length=COLOUR_BAR_LENGTH,
        colour_bar_font_size=COLOUR_BAR_FONT_SIZE,
        num_panel_rows=num_radar_heights
    )

    sounding_file_name = plot_examples.metadata_to_file_name(
        output_dir_name=output_dir_name, is_sounding=True, pmm_flag=False,
        full_storm_id_string=full_storm_id_string,
        storm_time_unix_sec=storm_time_unix_sec
    )

    print('Saving figure to: "{0:s}"...'.format(sounding_file_name))

    sounding_figure_object = handle_dict[plot_examples.SOUNDING_FIGURE_KEY]
    sounding_figure_object.savefig(
        sounding_file_name, dpi=FIGURE_RESOLUTION_DPI,
        pad_inches=0, bbox_inches='tight'
    )
    pyplot.close(sounding_figure_object)

    figure_objects = handle_dict[plot_examples.RADAR_FIGURES_KEY]
    panel_file_names = [None] * num_radar_fields

    for k in range(num_radar_fields):
        panel_file_names[k] = plot_examples.metadata_to_file_name(
            output_dir_name=output_dir_name, is_sounding=False, pmm_flag=False,
            full_storm_id_string=full_storm_id_string,
            storm_time_unix_sec=storm_time_unix_sec,
            radar_field_name=radar_field_names[k]
        )

        print('Saving figure to: "{0:s}"...'.format(panel_file_names[k]))

        figure_objects[k].savefig(
            panel_file_names[k], dpi=FIGURE_RESOLUTION_DPI,
            pad_inches=0, bbox_inches='tight'
        )
        pyplot.close(figure_objects[k])

    radar_figure_file_name = plot_examples.metadata_to_file_name(
        output_dir_name=output_dir_name, is_sounding=False, pmm_flag=False,
        full_storm_id_string=full_storm_id_string,
        storm_time_unix_sec=storm_time_unix_sec
    )

    print('Concatenating panels to: "{0:s}"...'.format(radar_figure_file_name))

    imagemagick_utils.concatenate_images(
        input_file_names=panel_file_names,
        output_file_name=radar_figure_file_name,
        num_panel_rows=1, num_panel_columns=num_radar_fields,
        border_width_pixels=50
    )
    imagemagick_utils.resize_image(
        input_file_name=radar_figure_file_name,
        output_file_name=radar_figure_file_name,
        output_size_pixels=CONCAT_FIGURE_SIZE_PX
    )
    imagemagick_utils.trim_whitespace(
        input_file_name=radar_figure_file_name,
        output_file_name=radar_figure_file_name,
        border_width_pixels=10
    )

    for this_file_name in panel_file_names:
        os.remove(this_file_name)

    return radar_figure_file_name
Exemplo n.º 20
0
def _run(gradcam_file_names, monte_carlo_file_names, composite_names,
         colour_map_name, min_colour_values, max_colour_values, num_contours,
         smoothing_radius_grid_cells, monte_carlo_max_fdr, output_dir_name):
    """Makes figure with gradient-weighted class-activation maps (Grad-CAM).

    This is effectively the main method.

    :param gradcam_file_names: See documentation at top of file.
    :param monte_carlo_file_names: Same.
    :param composite_names: Same.
    :param colour_map_name: Same.
    :param min_colour_values: Same.
    :param max_colour_values: Same.
    :param num_contours: Same.
    :param smoothing_radius_grid_cells: Same.
    :param output_dir_name: Same.
    """

    if smoothing_radius_grid_cells <= 0:
        smoothing_radius_grid_cells = None
    if monte_carlo_max_fdr <= 0:
        monte_carlo_max_fdr = None

    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=output_dir_name)

    colour_map_object = pyplot.cm.get_cmap(colour_map_name)
    error_checking.assert_is_geq(num_contours, 10)

    num_composites = len(gradcam_file_names)
    expected_dim = numpy.array([num_composites], dtype=int)
    error_checking.assert_is_numpy_array(numpy.array(composite_names),
                                         exact_dimensions=expected_dim)
    error_checking.assert_is_numpy_array(numpy.array(monte_carlo_file_names),
                                         exact_dimensions=expected_dim)

    monte_carlo_file_names = [
        None if f in NONE_STRINGS else f for f in monte_carlo_file_names
    ]

    nan_indices = numpy.where(
        numpy.logical_or(max_colour_values < 0, min_colour_values < 0))[0]
    min_colour_values[nan_indices] = numpy.nan
    max_colour_values[nan_indices] = numpy.nan

    error_checking.assert_is_numpy_array(min_colour_values,
                                         exact_dimensions=expected_dim)
    error_checking.assert_is_numpy_array(max_colour_values,
                                         exact_dimensions=expected_dim)
    assert not numpy.any(max_colour_values <= min_colour_values)

    composite_names_abbrev = [
        n.replace('_', '-').lower() for n in composite_names
    ]
    composite_names_verbose = [
        '({0:s}) {1:s}'.format(chr(ord('a') + i),
                               composite_names[i].replace('_', ' '))
        for i in range(num_composites)
    ]

    panel_file_names = [None] * num_composites

    for i in range(num_composites):
        (panel_file_names[i], min_colour_values[i],
         max_colour_values[i]) = _plot_one_composite(
             gradcam_file_name=gradcam_file_names[i],
             monte_carlo_file_name=monte_carlo_file_names[i],
             composite_name_abbrev=composite_names_abbrev[i],
             composite_name_verbose=composite_names_verbose[i],
             colour_map_object=colour_map_object,
             min_colour_value=min_colour_values[i],
             max_colour_value=max_colour_values[i],
             num_contours=num_contours,
             smoothing_radius_grid_cells=smoothing_radius_grid_cells,
             monte_carlo_max_fdr=monte_carlo_max_fdr,
             output_dir_name=output_dir_name)

        _add_colour_bar(figure_file_name=panel_file_names[i],
                        colour_map_object=colour_map_object,
                        min_colour_value=min_colour_values[i],
                        max_colour_value=max_colour_values[i],
                        temporary_dir_name=output_dir_name)

        print('\n')

    figure_file_name = '{0:s}/gradcam_concat.jpg'.format(output_dir_name)
    print('Concatenating panels to: "{0:s}"...'.format(figure_file_name))

    num_panel_rows = int(numpy.ceil(numpy.sqrt(num_composites)))
    num_panel_columns = int(numpy.floor(
        float(num_composites) / num_panel_rows))

    imagemagick_utils.concatenate_images(input_file_names=panel_file_names,
                                         output_file_name=figure_file_name,
                                         border_width_pixels=25,
                                         num_panel_rows=num_panel_rows,
                                         num_panel_columns=num_panel_columns)
    imagemagick_utils.trim_whitespace(input_file_name=figure_file_name,
                                      output_file_name=figure_file_name,
                                      border_width_pixels=10)
    imagemagick_utils.resize_image(input_file_name=figure_file_name,
                                   output_file_name=figure_file_name,
                                   output_size_pixels=CONCAT_FIGURE_SIZE_PX)
Exemplo n.º 21
0
def _plot_one_composite(saliency_file_name, monte_carlo_file_name,
                        composite_name_abbrev, composite_name_verbose,
                        colour_map_object, max_colour_value, half_num_contours,
                        smoothing_radius_grid_cells, output_dir_name):
    """Plots saliency map for one composite.

    :param saliency_file_name: Path to saliency file (will be read by
        `saliency.read_file`).
    :param monte_carlo_file_name: Path to Monte Carlo file (will be read by
        `_read_monte_carlo_file`).
    :param composite_name_abbrev: Abbrev composite name (will be used in file
        names).
    :param composite_name_verbose: Verbose composite name (will be used in
        figure title).
    :param colour_map_object: See documentation at top of file.
    :param max_colour_value: Same.
    :param half_num_contours: Same.
    :param smoothing_radius_grid_cells: Same.
    :param output_dir_name: Name of output directory (figures will be saved
        here).
    :return: main_figure_file_name: Path to main image file created by this
        method.
    """

    (mean_radar_matrices, mean_saliency_matrices, significance_matrices,
     model_metadata_dict) = _read_one_composite(
         saliency_file_name=saliency_file_name,
         smoothing_radius_grid_cells=smoothing_radius_grid_cells,
         monte_carlo_file_name=monte_carlo_file_name)

    refl_heights_m_agl = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY][
        trainval_io.RADAR_HEIGHTS_KEY]
    num_refl_heights = len(refl_heights_m_agl)

    handle_dict = plot_examples.plot_one_example(
        list_of_predictor_matrices=mean_radar_matrices,
        model_metadata_dict=model_metadata_dict,
        pmm_flag=True,
        plot_sounding=False,
        allow_whitespace=True,
        plot_panel_names=True,
        panel_name_font_size=PANEL_NAME_FONT_SIZE,
        add_titles=False,
        label_colour_bars=True,
        colour_bar_length=COLOUR_BAR_LENGTH,
        colour_bar_font_size=COLOUR_BAR_FONT_SIZE,
        num_panel_rows=num_refl_heights)

    axes_object_matrices = handle_dict[plot_examples.RADAR_AXES_KEY]

    this_saliency_matrix = numpy.flip(mean_saliency_matrices[0][0, ..., 0],
                                      axis=0)
    saliency_plotting.plot_many_2d_grids_with_contours(
        saliency_matrix_3d=this_saliency_matrix,
        axes_object_matrix=axes_object_matrices[0],
        colour_map_object=colour_map_object,
        max_absolute_contour_level=max_colour_value,
        contour_interval=max_colour_value / half_num_contours,
        row_major=True)

    this_sig_matrix = numpy.flip(significance_matrices[0][0, ..., 0], axis=0)
    significance_plotting.plot_many_2d_grids_without_coords(
        significance_matrix=this_sig_matrix,
        axes_object_matrix=axes_object_matrices[0],
        marker_size=2,
        row_major=True)

    this_saliency_matrix = numpy.flip(mean_saliency_matrices[1][0, ...],
                                      axis=0)
    saliency_plotting.plot_many_2d_grids_with_contours(
        saliency_matrix_3d=this_saliency_matrix,
        axes_object_matrix=axes_object_matrices[1],
        colour_map_object=colour_map_object,
        max_absolute_contour_level=max_colour_value,
        contour_interval=max_colour_value / half_num_contours,
        row_major=False)

    this_sig_matrix = numpy.flip(significance_matrices[1][0, ...], axis=0)
    significance_plotting.plot_many_2d_grids_without_coords(
        significance_matrix=this_sig_matrix,
        axes_object_matrix=axes_object_matrices[1],
        marker_size=2,
        row_major=False)

    refl_figure_object = handle_dict[plot_examples.RADAR_FIGURES_KEY][0]
    refl_figure_file_name = '{0:s}/{1:s}_reflectivity.jpg'.format(
        output_dir_name, composite_name_abbrev)

    print('Saving figure to: "{0:s}"...'.format(refl_figure_file_name))
    refl_figure_object.savefig(refl_figure_file_name,
                               dpi=FIGURE_RESOLUTION_DPI,
                               pad_inches=0,
                               bbox_inches='tight')
    pyplot.close(refl_figure_object)

    shear_figure_object = handle_dict[plot_examples.RADAR_FIGURES_KEY][1]
    shear_figure_file_name = '{0:s}/{1:s}_shear.jpg'.format(
        output_dir_name, composite_name_abbrev)

    print('Saving figure to: "{0:s}"...'.format(shear_figure_file_name))
    shear_figure_object.savefig(shear_figure_file_name,
                                dpi=FIGURE_RESOLUTION_DPI,
                                pad_inches=0,
                                bbox_inches='tight')
    pyplot.close(shear_figure_object)

    main_figure_file_name = '{0:s}/{1:s}_saliency.jpg'.format(
        output_dir_name, composite_name_abbrev)
    print('Concatenating panels to: "{0:s}"...'.format(main_figure_file_name))

    imagemagick_utils.concatenate_images(
        input_file_names=[refl_figure_file_name, shear_figure_file_name],
        output_file_name=main_figure_file_name,
        num_panel_rows=1,
        num_panel_columns=2,
        border_width_pixels=50,
        extra_args_string='-gravity south')
    imagemagick_utils.resize_image(input_file_name=main_figure_file_name,
                                   output_file_name=main_figure_file_name,
                                   output_size_pixels=CONCAT_FIGURE_SIZE_PX)
    imagemagick_utils.trim_whitespace(input_file_name=main_figure_file_name,
                                      output_file_name=main_figure_file_name,
                                      border_width_pixels=TITLE_FONT_SIZE + 25)
    _overlay_text(image_file_name=main_figure_file_name,
                  x_offset_from_center_px=0,
                  y_offset_from_top_px=0,
                  text_string=composite_name_verbose)
    imagemagick_utils.trim_whitespace(input_file_name=main_figure_file_name,
                                      output_file_name=main_figure_file_name,
                                      border_width_pixels=10)

    return main_figure_file_name
def _plot_composite(composite_file_name, composite_name_abbrev,
                    composite_name_verbose, output_dir_name):
    """Plots one composite.

    :param composite_file_name: Path to input file.  Will be read by
        `_read_composite`.
    :param composite_name_abbrev: Abbreviated name for composite.  Will be used
        in names of output files.
    :param composite_name_verbose: Verbose name for composite.  Will be used as
        figure title.
    :param output_dir_name: Path to output directory.  Figures will be saved
        here.
    :return: radar_figure_file_name: Path to file with radar figure for this
        composite.
    :return: sounding_figure_file_name: Path to file with sounding figure for
        this composite.
    """

    mean_predictor_matrices, model_metadata_dict, mean_sounding_pressures_pa = (
        _read_composite(composite_file_name))

    radar_field_names = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY][
        trainval_io.RADAR_FIELDS_KEY]
    radar_heights_m_agl = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY][
        trainval_io.RADAR_HEIGHTS_KEY]

    num_radar_fields = len(radar_field_names)
    num_radar_heights = len(radar_heights_m_agl)

    handle_dict = plot_examples.plot_one_example(
        list_of_predictor_matrices=mean_predictor_matrices,
        model_metadata_dict=model_metadata_dict,
        pmm_flag=True,
        plot_sounding=True,
        sounding_pressures_pascals=mean_sounding_pressures_pa,
        allow_whitespace=True,
        plot_panel_names=True,
        panel_name_font_size=PANEL_NAME_FONT_SIZE,
        add_titles=False,
        label_colour_bars=True,
        colour_bar_length=COLOUR_BAR_LENGTH,
        colour_bar_font_size=COLOUR_BAR_FONT_SIZE,
        sounding_font_size=SOUNDING_FONT_SIZE,
        num_panel_rows=num_radar_heights)

    sounding_figure_file_name = '{0:s}/{1:s}_sounding.jpg'.format(
        output_dir_name, composite_name_abbrev)

    print('Saving figure to: "{0:s}"...'.format(sounding_figure_file_name))
    sounding_figure_object = handle_dict[plot_examples.SOUNDING_FIGURE_KEY]

    sounding_figure_object.savefig(sounding_figure_file_name,
                                   dpi=FIGURE_RESOLUTION_DPI,
                                   pad_inches=0,
                                   bbox_inches='tight')
    pyplot.close(sounding_figure_object)

    imagemagick_utils.resize_image(input_file_name=sounding_figure_file_name,
                                   output_file_name=sounding_figure_file_name,
                                   output_size_pixels=CONCAT_FIGURE_SIZE_PX)

    imagemagick_utils.trim_whitespace(
        input_file_name=sounding_figure_file_name,
        output_file_name=sounding_figure_file_name,
        border_width_pixels=TITLE_FONT_SIZE + 25)

    _overlay_text(image_file_name=sounding_figure_file_name,
                  x_offset_from_center_px=0,
                  y_offset_from_top_px=0,
                  text_string=composite_name_verbose)

    imagemagick_utils.trim_whitespace(
        input_file_name=sounding_figure_file_name,
        output_file_name=sounding_figure_file_name,
        border_width_pixels=10)

    radar_figure_objects = handle_dict[plot_examples.RADAR_FIGURES_KEY]
    panel_file_names = [None] * num_radar_fields

    for j in range(num_radar_fields):
        panel_file_names[j] = '{0:s}/{1:s}_{2:s}.jpg'.format(
            output_dir_name, composite_name_abbrev,
            radar_field_names[j].replace('_', '-'))

        print('Saving figure to: "{0:s}"...'.format(panel_file_names[j]))

        radar_figure_objects[j].savefig(panel_file_names[j],
                                        dpi=FIGURE_RESOLUTION_DPI,
                                        pad_inches=0,
                                        bbox_inches='tight')
        pyplot.close(radar_figure_objects[j])

    radar_figure_file_name = '{0:s}/{1:s}_radar.jpg'.format(
        output_dir_name, composite_name_abbrev)

    print('Concatenating panels to: "{0:s}"...'.format(radar_figure_file_name))

    imagemagick_utils.concatenate_images(
        input_file_names=panel_file_names,
        output_file_name=radar_figure_file_name,
        num_panel_rows=1,
        num_panel_columns=num_radar_fields,
        border_width_pixels=50)

    imagemagick_utils.resize_image(input_file_name=radar_figure_file_name,
                                   output_file_name=radar_figure_file_name,
                                   output_size_pixels=CONCAT_FIGURE_SIZE_PX)

    imagemagick_utils.trim_whitespace(input_file_name=radar_figure_file_name,
                                      output_file_name=radar_figure_file_name,
                                      border_width_pixels=TITLE_FONT_SIZE + 25)

    _overlay_text(image_file_name=radar_figure_file_name,
                  x_offset_from_center_px=0,
                  y_offset_from_top_px=0,
                  text_string=composite_name_verbose)

    imagemagick_utils.trim_whitespace(input_file_name=radar_figure_file_name,
                                      output_file_name=radar_figure_file_name,
                                      border_width_pixels=10)

    return radar_figure_file_name, sounding_figure_file_name
Exemplo n.º 23
0
def _run(input_file_name, output_dir_name):
    """Plots mean example created by average_examples.py.

    This is effectively the main method.

    :param input_file_name: See documentation at top of file.
    :param output_dir_name: Same.
    """

    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=output_dir_name)

    pickle_file_handle = open(input_file_name, 'rb')
    mean_example_dict = pickle.load(pickle_file_handle)
    pickle_file_handle.close()

    # Plot predictors with liquid-water content (LWC).
    figure_object = profile_plotting.plot_predictors(
        example_dict=mean_example_dict,
        example_index=0,
        plot_ice=False,
        use_log_scale=True)[0]

    panel_file_names = ['foo'] * 3
    panel_file_names[0] = '{0:s}/predictors_with_lwc.jpg'.format(
        output_dir_name)
    print('Saving figure to: "{0:s}"...'.format(panel_file_names[0]))

    figure_object.savefig(panel_file_names[0],
                          dpi=FIGURE_RESOLUTION_DPI,
                          pad_inches=0,
                          bbox_inches='tight')
    pyplot.close(figure_object)

    # Plot predictors with ice-water content (IWC).
    figure_object = profile_plotting.plot_predictors(
        example_dict=mean_example_dict,
        example_index=0,
        plot_ice=True,
        use_log_scale=True)[0]

    panel_file_names[1] = '{0:s}/predictors_with_iwc.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 targets.
    figure_object = profile_plotting.plot_targets(
        example_dict=mean_example_dict, example_index=0, use_log_scale=True)[0]

    panel_file_names[2] = '{0:s}/targets.jpg'.format(output_dir_name)
    print('Saving figure to: "{0:s}"...'.format(panel_file_names[2]))

    figure_object.savefig(panel_file_names[2],
                          dpi=FIGURE_RESOLUTION_DPI,
                          pad_inches=0,
                          bbox_inches='tight')
    pyplot.close(figure_object)

    # Concatenate panels.
    concat_figure_file_name = '{0:s}/predictors_and_targets.jpg'.format(
        output_dir_name)
    print(
        'Concatenating panels to: "{0:s}"...'.format(concat_figure_file_name))

    imagemagick_utils.concatenate_images(
        input_file_names=panel_file_names,
        output_file_name=concat_figure_file_name,
        num_panel_rows=2,
        num_panel_columns=2,
        border_width_pixels=50)
    imagemagick_utils.resize_image(input_file_name=concat_figure_file_name,
                                   output_file_name=concat_figure_file_name,
                                   output_size_pixels=CONCAT_FIGURE_SIZE_PX)
Exemplo n.º 24
0
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():
    """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)
Exemplo n.º 26
0
def _run():
    """Plots results of CNN experiment.

    This is effectively the main method.

    :raises: ValueError: if any Unix command fails.
    """

    num_predictor_combos = len(UNIQUE_PREDICTOR_COMBO_STRINGS)
    num_image_sizes = len(UNIQUE_HALF_IMAGE_SIZES)
    num_dropout_fractions = len(UNIQUE_DROPOUT_FRACTIONS)

    gerrity_score_matrix = numpy.full(
        (num_predictor_combos, num_image_sizes, num_dropout_fractions),
        numpy.nan)
    peirce_score_matrix = gerrity_score_matrix + 0.
    hss_matrix = gerrity_score_matrix + 0.
    accuracy_matrix = gerrity_score_matrix + 0.

    for i in range(num_predictor_combos):
        for j in range(num_image_sizes):
            for k in range(num_dropout_fractions):
                this_num_predictors = len(
                    UNIQUE_PREDICTOR_COMBO_STRINGS[i].split())
                this_eval_file_name = (
                    '{0:s}/{1:s}_init-num-filters={2:d}_half-image-size-px='
                    '{3:d}_num-conv-layer-sets={4:d}_dropout={5:.2f}/validation'
                    '/model_evaluation.p'
                ).format(
                    TOP_EXPERIMENT_DIR_NAME,
                    UNIQUE_PREDICTOR_COMBO_STRINGS[i].replace(
                        '_', '-').replace(' ', '_'),
                    this_num_predictors * 8,
                    UNIQUE_HALF_IMAGE_SIZES[j],
                    2 + int(UNIQUE_HALF_IMAGE_SIZES[j] > 8),
                    UNIQUE_DROPOUT_FRACTIONS[k]
                )

                if not os.path.isfile(this_eval_file_name):
                    warning_string = (
                        'POTENTIAL PROBLEM.  Cannot find file 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 = eval_utils.read_evaluation_results(
                    this_eval_file_name)

                gerrity_score_matrix[i, j, k] = this_evaluation_dict[
                    eval_utils.GERRITY_SCORE_KEY]
                peirce_score_matrix[i, j, k] = this_evaluation_dict[
                    eval_utils.PEIRCE_SCORE_KEY]
                hss_matrix[i, j, k] = this_evaluation_dict[
                    eval_utils.HEIDKE_SCORE_KEY]
                accuracy_matrix[i, j, k] = this_evaluation_dict[
                    eval_utils.ACCURACY_KEY]

    print SEPARATOR_STRING
    panel_file_names = numpy.full((4, num_dropout_fractions), '', dtype=object)

    for k in range(num_dropout_fractions):
        if k == 0:
            this_y_axis_text_colour = BLACK_COLOUR + 0.
        else:
            this_y_axis_text_colour = WHITE_COLOUR + 0.
        
        this_title_string = 'Gerrity score; dropout = {0:.2f}'.format(
            UNIQUE_DROPOUT_FRACTIONS[k])
        panel_file_names[0, k] = (
            '{0:s}/gerrity_score_dropout-fraction={1:.2f}.jpg'
        ).format(TOP_EXPERIMENT_DIR_NAME, UNIQUE_DROPOUT_FRACTIONS[k])

        print gerrity_score_matrix[..., k]

        _plot_scores_as_grid(
            score_matrix=gerrity_score_matrix[..., k],
            colour_map_object=COLOUR_MAP_OBJECT,
            min_colour_value=numpy.nanpercentile(
                gerrity_score_matrix, MIN_COLOUR_PERCENTILE),
            max_colour_value=numpy.nanpercentile(
                gerrity_score_matrix, MAX_COLOUR_PERCENTILE),
            x_tick_labels=UNIQUE_IMAGE_SIZE_STRINGS,
            x_axis_label=IMAGE_SIZE_AXIS_LABEL,
            x_axis_text_colour=WHITE_COLOUR,
            y_tick_labels=UNIQUE_PREDICTOR_ABBREV_STRINGS,
            y_axis_label='',
            y_axis_text_colour=this_y_axis_text_colour,
            title_string=this_title_string,
            output_file_name=panel_file_names[0, k])

        this_title_string = 'Peirce score; dropout = {0:.2f}'.format(
            UNIQUE_DROPOUT_FRACTIONS[k])
        panel_file_names[1, k] = (
            '{0:s}/peirce_score_dropout-fraction={1:.2f}.jpg'
        ).format(TOP_EXPERIMENT_DIR_NAME, UNIQUE_DROPOUT_FRACTIONS[k])

        _plot_scores_as_grid(
            score_matrix=peirce_score_matrix[..., k],
            colour_map_object=COLOUR_MAP_OBJECT,
            min_colour_value=numpy.nanpercentile(
                peirce_score_matrix, MIN_COLOUR_PERCENTILE),
            max_colour_value=numpy.nanpercentile(
                peirce_score_matrix, MAX_COLOUR_PERCENTILE),
            x_tick_labels=UNIQUE_IMAGE_SIZE_STRINGS,
            x_axis_label=IMAGE_SIZE_AXIS_LABEL,
            x_axis_text_colour=WHITE_COLOUR,
            y_tick_labels=UNIQUE_PREDICTOR_ABBREV_STRINGS,
            y_axis_label='',
            y_axis_text_colour=this_y_axis_text_colour,
            title_string=this_title_string,
            output_file_name=panel_file_names[1, k])

        this_title_string = 'Heidke skill score; dropout = {0:.2f}'.format(
            UNIQUE_DROPOUT_FRACTIONS[k])
        panel_file_names[2, k] = (
            '{0:s}/hss_dropout-fraction={1:.2f}.jpg'
        ).format(TOP_EXPERIMENT_DIR_NAME, UNIQUE_DROPOUT_FRACTIONS[k])

        _plot_scores_as_grid(
            score_matrix=hss_matrix[..., k],
            colour_map_object=COLOUR_MAP_OBJECT,
            min_colour_value=numpy.nanpercentile(
                hss_matrix, MIN_COLOUR_PERCENTILE),
            max_colour_value=numpy.nanpercentile(
                hss_matrix, MAX_COLOUR_PERCENTILE),
            x_tick_labels=UNIQUE_IMAGE_SIZE_STRINGS,
            x_axis_label=IMAGE_SIZE_AXIS_LABEL,
            x_axis_text_colour=WHITE_COLOUR,
            y_tick_labels=UNIQUE_PREDICTOR_ABBREV_STRINGS,
            y_axis_label='',
            y_axis_text_colour=this_y_axis_text_colour,
            title_string=this_title_string,
            output_file_name=panel_file_names[2, k])

        this_title_string = 'Accuracy; dropout = {0:.2f}'.format(
            UNIQUE_DROPOUT_FRACTIONS[k])
        panel_file_names[3, k] = (
            '{0:s}/accuracy_dropout-fraction={1:.2f}.jpg'
        ).format(TOP_EXPERIMENT_DIR_NAME, UNIQUE_DROPOUT_FRACTIONS[k])

        _plot_scores_as_grid(
            score_matrix=accuracy_matrix[..., k],
            colour_map_object=COLOUR_MAP_OBJECT,
            min_colour_value=numpy.nanpercentile(
                accuracy_matrix, MIN_COLOUR_PERCENTILE),
            max_colour_value=numpy.nanpercentile(
                accuracy_matrix, MAX_COLOUR_PERCENTILE),
            x_tick_labels=UNIQUE_IMAGE_SIZE_STRINGS,
            x_axis_label=IMAGE_SIZE_AXIS_LABEL,
            x_axis_text_colour=BLACK_COLOUR,
            y_tick_labels=UNIQUE_PREDICTOR_ABBREV_STRINGS,
            y_axis_label='',
            y_axis_text_colour=this_y_axis_text_colour,
            title_string=this_title_string,
            output_file_name=panel_file_names[3, k])

    for m in range(4):
        second_image_object = Image.open(panel_file_names[m, 1])
        command_string = '"{0:s}" "{1:s}" -resize {2:d}x{3:d}\! "{1:s}"'.format(
            imagemagick_utils.DEFAULT_CONVERT_EXE_NAME, panel_file_names[m, 0],
            second_image_object.size[0], second_image_object.size[1])

        print 'Resizing image: "{0:s}"...'.format(panel_file_names[m, 0])
        exit_code = os.system(command_string)
        if exit_code != 0:
            raise ValueError('\nUnix command failed (log messages shown '
                             'above should explain why).')

    concat_file_name = '{0:s}/validation.jpg'.format(TOP_EXPERIMENT_DIR_NAME)
    print 'Concatenating panels to: "{0:s}"...'.format(concat_file_name)

    imagemagick_utils.concatenate_images(
        input_file_names=numpy.ravel(panel_file_names).tolist(),
        output_file_name=concat_file_name, num_panel_rows=4,
        num_panel_columns=num_dropout_fractions)

    imagemagick_utils.resize_image(
        input_file_name=concat_file_name, output_file_name=concat_file_name,
        output_size_pixels=FIGURE_SIZE_PIXELS)
Exemplo n.º 27
0
def _run():
    """Plots example of double penalty.

    This is effectively the main method.
    """

    print 'Reading data from: "{0:s}"...'.format(INPUT_FILE_NAME)
    actual_grid_point_table = fronts_io.read_narr_grids_from_file(
        INPUT_FILE_NAME)

    predicted_grid_point_table = copy.deepcopy(actual_grid_point_table)
    predicted_grid_point_table[
        front_utils.WARM_FRONT_COLUMN_INDICES_COLUMN] += 1
    predicted_grid_point_table[
        front_utils.COLD_FRONT_COLUMN_INDICES_COLUMN] += 1
    predicted_grid_point_table[front_utils.WARM_FRONT_ROW_INDICES_COLUMN] += 1
    predicted_grid_point_table[front_utils.COLD_FRONT_ROW_INDICES_COLUMN] += 1

    num_grid_rows, num_grid_columns = nwp_model_utils.get_grid_dimensions(
        model_name=nwp_model_utils.NARR_MODEL_NAME)

    actual_binary_matrix = ml_utils.front_table_to_images(
        frontal_grid_table=actual_grid_point_table,
        num_rows_per_image=num_grid_rows,
        num_columns_per_image=num_grid_columns)
    actual_binary_matrix = ml_utils.binarize_front_images(actual_binary_matrix)

    predicted_binary_matrix = ml_utils.front_table_to_images(
        frontal_grid_table=predicted_grid_point_table,
        num_rows_per_image=num_grid_rows,
        num_columns_per_image=num_grid_columns)
    predicted_binary_matrix = ml_utils.binarize_front_images(
        predicted_binary_matrix)

    _plot_fronts(actual_binary_matrix=actual_binary_matrix,
                 predicted_binary_matrix=predicted_binary_matrix,
                 title_string='Observed and predicted front\nwithout dilation',
                 annotation_string='(c)',
                 output_file_name=NO_DILATION_FILE_NAME)

    actual_binary_matrix = ml_utils.dilate_binary_target_images(
        target_matrix=actual_binary_matrix,
        dilation_distance_metres=DILATION_DISTANCE_METRES,
        verbose=False)
    predicted_binary_matrix = ml_utils.dilate_binary_target_images(
        target_matrix=predicted_binary_matrix,
        dilation_distance_metres=DILATION_DISTANCE_METRES,
        verbose=False)

    _plot_fronts(actual_binary_matrix=actual_binary_matrix,
                 predicted_binary_matrix=predicted_binary_matrix,
                 title_string='Observed and predicted front\nwith dilation',
                 annotation_string='(d)',
                 output_file_name=WITH_DILATION_FILE_NAME)

    print 'Concatenating figures to: "{0:s}"...'.format(CONCAT_FILE_NAME)

    imagemagick_utils.concatenate_images(
        input_file_names=[NO_DILATION_FILE_NAME, WITH_DILATION_FILE_NAME],
        output_file_name=CONCAT_FILE_NAME,
        num_panel_rows=1,
        num_panel_columns=2)

    imagemagick_utils.resize_image(input_file_name=CONCAT_FILE_NAME,
                                   output_file_name=CONCAT_FILE_NAME,
                                   output_size_pixels=CONCAT_SIZE_PIXELS)
def _plot_sounding_saliency(
        saliency_matrix, colour_map_object, max_colour_value,
        sounding_figure_object, sounding_axes_object,
        sounding_pressures_pascals, saliency_dict, model_metadata_dict,
        add_title, output_dir_name, pmm_flag, example_index=None):
    """Plots saliency for sounding.

    H = number of sounding heights
    F = number of sounding fields

    :param saliency_matrix: H-by-F numpy array of saliency values.
    :param colour_map_object: See documentation at top of file.
    :param max_colour_value: Same.
    :param sounding_figure_object: Figure handle (instance of
        `matplotlib.figure.Figure`) for sounding itself.
    :param sounding_axes_object: Axes handle (instance of
        `matplotlib.axes._subplots.AxesSubplot`) for sounding itself.
    :param sounding_pressures_pascals: length-H numpy array of sounding
        pressures.
    :param saliency_dict: Dictionary returned by `saliency_maps.read_file`.
    :param model_metadata_dict: Dictionary returned by
        `cnn.read_model_metadata`.
    :param add_title: Boolean flag.
    :param output_dir_name: Name of output directory.  Figures will be saved
        here.
    :param pmm_flag: Boolean flag.  If True, plotting PMM composite rather than
        one example.
    :param example_index: [used only if `pmm_flag == False`]
        Plotting the [i]th example, where i = `example_index`.
    """

    if max_colour_value is None:
        max_colour_value = numpy.percentile(
            numpy.absolute(saliency_matrix), MAX_COLOUR_PERCENTILE
        )

    training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY]
    sounding_field_names = training_option_dict[trainval_io.SOUNDING_FIELDS_KEY]

    if pmm_flag:
        full_storm_id_string = None
        storm_time_unix_sec = None
    else:
        full_storm_id_string = saliency_dict[saliency_maps.FULL_STORM_IDS_KEY][
            example_index]
        storm_time_unix_sec = saliency_dict[saliency_maps.STORM_TIMES_KEY][
            example_index]

    if add_title:
        title_string = 'Max absolute saliency = {0:.2e}'.format(
            max_colour_value)
        sounding_axes_object.set_title(title_string)

    left_panel_file_name = plot_examples.metadata_to_file_name(
        output_dir_name=output_dir_name, is_sounding=False, pmm_flag=pmm_flag,
        full_storm_id_string=full_storm_id_string,
        storm_time_unix_sec=storm_time_unix_sec,
        radar_field_name='sounding-actual')

    print('Saving figure to file: "{0:s}"...'.format(left_panel_file_name))
    sounding_figure_object.savefig(
        left_panel_file_name, dpi=FIGURE_RESOLUTION_DPI, pad_inches=0,
        bbox_inches='tight')
    pyplot.close(sounding_figure_object)

    saliency_plotting.plot_saliency_for_sounding(
        saliency_matrix=saliency_matrix,
        sounding_field_names=sounding_field_names,
        pressure_levels_mb=PASCALS_TO_MB * sounding_pressures_pascals,
        colour_map_object=colour_map_object,
        max_absolute_colour_value=max_colour_value)

    right_panel_file_name = plot_examples.metadata_to_file_name(
        output_dir_name=output_dir_name, is_sounding=False, pmm_flag=pmm_flag,
        full_storm_id_string=full_storm_id_string,
        storm_time_unix_sec=storm_time_unix_sec,
        radar_field_name='sounding-saliency')

    print('Saving figure to file: "{0:s}"...'.format(right_panel_file_name))
    pyplot.savefig(right_panel_file_name, dpi=FIGURE_RESOLUTION_DPI,
                   pad_inches=0, bbox_inches='tight')
    pyplot.close()

    concat_file_name = plot_examples.metadata_to_file_name(
        output_dir_name=output_dir_name, is_sounding=True, pmm_flag=pmm_flag,
        full_storm_id_string=full_storm_id_string,
        storm_time_unix_sec=storm_time_unix_sec)

    print('Concatenating figures to: "{0:s}"...\n'.format(concat_file_name))
    imagemagick_utils.concatenate_images(
        input_file_names=[left_panel_file_name, right_panel_file_name],
        output_file_name=concat_file_name,
        num_panel_rows=1, num_panel_columns=2
    )

    imagemagick_utils.resize_image(
        input_file_name=concat_file_name, output_file_name=concat_file_name,
        output_size_pixels=SOUNDING_IMAGE_SIZE_PX)

    os.remove(left_panel_file_name)
    os.remove(right_panel_file_name)
Exemplo n.º 29
0
def _plot_one_composite(saliency_file_name, composite_name_abbrev,
                        composite_name_verbose, colour_map_object,
                        max_colour_value, half_num_contours,
                        smoothing_radius_grid_cells, output_dir_name):
    """Plots saliency map for one composite.

    :param saliency_file_name: Path to input file (will be read by
        `saliency.read_file`).
    :param composite_name_abbrev: Abbrev composite name (will be used in file
        names).
    :param composite_name_verbose: Verbose composite name (will be used in
        figure title).
    :param colour_map_object: See documentation at top of file.
    :param max_colour_value: Same.
    :param half_num_contours: Same.
    :param smoothing_radius_grid_cells: Same.
    :param output_dir_name: Name of output directory (figures will be saved
        here).
    :return: main_figure_file_name: Path to main image file created by this
        method.
    :return: max_colour_value: See input doc.
    """

    mean_radar_matrix, mean_saliency_matrix, model_metadata_dict = (
        _read_one_composite(
            saliency_file_name=saliency_file_name,
            smoothing_radius_grid_cells=smoothing_radius_grid_cells))

    if numpy.isnan(max_colour_value):
        max_colour_value = numpy.percentile(mean_saliency_matrix,
                                            MAX_COLOUR_PERCENTILE)

    training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY]
    field_names = training_option_dict[trainval_io.RADAR_FIELDS_KEY]

    num_fields = mean_radar_matrix.shape[-1]
    num_heights = mean_radar_matrix.shape[-2]

    handle_dict = plot_examples.plot_one_example(
        list_of_predictor_matrices=[mean_radar_matrix],
        model_metadata_dict=model_metadata_dict,
        pmm_flag=True,
        allow_whitespace=True,
        plot_panel_names=True,
        panel_name_font_size=PANEL_NAME_FONT_SIZE,
        add_titles=False,
        label_colour_bars=True,
        colour_bar_length=COLOUR_BAR_LENGTH,
        colour_bar_font_size=COLOUR_BAR_FONT_SIZE,
        num_panel_rows=num_heights)

    figure_objects = handle_dict[plot_examples.RADAR_FIGURES_KEY]
    axes_object_matrices = handle_dict[plot_examples.RADAR_AXES_KEY]

    for k in range(num_fields):
        this_saliency_matrix = mean_saliency_matrix[0, ..., k]

        saliency_plotting.plot_many_2d_grids_with_contours(
            saliency_matrix_3d=numpy.flip(this_saliency_matrix, axis=0),
            axes_object_matrix=axes_object_matrices[k],
            colour_map_object=colour_map_object,
            max_absolute_contour_level=max_colour_value,
            contour_interval=max_colour_value / half_num_contours)

    panel_file_names = [None] * num_fields

    for k in range(num_fields):
        panel_file_names[k] = '{0:s}/{1:s}_{2:s}.jpg'.format(
            output_dir_name, composite_name_abbrev,
            field_names[k].replace('_', '-'))

        print('Saving figure to: "{0:s}"...'.format(panel_file_names[k]))

        figure_objects[k].savefig(panel_file_names[k],
                                  dpi=FIGURE_RESOLUTION_DPI,
                                  pad_inches=0,
                                  bbox_inches='tight')
        pyplot.close(figure_objects[k])

    main_figure_file_name = '{0:s}/{1:s}_saliency.jpg'.format(
        output_dir_name, composite_name_abbrev)

    print('Concatenating panels to: "{0:s}"...'.format(main_figure_file_name))

    imagemagick_utils.concatenate_images(
        input_file_names=panel_file_names,
        output_file_name=main_figure_file_name,
        num_panel_rows=1,
        num_panel_columns=num_fields,
        border_width_pixels=50)

    imagemagick_utils.resize_image(input_file_name=main_figure_file_name,
                                   output_file_name=main_figure_file_name,
                                   output_size_pixels=CONCAT_FIGURE_SIZE_PX)

    imagemagick_utils.trim_whitespace(input_file_name=main_figure_file_name,
                                      output_file_name=main_figure_file_name,
                                      border_width_pixels=TITLE_FONT_SIZE + 25)

    _overlay_text(image_file_name=main_figure_file_name,
                  x_offset_from_center_px=0,
                  y_offset_from_top_px=0,
                  text_string=composite_name_verbose)

    imagemagick_utils.trim_whitespace(input_file_name=main_figure_file_name,
                                      output_file_name=main_figure_file_name,
                                      border_width_pixels=10)

    return main_figure_file_name, max_colour_value
def _plot_sounding_saliency(
        sounding_matrix, sounding_saliency_matrix, sounding_field_names,
        saliency_metadata_dict, colour_map_object, max_colour_value_by_example,
        output_dir_name):
    """Plots soundings along with their saliency maps.

    E = number of examples
    H = number of sounding heights
    F = number of sounding fields

    :param sounding_matrix: E-by-H-by-F numpy array of sounding values.
    :param sounding_saliency_matrix: E-by-H-by-F numpy array of corresponding
        saliency values.
    :param sounding_field_names: length-F list of field names.
    :param saliency_metadata_dict: Dictionary returned by
        `saliency_maps.read_standard_file`.
    :param colour_map_object: See doc for `_plot_2d3d_radar_saliency`.
    :param max_colour_value_by_example: Same.
    :param output_dir_name: Name of output directory (figures will be saved
        here).
    """

    # TODO(thunderhoser): Generalize this method to deal with
    # probability-matched means.

    num_examples = sounding_matrix.shape[0]

    try:
        metpy_dict_by_example = dl_utils.soundings_to_metpy_dictionaries(
            sounding_matrix=sounding_matrix, field_names=sounding_field_names)
    except:
        sounding_pressure_matrix_pa = numpy.expand_dims(
            saliency_metadata_dict[saliency_maps.SOUNDING_PRESSURES_KEY],
            axis=-1)

        this_sounding_matrix = numpy.concatenate(
            (sounding_matrix, sounding_pressure_matrix_pa), axis=-1)

        metpy_dict_by_example = dl_utils.soundings_to_metpy_dictionaries(
            sounding_matrix=this_sounding_matrix,
            field_names=sounding_field_names + [soundings.PRESSURE_NAME])

    for i in range(num_examples):
        this_storm_id = saliency_metadata_dict[
            saliency_maps.STORM_IDS_KEY][i]
        this_storm_time_string = time_conversion.unix_sec_to_string(
            saliency_metadata_dict[saliency_maps.STORM_TIMES_KEY][i],
            TIME_FORMAT)

        this_title_string = 'Storm "{0:s}" at {1:s}'.format(
            this_storm_id, this_storm_time_string)
        sounding_plotting.plot_sounding(
            sounding_dict_for_metpy=metpy_dict_by_example[i],
            title_string=this_title_string)

        this_left_file_name = (
            '{0:s}/{1:s}_{2:s}_sounding-actual.jpg'
        ).format(
            output_dir_name, this_storm_id.replace('_', '-'),
            this_storm_time_string
        )

        print 'Saving figure to file: "{0:s}"...'.format(
            this_left_file_name)
        pyplot.savefig(this_left_file_name, dpi=FIGURE_RESOLUTION_DPI)
        pyplot.close()

        imagemagick_utils.trim_whitespace(
            input_file_name=this_left_file_name,
            output_file_name=this_left_file_name)

        saliency_plotting.plot_saliency_for_sounding(
            saliency_matrix=sounding_saliency_matrix[i, ...],
            sounding_field_names=sounding_field_names,
            pressure_levels_mb=metpy_dict_by_example[i][
                soundings.PRESSURE_COLUMN_METPY],
            colour_map_object=colour_map_object,
            max_absolute_colour_value=max_colour_value_by_example[i])

        this_right_file_name = (
            '{0:s}/{1:s}_{2:s}_sounding-saliency.jpg'
        ).format(
            output_dir_name, this_storm_id.replace('_', '-'),
            this_storm_time_string
        )

        print 'Saving figure to file: "{0:s}"...'.format(
            this_right_file_name)
        pyplot.savefig(this_right_file_name, dpi=FIGURE_RESOLUTION_DPI)
        pyplot.close()

        imagemagick_utils.trim_whitespace(
            input_file_name=this_right_file_name,
            output_file_name=this_right_file_name)

        this_file_name = (
            '{0:s}/saliency_{1:s}_{2:s}_sounding.jpg'
        ).format(
            output_dir_name, this_storm_id.replace('_', '-'),
            this_storm_time_string
        )

        print 'Concatenating panels into file: "{0:s}"...\n'.format(
            this_file_name)

        imagemagick_utils.concatenate_images(
            input_file_names=[this_left_file_name, this_right_file_name],
            output_file_name=this_file_name, num_panel_rows=1,
            num_panel_columns=2)

        imagemagick_utils.resize_image(
            input_file_name=this_file_name,
            output_file_name=this_file_name,
            output_size_pixels=SOUNDING_IMAGE_SIZE_PX)

        os.remove(this_left_file_name)
        os.remove(this_right_file_name)