Example #1
0
def _plot_sounding(list_of_predictor_matrices,
                   model_metadata_dict,
                   allow_whitespace,
                   title_string=None):
    """Plots sounding for one example.

    :param list_of_predictor_matrices: See doc for `_plot_3d_radar_scan`.
    :param model_metadata_dict: Same.
    :param allow_whitespace: Same.
    :param title_string: Same.
    :return: figure_object: Figure handle (instance of
        `matplotlib.figure.Figure`).
    :return: axes_object: Axes handle (instance of
        `matplotlib.axes._subplots.AxesSubplot`).
    """

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

    sounding_matrix = numpy.expand_dims(list_of_predictor_matrices[-1], axis=0)

    # TODO(thunderhoser): Allow actual storm elevation to be used.
    metpy_dict = dl_utils.soundings_to_metpy_dictionaries(
        sounding_matrix=sounding_matrix,
        field_names=sounding_field_names,
        height_levels_m_agl=sounding_heights_m_agl,
        storm_elevations_m_asl=numpy.array([0.]))[0]

    return sounding_plotting.plot_sounding(
        sounding_dict_for_metpy=metpy_dict,
        title_string=title_string if allow_whitespace else None)
    def test_soundings_to_metpy_dictionaries_with_pressure(self):
        """Ensures correct output from soundings_to_metpy_dictionaries.

        In this case the soundings contain pressure.
        """

        these_metpy_dictionaries = dl_utils.soundings_to_metpy_dictionaries(
            sounding_matrix=SOUNDING_MATRIX_UNNORMALIZED,
            field_names=SOUNDING_FIELD_NAMES)

        self.assertTrue(
            _compare_lists_of_metpy_dicts(these_metpy_dictionaries,
                                          LIST_OF_METPY_DICTIONARIES))
    def test_soundings_to_metpy_dictionaries_no_pressure(self):
        """Ensures correct output from soundings_to_metpy_dictionaries.

        In this case the soundings do not contain pressure.
        """

        these_metpy_dictionaries = dl_utils.soundings_to_metpy_dictionaries(
            sounding_matrix=SOUNDING_MATRIX_NO_PRESSURE,
            field_names=SOUNDING_FIELD_NAMES_NO_PRESSURE,
            height_levels_m_agl=HEIGHT_LEVELS_M_AGL,
            storm_elevations_m_asl=STORM_ELEVATIONS_M_ASL)

        self.assertTrue(
            _compare_lists_of_metpy_dicts(these_metpy_dictionaries,
                                          LIST_OF_METPY_DICTIONARIES))
def _plot_sounding_saliency(
        saliency_matrix, colour_map_object, max_colour_value, sounding_matrix,
        saliency_dict, model_metadata_dict, output_dir_name, pmm_flag,
        example_index=None):
    """Plots saliency for sounding.

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

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

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

    if pmm_flag:
        example_index = 0

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    os.remove(left_panel_file_name)
    os.remove(right_panel_file_name)
def _plot_sounding_saliency(
        sounding_matrix, sounding_saliency_matrix, sounding_field_names,
        saliency_metadata_dict, colour_map_object, max_colour_value_by_example,
        output_dir_name):
    """Plots soundings along with their saliency maps.

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

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

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

    num_examples = sounding_matrix.shape[0]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        os.remove(this_left_file_name)
        os.remove(this_right_file_name)
Example #6
0
def _plot_bwo_for_soundings(
        optimized_sounding_matrix, training_option_dict, top_output_dir_name,
        pmm_flag, input_sounding_matrix=None, storm_ids=None,
        storm_times_unix_sec=None):
    """Plots BWO results for soundings.

    E = number of examples (storm objects)
    H = number of sounding heights
    F = number of sounding fields

    :param optimized_sounding_matrix: E-by-H-by-F numpy array of sounding values
        (predictors).
    :param training_option_dict: See doc for `_plot_bwo_for_2d3d_radar`.
    :param top_output_dir_name: Same.
    :param pmm_flag: Same.
    :param input_sounding_matrix: Same as `optimized_sounding_matrix` but with
        non-optimized input.
    :param storm_ids: See doc for `_plot_bwo_for_2d3d_radar`.
    :param storm_times_unix_sec: Same.
    """

    before_optimization_dir_name = '{0:s}/before_optimization'.format(
        top_output_dir_name)
    after_optimization_dir_name = '{0:s}/after_optimization'.format(
        top_output_dir_name)

    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=before_optimization_dir_name)
    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=after_optimization_dir_name)

    if pmm_flag:
        have_storm_ids = False
    else:
        have_storm_ids = not (storm_ids is None or storm_times_unix_sec is None)

    num_storms = optimized_sounding_matrix.shape[0]

    list_of_optimized_metpy_dicts = dl_utils.soundings_to_metpy_dictionaries(
        sounding_matrix=optimized_sounding_matrix,
        field_names=training_option_dict[trainval_io.SOUNDING_FIELDS_KEY],
        height_levels_m_agl=training_option_dict[
            trainval_io.SOUNDING_HEIGHTS_KEY],
        storm_elevations_m_asl=numpy.zeros(num_storms))

    if input_sounding_matrix is None:
        list_of_input_metpy_dicts = None
    else:
        list_of_input_metpy_dicts = dl_utils.soundings_to_metpy_dictionaries(
            sounding_matrix=input_sounding_matrix,
            field_names=training_option_dict[trainval_io.SOUNDING_FIELDS_KEY],
            height_levels_m_agl=training_option_dict[
                trainval_io.SOUNDING_HEIGHTS_KEY],
            storm_elevations_m_asl=numpy.zeros(num_storms))

    for i in range(num_storms):
        if pmm_flag:
            this_base_title_string = 'Probability-matched mean'
            this_base_pathless_file_name = 'pmm'
        else:
            if have_storm_ids:
                this_storm_time_string = time_conversion.unix_sec_to_string(
                    storm_times_unix_sec[i], TIME_FORMAT)

                this_base_title_string = 'Storm "{0:s}" at {1:s}'.format(
                    storm_ids[i], this_storm_time_string)

                this_base_pathless_file_name = '{0:s}_{1:s}'.format(
                    storm_ids[i].replace('_', '-'), this_storm_time_string)

            else:
                this_base_title_string = 'Example {0:d}'.format(i + 1)
                this_base_pathless_file_name = 'example{0:06d}'.format(i)

        this_title_string = '{0:s} (after optimization)'.format(
            this_base_title_string)
        this_file_name = '{0:s}/{1:s}_after-optimization_sounding.jpg'.format(
            after_optimization_dir_name, this_base_pathless_file_name)

        sounding_plotting.plot_sounding(
            sounding_dict_for_metpy=list_of_optimized_metpy_dicts[i],
            title_string=this_title_string)

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

        if input_sounding_matrix is None:
            continue

        this_title_string = '{0:s} (before optimization)'.format(
            this_base_title_string)
        this_file_name = '{0:s}/{1:s}_before-optimization_sounding.jpg'.format(
            before_optimization_dir_name, this_base_pathless_file_name)

        sounding_plotting.plot_sounding(
            sounding_dict_for_metpy=list_of_input_metpy_dicts[i],
            title_string=this_title_string)

        print 'Saving figure to: "{0:s}"...'.format(this_file_name)
        pyplot.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI)
        pyplot.close()
def plot_examples(list_of_predictor_matrices,
                  storm_ids,
                  storm_times_unix_sec,
                  model_metadata_dict,
                  output_dir_name,
                  storm_activations=None):
    """Plots one or more learning examples.

    E = number of examples (storm objects)

    :param list_of_predictor_matrices: List created by
        `testing_io.read_specific_examples`.  Contains data to be plotted.
    :param storm_ids: length-E list of storm IDs.
    :param storm_times_unix_sec: length-E numpy array of storm times.
    :param model_metadata_dict: See doc for `cnn.read_model_metadata`.
    :param output_dir_name: Name of output directory (figures will be saved
        here).
    :param storm_activations: length-E numpy array of storm activations (may be
        None).  Will be included in title of each figure.
    """

    training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY]
    sounding_field_names = training_option_dict[
        trainval_io.SOUNDING_FIELDS_KEY]
    plot_soundings = sounding_field_names is not None

    if plot_soundings:
        list_of_metpy_dictionaries = dl_utils.soundings_to_metpy_dictionaries(
            sounding_matrix=list_of_predictor_matrices[-1],
            field_names=sounding_field_names)
    else:
        list_of_metpy_dictionaries = None

    num_radar_dimensions = len(list_of_predictor_matrices[0].shape) - 2
    list_of_layer_operation_dicts = model_metadata_dict[
        cnn.LAYER_OPERATIONS_KEY]

    if num_radar_dimensions == 2:
        if list_of_layer_operation_dicts is None:
            field_name_by_panel = training_option_dict[
                trainval_io.RADAR_FIELDS_KEY]

            panel_names = (
                radar_plotting.radar_fields_and_heights_to_panel_names(
                    field_names=field_name_by_panel,
                    heights_m_agl=training_option_dict[
                        trainval_io.RADAR_HEIGHTS_KEY]))

            plot_colour_bar_by_panel = numpy.full(len(panel_names),
                                                  True,
                                                  dtype=bool)

        else:
            field_name_by_panel, panel_names = (
                radar_plotting.layer_ops_to_field_and_panel_names(
                    list_of_layer_operation_dicts))

            plot_colour_bar_by_panel = numpy.full(len(panel_names),
                                                  False,
                                                  dtype=bool)
            plot_colour_bar_by_panel[2::3] = True
    else:
        field_name_by_panel = None
        panel_names = None
        plot_colour_bar_by_panel = None

    az_shear_field_names = training_option_dict[trainval_io.RADAR_FIELDS_KEY]
    num_az_shear_fields = len(az_shear_field_names)

    num_storms = len(storm_ids)
    myrorss_2d3d = len(list_of_predictor_matrices) == 3

    for i in range(num_storms):
        this_time_string = time_conversion.unix_sec_to_string(
            storm_times_unix_sec[i], TIME_FORMAT)
        this_base_title_string = 'Storm "{0:s}" at {1:s}'.format(
            storm_ids[i], this_time_string)

        if storm_activations is not None:
            this_base_title_string += ' (activation = {0:.3f})'.format(
                storm_activations[i])

        this_base_file_name = '{0:s}/storm={1:s}_{2:s}'.format(
            output_dir_name, storm_ids[i].replace('_', '-'), this_time_string)

        if plot_soundings:
            sounding_plotting.plot_sounding(
                sounding_dict_for_metpy=list_of_metpy_dictionaries[i],
                title_string=this_base_title_string)

            this_file_name = '{0:s}_sounding.jpg'.format(this_base_file_name)
            print 'Saving figure to: "{0:s}"...'.format(this_file_name)
            pyplot.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI)
            pyplot.close()

        if myrorss_2d3d:
            this_reflectivity_matrix_dbz = numpy.flip(
                list_of_predictor_matrices[0][i, ..., 0], axis=0)

            this_num_heights = this_reflectivity_matrix_dbz.shape[-1]
            this_num_panel_rows = int(numpy.floor(
                numpy.sqrt(this_num_heights)))

            _, these_axes_objects = radar_plotting.plot_3d_grid_without_coords(
                field_matrix=this_reflectivity_matrix_dbz,
                field_name=radar_utils.REFL_NAME,
                grid_point_heights_metres=training_option_dict[
                    trainval_io.RADAR_HEIGHTS_KEY],
                ground_relative=True,
                num_panel_rows=this_num_panel_rows,
                font_size=FONT_SIZE_SANS_COLOUR_BARS)

            this_colour_map_object, this_colour_norm_object = (
                radar_plotting.get_default_colour_scheme(
                    radar_utils.REFL_NAME))

            plotting_utils.add_colour_bar(
                axes_object_or_list=these_axes_objects,
                values_to_colour=this_reflectivity_matrix_dbz,
                colour_map=this_colour_map_object,
                colour_norm_object=this_colour_norm_object,
                orientation='horizontal',
                extend_min=True,
                extend_max=True)

            this_title_string = '{0:s}; {1:s}'.format(this_base_title_string,
                                                      radar_utils.REFL_NAME)
            this_file_name = '{0:s}_reflectivity.jpg'.format(
                this_base_file_name)

            pyplot.suptitle(this_title_string, fontsize=TITLE_FONT_SIZE)
            print 'Saving figure to: "{0:s}"...'.format(this_file_name)
            pyplot.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI)
            pyplot.close()

            this_az_shear_matrix_s01 = numpy.flip(
                list_of_predictor_matrices[1][i, ..., 0], axis=0)

            _, these_axes_objects = (
                radar_plotting.plot_many_2d_grids_without_coords(
                    field_matrix=this_az_shear_matrix_s01,
                    field_name_by_panel=az_shear_field_names,
                    panel_names=az_shear_field_names,
                    num_panel_rows=1,
                    plot_colour_bar_by_panel=numpy.full(num_az_shear_fields,
                                                        False,
                                                        dtype=bool),
                    font_size=FONT_SIZE_SANS_COLOUR_BARS))

            this_colour_map_object, this_colour_norm_object = (
                radar_plotting.get_default_colour_scheme(
                    radar_utils.LOW_LEVEL_SHEAR_NAME))

            plotting_utils.add_colour_bar(
                axes_object_or_list=these_axes_objects,
                values_to_colour=this_az_shear_matrix_s01,
                colour_map=this_colour_map_object,
                colour_norm_object=this_colour_norm_object,
                orientation='horizontal',
                extend_min=True,
                extend_max=True)

            this_file_name = '{0:s}_shear.jpg'.format(this_base_file_name)
            pyplot.suptitle(this_base_title_string, fontsize=TITLE_FONT_SIZE)
            print 'Saving figure to: "{0:s}"...'.format(this_file_name)
            pyplot.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI)
            pyplot.close()

            continue

        this_radar_matrix = list_of_predictor_matrices[0]

        if num_radar_dimensions == 2:
            this_num_channels = this_radar_matrix.shape[-1]
            this_num_panel_rows = int(
                numpy.floor(numpy.sqrt(this_num_channels)))

            radar_plotting.plot_many_2d_grids_without_coords(
                field_matrix=numpy.flip(this_radar_matrix[i, ...], axis=0),
                field_name_by_panel=field_name_by_panel,
                panel_names=panel_names,
                num_panel_rows=this_num_panel_rows,
                plot_colour_bar_by_panel=plot_colour_bar_by_panel,
                font_size=FONT_SIZE_WITH_COLOUR_BARS,
                row_major=False)

            this_title_string = this_base_title_string + ''
            pyplot.suptitle(this_title_string, fontsize=TITLE_FONT_SIZE)

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

            continue

        radar_field_names = training_option_dict[trainval_io.RADAR_FIELDS_KEY]
        radar_heights_m_agl = training_option_dict[
            trainval_io.RADAR_HEIGHTS_KEY]

        for j in range(len(radar_field_names)):
            this_num_heights = this_radar_matrix.shape[-2]
            this_num_panel_rows = int(numpy.floor(
                numpy.sqrt(this_num_heights)))

            _, these_axes_objects = radar_plotting.plot_3d_grid_without_coords(
                field_matrix=numpy.flip(this_radar_matrix[i, ..., j], axis=0),
                field_name=radar_field_names[j],
                grid_point_heights_metres=radar_heights_m_agl,
                ground_relative=True,
                num_panel_rows=this_num_panel_rows,
                font_size=FONT_SIZE_SANS_COLOUR_BARS)

            this_colour_map_object, this_colour_norm_object = (
                radar_plotting.get_default_colour_scheme(radar_field_names[j]))

            plotting_utils.add_colour_bar(
                axes_object_or_list=these_axes_objects,
                values_to_colour=this_radar_matrix[i, ..., j],
                colour_map=this_colour_map_object,
                colour_norm_object=this_colour_norm_object,
                orientation='horizontal',
                extend_min=True,
                extend_max=True)

            this_title_string = '{0:s}; {1:s}'.format(this_base_title_string,
                                                      radar_field_names[j])
            this_file_name = '{0:s}_{1:s}.jpg'.format(
                this_base_file_name, radar_field_names[j].replace('_', '-'))

            pyplot.suptitle(this_title_string, fontsize=TITLE_FONT_SIZE)
            print 'Saving figure to: "{0:s}"...'.format(this_file_name)
            pyplot.savefig(this_file_name, dpi=FIGURE_RESOLUTION_DPI)
            pyplot.close()