예제 #1
0
def _read_actual_polylines(top_input_dir_name, unix_times_sec):
    """Reads actual fronts (polylines) for each time step.

    :param top_input_dir_name: See documentation at top of file.
    :param unix_times_sec: 1-D numpy array of valid times.
    :return: polyline_table: See doc for `fronts_io.write_polylines_to_file`.
    """

    list_of_polyline_tables = []
    for this_time_unix_sec in unix_times_sec:
        this_file_name = fronts_io.find_file_for_one_time(
            top_directory_name=top_input_dir_name,
            file_type=fronts_io.POLYLINE_FILE_TYPE,
            valid_time_unix_sec=this_time_unix_sec)

        print 'Reading data from: "{0:s}"...'.format(this_file_name)
        list_of_polyline_tables.append(
            fronts_io.read_polylines_from_file(this_file_name)
        )
        if len(list_of_polyline_tables) == 1:
            continue

        list_of_polyline_tables[-1] = list_of_polyline_tables[-1].align(
            list_of_polyline_tables[0], axis=1)[0]

    # print 'Removing fronts in masked area...'
    # return front_utils.remove_polylines_in_masked_area(
    #     polyline_table=polyline_table, narr_mask_matrix=narr_mask_matrix)

    return pandas.concat(
        list_of_polyline_tables, axis=0, ignore_index=True)
예제 #2
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(top_narr_dir_name, top_front_line_dir_name, top_wpc_bulletin_dir_name,
         first_time_string, last_time_string, pressure_level_mb,
         thermal_field_name, thermal_colour_map_name,
         max_thermal_prctile_for_colours, first_letter_label, letter_interval,
         output_dir_name):
    """Plots predictors on full NARR grid.

    This is effectively the main method.

    :param top_narr_dir_name: See documentation at top of file.
    :param top_front_line_dir_name: Same.
    :param top_wpc_bulletin_dir_name: Same.
    :param first_time_string: Same.
    :param last_time_string: Same.
    :param pressure_level_mb: Same.
    :param thermal_field_name: Same.
    :param thermal_colour_map_name: Same.
    :param max_thermal_prctile_for_colours: Same.
    :param first_letter_label: Same.
    :param letter_interval: Same.
    :param output_dir_name: Same.
    :raises: ValueError: if
        `thermal_field_name not in VALID_THERMAL_FIELD_NAMES`.
    """

    # Check input args.
    if top_wpc_bulletin_dir_name in ['', 'None']:
        top_wpc_bulletin_dir_name = None

    if first_letter_label in ['', 'None']:
        first_letter_label = None

    if thermal_field_name not in VALID_THERMAL_FIELD_NAMES:
        error_string = (
            '\n{0:s}\nValid thermal fields (listed above) do not include '
            '"{1:s}".'
        ).format(str(VALID_THERMAL_FIELD_NAMES), thermal_field_name)

        raise ValueError(error_string)

    thermal_colour_map_object = pyplot.cm.get_cmap(thermal_colour_map_name)

    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=output_dir_name)

    first_time_unix_sec = time_conversion.string_to_unix_sec(
        first_time_string, DEFAULT_TIME_FORMAT)
    last_time_unix_sec = time_conversion.string_to_unix_sec(
        last_time_string, DEFAULT_TIME_FORMAT)

    valid_times_unix_sec = time_periods.range_and_interval_to_list(
        start_time_unix_sec=first_time_unix_sec,
        end_time_unix_sec=last_time_unix_sec,
        time_interval_sec=NARR_TIME_INTERVAL_SEC, include_endpoint=True)

    # Read metadata for NARR grid.
    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)
    )

    narr_row_limits, narr_column_limits = (
        nwp_plotting.latlng_limits_to_rowcol_limits(
            min_latitude_deg=MIN_LATITUDE_DEG,
            max_latitude_deg=MAX_LATITUDE_DEG,
            min_longitude_deg=MIN_LONGITUDE_DEG,
            max_longitude_deg=MAX_LONGITUDE_DEG,
            model_name=nwp_model_utils.NARR_MODEL_NAME)
    )

    narr_rotation_cos_matrix = narr_rotation_cos_matrix[
        narr_row_limits[0]:(narr_row_limits[1] + 1),
        narr_column_limits[0]:(narr_column_limits[1] + 1)
    ]

    narr_rotation_sin_matrix = narr_rotation_sin_matrix[
        narr_row_limits[0]:(narr_row_limits[1] + 1),
        narr_column_limits[0]:(narr_column_limits[1] + 1)
    ]

    # Do plotting.
    narr_field_names = [
        processed_narr_io.U_WIND_GRID_RELATIVE_NAME,
        processed_narr_io.V_WIND_GRID_RELATIVE_NAME,
        thermal_field_name
    ]

    this_letter_label = None

    for this_time_unix_sec in valid_times_unix_sec:
        this_file_name = fronts_io.find_file_for_one_time(
            top_directory_name=top_front_line_dir_name,
            file_type=fronts_io.POLYLINE_FILE_TYPE,
            valid_time_unix_sec=this_time_unix_sec)

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

        if top_wpc_bulletin_dir_name is None:
            this_high_low_table = None
        else:
            this_file_name = wpc_bulletin_io.find_file(
                top_directory_name=top_wpc_bulletin_dir_name,
                valid_time_unix_sec=this_time_unix_sec)

            print 'Reading data from: "{0:s}"...'.format(this_file_name)
            this_high_low_table = wpc_bulletin_io.read_highs_and_lows(
                this_file_name)

        this_predictor_matrix = None

        for this_field_name in narr_field_names:
            this_file_name = processed_narr_io.find_file_for_one_time(
                top_directory_name=top_narr_dir_name,
                field_name=this_field_name,
                pressure_level_mb=pressure_level_mb,
                valid_time_unix_sec=this_time_unix_sec)

            print 'Reading data from: "{0:s}"...'.format(this_file_name)
            this_field_matrix = processed_narr_io.read_fields_from_file(
                this_file_name
            )[0][0, ...]

            this_field_matrix = utils.fill_nans(this_field_matrix)
            this_field_matrix = this_field_matrix[
                narr_row_limits[0]:(narr_row_limits[1] + 1),
                narr_column_limits[0]:(narr_column_limits[1] + 1)
            ]

            if this_field_name in [processed_narr_io.TEMPERATURE_NAME,
                                   processed_narr_io.WET_BULB_THETA_NAME]:
                this_field_matrix -= ZERO_CELSIUS_IN_KELVINS

            if this_field_name == processed_narr_io.SPECIFIC_HUMIDITY_NAME:
                this_field_matrix = this_field_matrix * KG_TO_GRAMS

            this_field_matrix = numpy.expand_dims(this_field_matrix, axis=-1)

            if this_predictor_matrix is None:
                this_predictor_matrix = this_field_matrix + 0.
            else:
                this_predictor_matrix = numpy.concatenate(
                    (this_predictor_matrix, this_field_matrix), axis=-1)

        u_wind_index = narr_field_names.index(
            processed_narr_io.U_WIND_GRID_RELATIVE_NAME)
        v_wind_index = narr_field_names.index(
            processed_narr_io.V_WIND_GRID_RELATIVE_NAME)

        (this_predictor_matrix[..., u_wind_index],
         this_predictor_matrix[..., v_wind_index]
        ) = nwp_model_utils.rotate_winds_to_earth_relative(
            u_winds_grid_relative_m_s01=this_predictor_matrix[
                ..., u_wind_index],
            v_winds_grid_relative_m_s01=this_predictor_matrix[
                ..., v_wind_index],
            rotation_angle_cosines=narr_rotation_cos_matrix,
            rotation_angle_sines=narr_rotation_sin_matrix)

        this_title_string = time_conversion.unix_sec_to_string(
            this_time_unix_sec, NICE_TIME_FORMAT)

        if pressure_level_mb == 1013:
            this_title_string += ' at surface'
        else:
            this_title_string += ' at {0:d} mb'.format(pressure_level_mb)

        this_default_time_string = time_conversion.unix_sec_to_string(
            this_time_unix_sec, DEFAULT_TIME_FORMAT)

        this_output_file_name = '{0:s}/predictors_{1:s}.jpg'.format(
            output_dir_name, this_default_time_string)

        if first_letter_label is not None:
            if this_letter_label is None:
                this_letter_label = first_letter_label
            else:
                this_letter_label = chr(
                    ord(this_letter_label) + letter_interval
                )

        _plot_one_time(
            predictor_matrix=this_predictor_matrix,
            predictor_names=narr_field_names,
            front_polyline_table=this_polyline_table,
            high_low_table=this_high_low_table,
            thermal_colour_map_object=thermal_colour_map_object,
            max_thermal_prctile_for_colours=max_thermal_prctile_for_colours,
            narr_row_limits=narr_row_limits,
            narr_column_limits=narr_column_limits,
            title_string=this_title_string, letter_label=this_letter_label,
            output_file_name=this_output_file_name)

        print '\n'
예제 #4
0
def _run():
    """Plots input example.

    This is effectively the main method.

    :return: figure_file_name: Path to output file (where the figure was saved).
    """

    valid_time_unix_sec = time_conversion.string_to_unix_sec(
        VALID_TIME_STRING, TIME_FORMAT)
    front_file_name = fronts_io.find_file_for_one_time(
        top_directory_name=TOP_FRONT_DIR_NAME,
        file_type=fronts_io.POLYLINE_FILE_TYPE,
        valid_time_unix_sec=valid_time_unix_sec)

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

    num_narr_fields = len(NARR_FIELD_NAMES)
    narr_matrix_by_field = [numpy.array([])] * num_narr_fields

    for j in range(num_narr_fields):
        if NARR_FIELD_NAMES[j] in WIND_FIELD_NAMES:
            this_directory_name = '{0:s}/earth_relative_wind'.format(
                TOP_NARR_DIRECTORY_NAME)
        else:
            this_directory_name = TOP_NARR_DIRECTORY_NAME + ''

        this_file_name = processed_narr_io.find_file_for_one_time(
            top_directory_name=this_directory_name,
            field_name=NARR_FIELD_NAMES[j],
            pressure_level_mb=PRESSURE_LEVEL_MB,
            valid_time_unix_sec=valid_time_unix_sec)

        print 'Reading data from: "{0:s}"...'.format(this_file_name)
        narr_matrix_by_field[j] = processed_narr_io.read_fields_from_file(
            this_file_name)[0][0, ...]
        narr_matrix_by_field[j] = utils.fill_nans(narr_matrix_by_field[j])

        if NARR_FIELD_NAMES[j] == processed_narr_io.WET_BULB_THETA_NAME:
            narr_matrix_by_field[j] = (narr_matrix_by_field[j] -
                                       ZERO_CELSIUS_IN_KELVINS)

    # (_, front_centroid_latitude_deg, front_centroid_longitude_deg
    # ) = _find_nearest_front(
    #     front_line_table=front_line_table,
    #     query_latitude_deg=APPROX_FRONT_LATITUDE_DEG,
    #     query_longitude_deg=APPROX_FRONT_LONGITUDE_DEG)

    front_centroid_latitude_deg = APPROX_FRONT_LATITUDE_DEG + 0.
    front_centroid_longitude_deg = APPROX_FRONT_LONGITUDE_DEG + 0.

    projection_object = nwp_model_utils.init_model_projection(
        nwp_model_utils.NARR_MODEL_NAME)
    these_x_metres, these_y_metres = nwp_model_utils.project_latlng_to_xy(
        latitudes_deg=numpy.array([front_centroid_latitude_deg]),
        longitudes_deg=numpy.array([front_centroid_longitude_deg]),
        projection_object=projection_object,
        model_name=nwp_model_utils.NARR_MODEL_NAME)

    front_centroid_x_metres = these_x_metres[0]
    front_centroid_y_metres = these_y_metres[0]

    grid_spacing_metres, _ = nwp_model_utils.get_xy_grid_spacing(
        model_name=nwp_model_utils.NARR_MODEL_NAME)
    center_narr_row_index = int(
        numpy.round(front_centroid_y_metres / grid_spacing_metres))
    center_narr_column_index = int(
        numpy.round(front_centroid_x_metres / grid_spacing_metres))

    first_narr_row_index = center_narr_row_index - NUM_ROWS_IN_HALF_GRID
    last_narr_row_index = center_narr_row_index + NUM_ROWS_IN_HALF_GRID
    first_narr_column_index = (center_narr_column_index -
                               NUM_COLUMNS_IN_HALF_GRID)
    last_narr_column_index = center_narr_column_index + NUM_COLUMNS_IN_HALF_GRID

    for j in range(num_narr_fields):
        narr_matrix_by_field[j] = narr_matrix_by_field[j][
            first_narr_row_index:(last_narr_row_index + 1),
            first_narr_column_index:(last_narr_column_index + 1)]

    _, axes_object, basemap_object = nwp_plotting.init_basemap(
        model_name=nwp_model_utils.NARR_MODEL_NAME,
        first_row_in_full_grid=first_narr_row_index,
        last_row_in_full_grid=last_narr_row_index,
        first_column_in_full_grid=first_narr_column_index,
        last_column_in_full_grid=last_narr_column_index,
        resolution_string='i')

    plotting_utils.plot_coastlines(basemap_object=basemap_object,
                                   axes_object=axes_object,
                                   line_colour=BORDER_COLOUR)
    plotting_utils.plot_countries(basemap_object=basemap_object,
                                  axes_object=axes_object,
                                  line_colour=BORDER_COLOUR)
    plotting_utils.plot_states_and_provinces(basemap_object=basemap_object,
                                             axes_object=axes_object,
                                             line_colour=BORDER_COLOUR)
    plotting_utils.plot_parallels(basemap_object=basemap_object,
                                  axes_object=axes_object,
                                  bottom_left_lat_deg=-90.,
                                  upper_right_lat_deg=90.,
                                  parallel_spacing_deg=PARALLEL_SPACING_DEG)
    plotting_utils.plot_meridians(basemap_object=basemap_object,
                                  axes_object=axes_object,
                                  bottom_left_lng_deg=0.,
                                  upper_right_lng_deg=360.,
                                  meridian_spacing_deg=MERIDIAN_SPACING_DEG)

    for j in range(num_narr_fields):
        if NARR_FIELD_NAMES[j] in WIND_FIELD_NAMES:
            continue

        min_colour_value = numpy.percentile(narr_matrix_by_field[j],
                                            MIN_COLOUR_PERCENTILE)
        max_colour_value = numpy.percentile(narr_matrix_by_field[j],
                                            MAX_COLOUR_PERCENTILE)

        nwp_plotting.plot_subgrid(
            field_matrix=narr_matrix_by_field[j],
            model_name=nwp_model_utils.NARR_MODEL_NAME,
            axes_object=axes_object,
            basemap_object=basemap_object,
            colour_map=THERMAL_COLOUR_MAP_OBJECT,
            min_value_in_colour_map=min_colour_value,
            max_value_in_colour_map=max_colour_value,
            first_row_in_full_grid=first_narr_row_index,
            first_column_in_full_grid=first_narr_column_index)

        plotting_utils.add_linear_colour_bar(
            axes_object_or_list=axes_object,
            values_to_colour=narr_matrix_by_field[j],
            colour_map=THERMAL_COLOUR_MAP_OBJECT,
            colour_min=min_colour_value,
            colour_max=max_colour_value,
            orientation='horizontal',
            extend_min=True,
            extend_max=True)

    u_wind_index = NARR_FIELD_NAMES.index(
        processed_narr_io.U_WIND_EARTH_RELATIVE_NAME)
    v_wind_index = NARR_FIELD_NAMES.index(
        processed_narr_io.V_WIND_EARTH_RELATIVE_NAME)

    nwp_plotting.plot_wind_barbs_on_subgrid(
        u_wind_matrix_m_s01=narr_matrix_by_field[u_wind_index],
        v_wind_matrix_m_s01=narr_matrix_by_field[v_wind_index],
        model_name=nwp_model_utils.NARR_MODEL_NAME,
        axes_object=axes_object,
        basemap_object=basemap_object,
        first_row_in_full_grid=first_narr_row_index,
        first_column_in_full_grid=first_narr_column_index,
        plot_every_k_rows=PLOT_EVERY_KTH_WIND_BARB,
        plot_every_k_columns=PLOT_EVERY_KTH_WIND_BARB,
        barb_length=WIND_BARB_LENGTH,
        empty_barb_radius=EMPTY_WIND_BARB_RADIUS,
        colour_map=WIND_COLOUR_MAP_OBJECT,
        colour_minimum_kt=MIN_COLOUR_WIND_SPEED_KT,
        colour_maximum_kt=MAX_COLOUR_WIND_SPEED_KT)

    num_fronts = len(front_line_table.index)
    for i in range(num_fronts):
        this_front_type_string = front_line_table[
            front_utils.FRONT_TYPE_COLUMN].values[i]
        if this_front_type_string == front_utils.WARM_FRONT_STRING_ID:
            this_colour = WARM_FRONT_COLOUR
        else:
            this_colour = COLD_FRONT_COLOUR

        # front_plotting.plot_polyline(
        #     latitudes_deg=front_line_table[
        #         front_utils.LATITUDES_COLUMN].values[i],
        #     longitudes_deg=front_line_table[
        #         front_utils.LONGITUDES_COLUMN].values[i],
        #     basemap_object=basemap_object, axes_object=axes_object,
        #     front_type=front_line_table[
        #         front_utils.FRONT_TYPE_COLUMN].values[i],
        #     line_width=FRONT_LINE_WIDTH, line_colour=this_colour)

    print 'Saving figure to: "{0:s}"...'.format(OUTPUT_FILE_NAME)
    file_system_utils.mkdir_recursive_if_necessary(file_name=OUTPUT_FILE_NAME)
    pyplot.savefig(OUTPUT_FILE_NAME, dpi=OUTPUT_RESOLUTION_DPI)
    pyplot.close()

    imagemagick_utils.trim_whitespace(input_file_name=OUTPUT_FILE_NAME,
                                      output_file_name=OUTPUT_FILE_NAME)
def _plot_one_time(valid_time_string, pressure_level_mb, title_string,
                   annotation_string, narr_rotation_cos_matrix,
                   narr_rotation_sin_matrix):
    """Plots WPC fronts and NARR fields at one time.

    M = number of grid rows in the full NARR
    N = number of grid columns in the full NARR

    :param valid_time_string: Valid time (format "yyyy-mm-dd-HH").
    :param pressure_level_mb: Pressure level (millibars).
    :param title_string: Title (will be placed above figure).
    :param annotation_string: Annotation (will be placed above and left of
        figure).
    :param narr_rotation_cos_matrix: M-by-N numpy array of cosines for wind-
        rotation angles.
    :param narr_rotation_sin_matrix: M-by-N numpy array of sines for wind-
        rotation angles.
    """

    narr_row_limits, narr_column_limits = (
        nwp_plotting.latlng_limits_to_rowcol_limits(
            min_latitude_deg=MIN_LATITUDE_DEG,
            max_latitude_deg=MAX_LATITUDE_DEG,
            min_longitude_deg=MIN_LONGITUDE_DEG,
            max_longitude_deg=MAX_LONGITUDE_DEG,
            model_name=nwp_model_utils.NARR_MODEL_NAME))

    valid_time_unix_sec = time_conversion.string_to_unix_sec(
        valid_time_string, DEFAULT_TIME_FORMAT)

    front_file_name = fronts_io.find_file_for_one_time(
        top_directory_name=TOP_FRONT_DIR_NAME,
        file_type=fronts_io.POLYLINE_FILE_TYPE,
        valid_time_unix_sec=valid_time_unix_sec)

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

    num_narr_fields = len(NARR_FIELD_NAMES)
    narr_matrix_by_field = [numpy.array([])] * num_narr_fields

    for j in range(num_narr_fields):
        this_file_name = processed_narr_io.find_file_for_one_time(
            top_directory_name=TOP_NARR_DIRECTORY_NAME,
            field_name=NARR_FIELD_NAMES[j],
            pressure_level_mb=pressure_level_mb,
            valid_time_unix_sec=valid_time_unix_sec)

        print 'Reading data from: "{0:s}"...'.format(this_file_name)
        narr_matrix_by_field[j] = processed_narr_io.read_fields_from_file(
            this_file_name)[0][0, ...]

        narr_matrix_by_field[j] = utils.fill_nans(narr_matrix_by_field[j])
        narr_matrix_by_field[j] = narr_matrix_by_field[j][narr_row_limits[0]:(
            narr_row_limits[1] +
            1), narr_column_limits[0]:(narr_column_limits[1] + 1)]

        if NARR_FIELD_NAMES[j] == processed_narr_io.WET_BULB_THETA_NAME:
            narr_matrix_by_field[j] = (narr_matrix_by_field[j] -
                                       ZERO_CELSIUS_IN_KELVINS)

    _, axes_object, basemap_object = nwp_plotting.init_basemap(
        model_name=nwp_model_utils.NARR_MODEL_NAME,
        first_row_in_full_grid=narr_row_limits[0],
        last_row_in_full_grid=narr_row_limits[1],
        first_column_in_full_grid=narr_column_limits[0],
        last_column_in_full_grid=narr_column_limits[1])

    plotting_utils.plot_coastlines(basemap_object=basemap_object,
                                   axes_object=axes_object,
                                   line_colour=BORDER_COLOUR)
    plotting_utils.plot_countries(basemap_object=basemap_object,
                                  axes_object=axes_object,
                                  line_colour=BORDER_COLOUR)
    plotting_utils.plot_states_and_provinces(basemap_object=basemap_object,
                                             axes_object=axes_object,
                                             line_colour=BORDER_COLOUR)
    plotting_utils.plot_parallels(basemap_object=basemap_object,
                                  axes_object=axes_object,
                                  bottom_left_lat_deg=-90.,
                                  upper_right_lat_deg=90.,
                                  parallel_spacing_deg=PARALLEL_SPACING_DEG)
    plotting_utils.plot_meridians(basemap_object=basemap_object,
                                  axes_object=axes_object,
                                  bottom_left_lng_deg=0.,
                                  upper_right_lng_deg=360.,
                                  meridian_spacing_deg=MERIDIAN_SPACING_DEG)

    for j in range(num_narr_fields):
        if NARR_FIELD_NAMES[j] in WIND_FIELD_NAMES:
            continue

        min_colour_value = numpy.percentile(narr_matrix_by_field[j],
                                            MIN_COLOUR_PERCENTILE)
        max_colour_value = numpy.percentile(narr_matrix_by_field[j],
                                            MAX_COLOUR_PERCENTILE)

        nwp_plotting.plot_subgrid(
            field_matrix=narr_matrix_by_field[j],
            model_name=nwp_model_utils.NARR_MODEL_NAME,
            axes_object=axes_object,
            basemap_object=basemap_object,
            colour_map=THERMAL_COLOUR_MAP_OBJECT,
            min_value_in_colour_map=min_colour_value,
            max_value_in_colour_map=max_colour_value,
            first_row_in_full_grid=narr_row_limits[0],
            first_column_in_full_grid=narr_column_limits[0])

        plotting_utils.add_linear_colour_bar(
            axes_object_or_list=axes_object,
            values_to_colour=narr_matrix_by_field[j],
            colour_map=THERMAL_COLOUR_MAP_OBJECT,
            colour_min=min_colour_value,
            colour_max=max_colour_value,
            orientation='horizontal',
            extend_min=True,
            extend_max=True,
            fraction_of_axis_length=0.9)

    this_cos_matrix = narr_rotation_cos_matrix[narr_row_limits[0]:(
        narr_row_limits[1] + 1), narr_column_limits[0]:(narr_column_limits[1] +
                                                        1)]

    this_sin_matrix = narr_rotation_sin_matrix[narr_row_limits[0]:(
        narr_row_limits[1] + 1), narr_column_limits[0]:(narr_column_limits[1] +
                                                        1)]

    u_wind_index = NARR_FIELD_NAMES.index(
        processed_narr_io.U_WIND_GRID_RELATIVE_NAME)
    v_wind_index = NARR_FIELD_NAMES.index(
        processed_narr_io.V_WIND_GRID_RELATIVE_NAME)

    narr_matrix_by_field[u_wind_index], narr_matrix_by_field[v_wind_index] = (
        nwp_model_utils.rotate_winds_to_earth_relative(
            u_winds_grid_relative_m_s01=narr_matrix_by_field[u_wind_index],
            v_winds_grid_relative_m_s01=narr_matrix_by_field[v_wind_index],
            rotation_angle_cosines=this_cos_matrix,
            rotation_angle_sines=this_sin_matrix))

    nwp_plotting.plot_wind_barbs_on_subgrid(
        u_wind_matrix_m_s01=narr_matrix_by_field[u_wind_index],
        v_wind_matrix_m_s01=narr_matrix_by_field[v_wind_index],
        model_name=nwp_model_utils.NARR_MODEL_NAME,
        axes_object=axes_object,
        basemap_object=basemap_object,
        first_row_in_full_grid=narr_row_limits[0],
        first_column_in_full_grid=narr_column_limits[0],
        plot_every_k_rows=PLOT_EVERY_KTH_WIND_BARB,
        plot_every_k_columns=PLOT_EVERY_KTH_WIND_BARB,
        barb_length=WIND_BARB_LENGTH,
        empty_barb_radius=EMPTY_WIND_BARB_RADIUS,
        fill_empty_barb=False,
        colour_map=WIND_COLOUR_MAP_OBJECT,
        colour_minimum_kt=MIN_COLOUR_WIND_SPEED_KT,
        colour_maximum_kt=MAX_COLOUR_WIND_SPEED_KT)

    num_fronts = len(front_line_table.index)

    for i in range(num_fronts):
        this_front_type_string = front_line_table[
            front_utils.FRONT_TYPE_COLUMN].values[i]

        if this_front_type_string == front_utils.WARM_FRONT_STRING_ID:
            this_colour = WARM_FRONT_COLOUR
        else:
            this_colour = COLD_FRONT_COLOUR

        front_plotting.plot_front_with_markers(
            line_latitudes_deg=front_line_table[
                front_utils.LATITUDES_COLUMN].values[i],
            line_longitudes_deg=front_line_table[
                front_utils.LONGITUDES_COLUMN].values[i],
            axes_object=axes_object,
            basemap_object=basemap_object,
            front_type_string=front_line_table[
                front_utils.FRONT_TYPE_COLUMN].values[i],
            marker_colour=this_colour)

    pyplot.title(title_string)
    plotting_utils.annotate_axes(axes_object=axes_object,
                                 annotation_string=annotation_string)

    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=OUTPUT_DIR_NAME)
    figure_file_name = '{0:s}/fronts_{1:04d}mb_{2:s}.jpg'.format(
        OUTPUT_DIR_NAME, pressure_level_mb, valid_time_string)

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

    imagemagick_utils.trim_whitespace(input_file_name=figure_file_name,
                                      output_file_name=figure_file_name)
    return figure_file_name
def _plot_observations_one_time(
        valid_time_string, title_string, annotation_string, output_file_name):
    """Plots observations (NARR predictors and WPC fronts) for one valid time.

    :param valid_time_string: Valid time (format "yyyy-mm-dd-HH").
    :param title_string: Title (will be placed above figure).
    :param annotation_string: Text annotation (will be placed in top left of
        figure).
    :param output_file_name: Path to output file (figure will be saved here).
    """

    (narr_row_limits, narr_column_limits
    ) = nwp_plotting.latlng_limits_to_rowcol_limits(
        min_latitude_deg=MIN_LATITUDE_DEG, max_latitude_deg=MAX_LATITUDE_DEG,
        min_longitude_deg=MIN_LONGITUDE_DEG,
        max_longitude_deg=MAX_LONGITUDE_DEG,
        model_name=nwp_model_utils.NARR_MODEL_NAME)

    valid_time_unix_sec = time_conversion.string_to_unix_sec(
        valid_time_string, INPUT_TIME_FORMAT)
    front_file_name = fronts_io.find_file_for_one_time(
        top_directory_name=TOP_FRONT_DIR_NAME,
        file_type=fronts_io.POLYLINE_FILE_TYPE,
        valid_time_unix_sec=valid_time_unix_sec)

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

    num_narr_fields = len(NARR_FIELD_NAMES)
    narr_matrix_by_field = [numpy.array([])] * num_narr_fields

    for j in range(num_narr_fields):
        if NARR_FIELD_NAMES[j] in WIND_FIELD_NAMES:
            this_directory_name = TOP_NARR_WIND_DIR_NAME + ''
        else:
            this_directory_name = TOP_NARR_DIR_NAME + ''

        this_file_name = processed_narr_io.find_file_for_one_time(
            top_directory_name=this_directory_name,
            field_name=NARR_FIELD_NAMES[j], pressure_level_mb=PRESSURE_LEVEL_MB,
            valid_time_unix_sec=valid_time_unix_sec)

        print 'Reading data from: "{0:s}"...'.format(this_file_name)
        narr_matrix_by_field[j] = processed_narr_io.read_fields_from_file(
            this_file_name)[0][0, ...]

        narr_matrix_by_field[j] = utils.fill_nans(narr_matrix_by_field[j])
        narr_matrix_by_field[j] = narr_matrix_by_field[j][
            narr_row_limits[0]:(narr_row_limits[1] + 1),
            narr_column_limits[0]:(narr_column_limits[1] + 1)
        ]

        if NARR_FIELD_NAMES[j] == processed_narr_io.WET_BULB_THETA_NAME:
            narr_matrix_by_field[j] = (
                narr_matrix_by_field[j] - ZERO_CELSIUS_IN_KELVINS
            )

    _, axes_object, basemap_object = nwp_plotting.init_basemap(
        model_name=nwp_model_utils.NARR_MODEL_NAME,
        first_row_in_full_grid=narr_row_limits[0],
        last_row_in_full_grid=narr_row_limits[1],
        first_column_in_full_grid=narr_column_limits[0],
        last_column_in_full_grid=narr_column_limits[1])

    plotting_utils.plot_coastlines(
        basemap_object=basemap_object, axes_object=axes_object,
        line_colour=BORDER_COLOUR)
    plotting_utils.plot_countries(
        basemap_object=basemap_object, axes_object=axes_object,
        line_colour=BORDER_COLOUR)
    plotting_utils.plot_states_and_provinces(
        basemap_object=basemap_object, axes_object=axes_object,
        line_colour=BORDER_COLOUR)
    plotting_utils.plot_parallels(
        basemap_object=basemap_object, axes_object=axes_object,
        bottom_left_lat_deg=-90., upper_right_lat_deg=90.,
        parallel_spacing_deg=PARALLEL_SPACING_DEG)
    plotting_utils.plot_meridians(
        basemap_object=basemap_object, axes_object=axes_object,
        bottom_left_lng_deg=0., upper_right_lng_deg=360.,
        meridian_spacing_deg=MERIDIAN_SPACING_DEG)

    for j in range(num_narr_fields):
        if NARR_FIELD_NAMES[j] in WIND_FIELD_NAMES:
            continue

        min_colour_value = numpy.percentile(
            narr_matrix_by_field[j], MIN_COLOUR_PERCENTILE)
        max_colour_value = numpy.percentile(
            narr_matrix_by_field[j], MAX_COLOUR_PERCENTILE)

        nwp_plotting.plot_subgrid(
            field_matrix=narr_matrix_by_field[j],
            model_name=nwp_model_utils.NARR_MODEL_NAME, axes_object=axes_object,
            basemap_object=basemap_object, colour_map=THERMAL_COLOUR_MAP_OBJECT,
            min_value_in_colour_map=min_colour_value,
            max_value_in_colour_map=max_colour_value,
            first_row_in_full_grid=narr_row_limits[0],
            first_column_in_full_grid=narr_column_limits[0])

        plotting_utils.add_linear_colour_bar(
            axes_object_or_list=axes_object,
            values_to_colour=narr_matrix_by_field[j],
            colour_map=THERMAL_COLOUR_MAP_OBJECT, colour_min=min_colour_value,
            colour_max=max_colour_value, orientation='vertical',
            extend_min=True, extend_max=True,
            fraction_of_axis_length=LENGTH_FRACTION_FOR_THETA_COLOUR_BAR)

    u_wind_index = NARR_FIELD_NAMES.index(
        processed_narr_io.U_WIND_EARTH_RELATIVE_NAME)
    v_wind_index = NARR_FIELD_NAMES.index(
        processed_narr_io.V_WIND_EARTH_RELATIVE_NAME)

    nwp_plotting.plot_wind_barbs_on_subgrid(
        u_wind_matrix_m_s01=narr_matrix_by_field[u_wind_index],
        v_wind_matrix_m_s01=narr_matrix_by_field[v_wind_index],
        model_name=nwp_model_utils.NARR_MODEL_NAME, axes_object=axes_object,
        basemap_object=basemap_object,
        first_row_in_full_grid=narr_row_limits[0],
        first_column_in_full_grid=narr_column_limits[0],
        plot_every_k_rows=PLOT_EVERY_KTH_WIND_BARB,
        plot_every_k_columns=PLOT_EVERY_KTH_WIND_BARB,
        barb_length=WIND_BARB_LENGTH, empty_barb_radius=EMPTY_WIND_BARB_RADIUS,
        colour_map=WIND_COLOUR_MAP_OBJECT,
        colour_minimum_kt=MIN_COLOUR_WIND_SPEED_KT,
        colour_maximum_kt=MAX_COLOUR_WIND_SPEED_KT)

    num_fronts = len(front_line_table.index)
    for i in range(num_fronts):
        this_front_type_string = front_line_table[
            front_utils.FRONT_TYPE_COLUMN].values[i]
        if this_front_type_string == front_utils.WARM_FRONT_STRING_ID:
            this_colour = WARM_FRONT_COLOUR
        else:
            this_colour = COLD_FRONT_COLOUR

        front_plotting.plot_polyline(
            latitudes_deg=front_line_table[
                front_utils.LATITUDES_COLUMN].values[i],
            longitudes_deg=front_line_table[
                front_utils.LONGITUDES_COLUMN].values[i],
            basemap_object=basemap_object, axes_object=axes_object,
            front_type=front_line_table[
                front_utils.FRONT_TYPE_COLUMN].values[i],
            line_width=FRONT_LINE_WIDTH, line_colour=this_colour)

    pyplot.title(title_string)
    plotting_utils.annotate_axes(
        axes_object=axes_object, annotation_string=annotation_string)

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

    imagemagick_utils.trim_whitespace(input_file_name=output_file_name,
                                      output_file_name=output_file_name)
def _run(example_file_name, top_front_line_dir_name, num_examples,
         example_indices, thetaw_colour_map_name, thetaw_max_colour_percentile,
         output_dir_name):
    """Plots one or more input examples.

    This is effectively the main method.

    :param example_file_name: See documentation at top of file.
    :param top_front_line_dir_name: Same.
    :param num_examples: Same.
    :param example_indices: Same.
    :param thetaw_colour_map_name: Same.
    :param thetaw_max_colour_percentile: Same.
    :param output_dir_name: Same.
    """

    if num_examples <= 0:
        num_examples = None

    if num_examples is None:
        error_checking.assert_is_geq_numpy_array(example_indices, 0)
    else:
        error_checking.assert_is_greater(num_examples, 0)

    error_checking.assert_is_geq(thetaw_max_colour_percentile, 0)
    error_checking.assert_is_leq(thetaw_max_colour_percentile, 100)
    thetaw_colour_map_object = pyplot.cm.get_cmap(thetaw_colour_map_name)

    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=output_dir_name)

    print 'Reading normalized examples from: "{0:s}"...'.format(
        example_file_name)

    example_dict = trainval_io.read_downsized_3d_examples(
        netcdf_file_name=example_file_name,
        num_half_rows_to_keep=NUM_HALF_ROWS,
        num_half_columns_to_keep=NUM_HALF_COLUMNS,
        predictor_names_to_keep=NARR_PREDICTOR_NAMES)

    # TODO(thunderhoser): This is a HACK (assuming that normalization method is
    # z-score and not min-max).
    mean_value_matrix = example_dict[trainval_io.FIRST_NORM_PARAM_KEY]
    standard_deviation_matrix = example_dict[trainval_io.SECOND_NORM_PARAM_KEY]

    normalization_dict = {
        ml_utils.MIN_VALUE_MATRIX_KEY: None,
        ml_utils.MAX_VALUE_MATRIX_KEY: None,
        ml_utils.MEAN_VALUE_MATRIX_KEY: mean_value_matrix,
        ml_utils.STDEV_MATRIX_KEY: standard_deviation_matrix
    }

    example_dict[trainval_io.PREDICTOR_MATRIX_KEY] = (
        ml_utils.denormalize_predictors(
            predictor_matrix=example_dict[trainval_io.PREDICTOR_MATRIX_KEY],
            normalization_dict=normalization_dict))

    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_examples_total = len(example_dict[trainval_io.TARGET_TIMES_KEY])
    example_indices = numpy.linspace(0,
                                     num_examples_total - 1,
                                     num=num_examples_total,
                                     dtype=int)

    if num_examples is not None:
        num_examples = min([num_examples, num_examples_total])
        example_indices = numpy.random.choice(example_indices,
                                              size=num_examples,
                                              replace=False)

    thetaw_index = NARR_PREDICTOR_NAMES.index(
        processed_narr_io.WET_BULB_THETA_NAME)
    u_wind_index = NARR_PREDICTOR_NAMES.index(
        processed_narr_io.U_WIND_GRID_RELATIVE_NAME)
    v_wind_index = NARR_PREDICTOR_NAMES.index(
        processed_narr_io.V_WIND_GRID_RELATIVE_NAME)

    for i in example_indices:
        this_center_row_index = example_dict[trainval_io.ROW_INDICES_KEY][i]
        this_first_row_index = this_center_row_index - NUM_HALF_ROWS
        this_last_row_index = this_center_row_index + NUM_HALF_ROWS

        this_center_column_index = example_dict[
            trainval_io.COLUMN_INDICES_KEY][i]
        this_first_column_index = this_center_column_index - NUM_HALF_COLUMNS
        this_last_column_index = this_center_column_index + NUM_HALF_COLUMNS

        this_u_wind_matrix_m_s01 = example_dict[
            trainval_io.PREDICTOR_MATRIX_KEY][i, ..., u_wind_index]
        this_v_wind_matrix_m_s01 = example_dict[
            trainval_io.PREDICTOR_MATRIX_KEY][i, ..., v_wind_index]
        this_cos_matrix = narr_rotation_cos_matrix[this_first_row_index:(
            this_last_row_index +
            1), this_first_column_index:(this_last_column_index + 1)]
        this_sin_matrix = narr_rotation_sin_matrix[this_first_row_index:(
            this_last_row_index +
            1), this_first_column_index:(this_last_column_index + 1)]

        this_u_wind_matrix_m_s01, this_v_wind_matrix_m_s01 = (
            nwp_model_utils.rotate_winds_to_earth_relative(
                u_winds_grid_relative_m_s01=this_u_wind_matrix_m_s01,
                v_winds_grid_relative_m_s01=this_v_wind_matrix_m_s01,
                rotation_angle_cosines=this_cos_matrix,
                rotation_angle_sines=this_sin_matrix))

        _, axes_object, basemap_object = nwp_plotting.init_basemap(
            model_name=nwp_model_utils.NARR_MODEL_NAME,
            first_row_in_full_grid=this_first_row_index,
            last_row_in_full_grid=this_last_row_index,
            first_column_in_full_grid=this_first_column_index,
            last_column_in_full_grid=this_last_column_index,
            resolution_string='i')

        plotting_utils.plot_coastlines(basemap_object=basemap_object,
                                       axes_object=axes_object,
                                       line_colour=BORDER_COLOUR,
                                       line_width=BORDER_WIDTH)
        plotting_utils.plot_countries(basemap_object=basemap_object,
                                      axes_object=axes_object,
                                      line_colour=BORDER_COLOUR,
                                      line_width=BORDER_WIDTH)
        plotting_utils.plot_states_and_provinces(basemap_object=basemap_object,
                                                 axes_object=axes_object,
                                                 line_colour=BORDER_COLOUR,
                                                 line_width=BORDER_WIDTH)
        plotting_utils.plot_parallels(
            basemap_object=basemap_object,
            axes_object=axes_object,
            bottom_left_lat_deg=-90.,
            upper_right_lat_deg=90.,
            parallel_spacing_deg=PARALLEL_SPACING_DEG)
        plotting_utils.plot_meridians(
            basemap_object=basemap_object,
            axes_object=axes_object,
            bottom_left_lng_deg=0.,
            upper_right_lng_deg=360.,
            meridian_spacing_deg=MERIDIAN_SPACING_DEG)

        this_thetaw_matrix_kelvins = example_dict[
            trainval_io.PREDICTOR_MATRIX_KEY][i, ..., thetaw_index]

        this_min_value = numpy.percentile(this_thetaw_matrix_kelvins,
                                          100. - thetaw_max_colour_percentile)
        this_max_value = numpy.percentile(this_thetaw_matrix_kelvins,
                                          thetaw_max_colour_percentile)

        nwp_plotting.plot_subgrid(
            field_matrix=this_thetaw_matrix_kelvins,
            model_name=nwp_model_utils.NARR_MODEL_NAME,
            axes_object=axes_object,
            basemap_object=basemap_object,
            colour_map=thetaw_colour_map_object,
            min_value_in_colour_map=this_min_value,
            max_value_in_colour_map=this_max_value,
            first_row_in_full_grid=this_first_row_index,
            first_column_in_full_grid=this_first_column_index)

        colour_bar_object = plotting_utils.add_linear_colour_bar(
            axes_object_or_list=axes_object,
            values_to_colour=this_thetaw_matrix_kelvins,
            colour_map=thetaw_colour_map_object,
            colour_min=this_min_value,
            colour_max=this_max_value,
            orientation='vertical',
            extend_min=True,
            extend_max=True,
            fraction_of_axis_length=0.8)

        colour_bar_object.set_label(
            r'Wet-bulb potential temperature ($^{\circ}$C)')

        nwp_plotting.plot_wind_barbs_on_subgrid(
            u_wind_matrix_m_s01=this_u_wind_matrix_m_s01,
            v_wind_matrix_m_s01=this_v_wind_matrix_m_s01,
            model_name=nwp_model_utils.NARR_MODEL_NAME,
            axes_object=axes_object,
            basemap_object=basemap_object,
            first_row_in_full_grid=this_first_row_index,
            first_column_in_full_grid=this_first_column_index,
            barb_length=WIND_BARB_LENGTH,
            empty_barb_radius=EMPTY_WIND_BARB_RADIUS,
            fill_empty_barb=False,
            colour_map=WIND_COLOUR_MAP_OBJECT,
            colour_minimum_kt=MIN_COLOUR_WIND_SPEED_KT,
            colour_maximum_kt=MAX_COLOUR_WIND_SPEED_KT)

        this_front_file_name = fronts_io.find_file_for_one_time(
            top_directory_name=top_front_line_dir_name,
            file_type=fronts_io.POLYLINE_FILE_TYPE,
            valid_time_unix_sec=example_dict[trainval_io.TARGET_TIMES_KEY][i])

        print time_conversion.unix_sec_to_string(
            example_dict[trainval_io.TARGET_TIMES_KEY][i], '%Y-%m-%d-%H')

        this_polyline_table = fronts_io.read_polylines_from_file(
            this_front_file_name)
        this_num_fronts = len(this_polyline_table.index)

        for j in range(this_num_fronts):
            this_front_type_string = this_polyline_table[
                front_utils.FRONT_TYPE_COLUMN].values[j]

            if this_front_type_string == front_utils.WARM_FRONT_STRING_ID:
                this_colour = WARM_FRONT_COLOUR
            else:
                this_colour = COLD_FRONT_COLOUR

            front_plotting.plot_front_with_markers(
                line_latitudes_deg=this_polyline_table[
                    front_utils.LATITUDES_COLUMN].values[j],
                line_longitudes_deg=this_polyline_table[
                    front_utils.LONGITUDES_COLUMN].values[j],
                axes_object=axes_object,
                basemap_object=basemap_object,
                front_type_string=this_polyline_table[
                    front_utils.FRONT_TYPE_COLUMN].values[j],
                marker_colour=this_colour,
                marker_size=FRONT_MARKER_SIZE,
                marker_spacing_metres=FRONT_SPACING_METRES)

        this_output_file_name = '{0:s}/example{1:06d}.jpg'.format(
            output_dir_name, i)

        print 'Saving figure to: "{0:s}"...'.format(this_output_file_name)
        pyplot.savefig(this_output_file_name, dpi=FIGURE_RESOLUTION_DPI)
        pyplot.close()
def _run():
    """Creates histograms of warm-front and cold-front lengths.

    This is effectively the main method.
    """

    input_file_names = glob.glob(INPUT_FILE_PATTERN)
    num_files = len(input_file_names)
    list_of_front_line_tables = [pandas.DataFrame()] * num_files

    for i in range(num_files):
        print 'Reading data from: "{0:s}"...'.format(input_file_names[i])

        list_of_front_line_tables[i] = fronts_io.read_polylines_from_file(
            input_file_names[i])
        if i == 0:
            continue

        list_of_front_line_tables[i] = list_of_front_line_tables[i].align(
            list_of_front_line_tables[0], axis=1)[0]

    print SEPARATOR_STRING
    front_line_table = pandas.concat(list_of_front_line_tables,
                                     axis=0,
                                     ignore_index=True)

    front_line_table = _project_fronts_latlng_to_narr(front_line_table)
    print SEPARATOR_STRING

    front_lengths_metres = _get_front_lengths(front_line_table)
    print SEPARATOR_STRING

    nan_flags = numpy.isnan(front_lengths_metres)
    warm_front_flags = numpy.array([
        s == front_utils.WARM_FRONT_STRING_ID
        for s in front_line_table[front_utils.FRONT_TYPE_COLUMN].values
    ])
    cold_front_flags = numpy.array([
        s == front_utils.COLD_FRONT_STRING_ID
        for s in front_line_table[front_utils.FRONT_TYPE_COLUMN].values
    ])

    warm_front_indices = numpy.where(
        numpy.logical_and(warm_front_flags, numpy.invert(nan_flags)))[0]
    cold_front_indices = numpy.where(
        numpy.logical_and(cold_front_flags, numpy.invert(nan_flags)))[0]

    warm_front_lengths_metres = front_lengths_metres[warm_front_indices]
    cold_front_lengths_metres = front_lengths_metres[cold_front_indices]

    print(
        'Number of fronts = {0:d} ... warm fronts with defined length = {1:d} '
        '... cold fronts with defined length = {2:d}').format(
            len(front_lengths_metres), len(warm_front_lengths_metres),
            len(cold_front_lengths_metres))

    _, num_warm_fronts_by_bin = histograms.create_histogram(
        input_values=warm_front_lengths_metres,
        num_bins=NUM_BINS,
        min_value=MIN_HISTOGRAM_LENGTH_METRES,
        max_value=MAX_HISTOGRAM_LENGTH_METRES)
    print 'Sum of bin counts for warm fronts = {0:d}'.format(
        numpy.sum(num_warm_fronts_by_bin))

    _plot_histogram(num_fronts_by_bin=num_warm_fronts_by_bin,
                    front_type_string=front_utils.WARM_FRONT_STRING_ID,
                    title_string='Warm fronts',
                    annotation_string='(a)',
                    output_file_name=WARM_FRONT_FILE_NAME)

    _, num_cold_fronts_by_bin = histograms.create_histogram(
        input_values=cold_front_lengths_metres,
        num_bins=NUM_BINS,
        min_value=MIN_HISTOGRAM_LENGTH_METRES,
        max_value=MAX_HISTOGRAM_LENGTH_METRES)
    print 'Sum of bin counts for cold fronts = {0:d}'.format(
        numpy.sum(num_cold_fronts_by_bin))

    _plot_histogram(num_fronts_by_bin=num_cold_fronts_by_bin,
                    front_type_string=front_utils.COLD_FRONT_STRING_ID,
                    title_string='Cold fronts',
                    annotation_string='(b)',
                    output_file_name=COLD_FRONT_FILE_NAME)

    print 'Concatenating figures to: "{0:s}"...'.format(CONCAT_FILE_NAME)
    imagemagick_utils.concatenate_images(
        input_file_names=[WARM_FRONT_FILE_NAME, COLD_FRONT_FILE_NAME],
        output_file_name=CONCAT_FILE_NAME,
        num_panel_rows=1,
        num_panel_columns=2,
        output_size_pixels=OUTPUT_SIZE_PIXELS)