def _read_storm_locations_one_time(
        top_tracking_dir_name, valid_time_unix_sec, desired_full_id_strings):
    """Reads storm locations at one time.

    K = number of storm objects desired

    :param top_tracking_dir_name: See documentation at top of file.
    :param valid_time_unix_sec: Valid time.
    :param desired_full_id_strings: length-K list of full storm IDs.  Locations
        will be read for these storms only.
    :return: desired_latitudes_deg: length-K numpy array of latitudes (deg N).
    :return: desired_longitudes_deg: length-K numpy array of longitudes (deg E).
    """

    spc_date_string = time_conversion.time_to_spc_date_string(
        valid_time_unix_sec)
    desired_times_unix_sec = numpy.full(
        len(desired_full_id_strings), valid_time_unix_sec, dtype=int
    )

    tracking_file_name = tracking_io.find_file(
        top_tracking_dir_name=top_tracking_dir_name,
        tracking_scale_metres2=DUMMY_TRACKING_SCALE_METRES2,
        source_name=tracking_utils.SEGMOTION_NAME,
        valid_time_unix_sec=valid_time_unix_sec,
        spc_date_string=spc_date_string, raise_error_if_missing=True)

    print('Reading storm locations from: "{0:s}"...'.format(tracking_file_name))
    storm_object_table = tracking_io.read_file(tracking_file_name)

    desired_indices = tracking_utils.find_storm_objects(
        all_id_strings=storm_object_table[
            tracking_utils.FULL_ID_COLUMN].values.tolist(),
        all_times_unix_sec=storm_object_table[
            tracking_utils.VALID_TIME_COLUMN].values,
        id_strings_to_keep=desired_full_id_strings,
        times_to_keep_unix_sec=desired_times_unix_sec, allow_missing=False)

    desired_latitudes_deg = storm_object_table[
        tracking_utils.CENTROID_LATITUDE_COLUMN].values[desired_indices]
    desired_longitudes_deg = storm_object_table[
        tracking_utils.CENTROID_LONGITUDE_COLUMN].values[desired_indices]

    return desired_latitudes_deg, desired_longitudes_deg
Esempio n. 2
0
def _run(top_input_dir_name, tracking_scale_metres2, first_spc_date_string,
         last_spc_date_string, min_distances_metres, max_distances_metres,
         top_output_dir_name):
    """Creates one or more distance buffers around each storm object (polygon).

    This is effectively the main method.

    :param top_input_dir_name: See documentation at top of file.
    :param tracking_scale_metres2: Same.
    :param first_spc_date_string: Same.
    :param last_spc_date_string: Same.
    :param min_distances_metres: Same.
    :param max_distances_metres: Same.
    :param top_output_dir_name: Same.
    """

    min_distances_metres[min_distances_metres < 0] = numpy.nan

    spc_date_strings = time_conversion.get_spc_dates_in_range(
        first_spc_date_string=first_spc_date_string,
        last_spc_date_string=last_spc_date_string)

    for this_spc_date_string in spc_date_strings:
        these_input_file_names = tracking_io.find_files_one_spc_date(
            top_tracking_dir_name=top_input_dir_name,
            tracking_scale_metres2=tracking_scale_metres2,
            source_name=tracking_utils.SEGMOTION_NAME,
            spc_date_string=this_spc_date_string,
            raise_error_if_missing=False)[0]

        if len(these_input_file_names) == 0:
            continue

        for this_input_file_name in these_input_file_names:
            print('Reading input tracks from: "{0:s}"...'.format(
                this_input_file_name))

            this_storm_object_table = tracking_io.read_file(
                this_input_file_name)

            this_storm_object_table = (tracking_utils.create_distance_buffers(
                storm_object_table=this_storm_object_table,
                min_distances_metres=min_distances_metres,
                max_distances_metres=max_distances_metres))

            this_output_file_name = tracking_io.find_file(
                top_tracking_dir_name=top_output_dir_name,
                tracking_scale_metres2=tracking_scale_metres2,
                source_name=tracking_utils.SEGMOTION_NAME,
                valid_time_unix_sec=tracking_io.file_name_to_time(
                    this_input_file_name),
                spc_date_string=this_spc_date_string,
                raise_error_if_missing=False)

            print('Writing input tracks + buffers to: "{0:s}"...\n'.format(
                this_output_file_name))

            tracking_io.write_file(storm_object_table=this_storm_object_table,
                                   pickle_file_name=this_output_file_name)

        print(SEPARATOR_STRING)
Esempio n. 3
0
def _plot_rapruc_one_example(
        full_storm_id_string, storm_time_unix_sec, top_tracking_dir_name,
        latitude_buffer_deg, longitude_buffer_deg, lead_time_seconds,
        field_name_grib1, output_dir_name, rap_file_name=None,
        ruc_file_name=None):
    """Plots RAP or RUC field for one example.

    :param full_storm_id_string: Full storm ID.
    :param storm_time_unix_sec: Valid time.
    :param top_tracking_dir_name: See documentation at top of file.
    :param latitude_buffer_deg: Same.
    :param longitude_buffer_deg: Same.
    :param lead_time_seconds: Same.
    :param field_name_grib1: Same.
    :param output_dir_name: Same.
    :param rap_file_name: Path to file with RAP analysis.
    :param ruc_file_name: [used only if `rap_file_name is None`]
        Path to file with RUC analysis.
    """

    tracking_file_name = tracking_io.find_file(
        top_tracking_dir_name=top_tracking_dir_name,
        tracking_scale_metres2=DUMMY_TRACKING_SCALE_METRES2,
        source_name=tracking_utils.SEGMOTION_NAME,
        valid_time_unix_sec=storm_time_unix_sec,
        spc_date_string=
        time_conversion.time_to_spc_date_string(storm_time_unix_sec),
        raise_error_if_missing=True
    )

    print('Reading data from: "{0:s}"...'.format(tracking_file_name))
    storm_object_table = tracking_io.read_file(tracking_file_name)
    storm_object_table = storm_object_table.loc[
        storm_object_table[tracking_utils.FULL_ID_COLUMN] ==
        full_storm_id_string
    ]

    extrap_times_sec = numpy.array([0, lead_time_seconds], dtype=int)
    storm_object_table = soundings._create_target_points_for_interp(
        storm_object_table=storm_object_table,
        lead_times_seconds=extrap_times_sec
    )

    orig_latitude_deg = (
        storm_object_table[tracking_utils.CENTROID_LATITUDE_COLUMN].values[0]
    )
    orig_longitude_deg = (
        storm_object_table[tracking_utils.CENTROID_LONGITUDE_COLUMN].values[0]
    )
    extrap_latitude_deg = (
        storm_object_table[tracking_utils.CENTROID_LATITUDE_COLUMN].values[1]
    )
    extrap_longitude_deg = (
        storm_object_table[tracking_utils.CENTROID_LONGITUDE_COLUMN].values[1]
    )

    if rap_file_name is None:
        grib_file_name = ruc_file_name
        model_name = nwp_model_utils.RUC_MODEL_NAME
    else:
        grib_file_name = rap_file_name
        model_name = nwp_model_utils.RAP_MODEL_NAME

    pathless_grib_file_name = os.path.split(grib_file_name)[-1]
    grid_name = pathless_grib_file_name.split('_')[1]

    host_name = socket.gethostname()

    if 'casper' in host_name:
        wgrib_exe_name = '/glade/work/ryanlage/wgrib/wgrib'
        wgrib2_exe_name = '/glade/work/ryanlage/wgrib2/wgrib2/wgrib2'
    else:
        wgrib_exe_name = '/condo/swatwork/ralager/wgrib/wgrib'
        wgrib2_exe_name = '/condo/swatwork/ralager/grib2/wgrib2/wgrib2'

    print('Reading field "{0:s}" from: "{1:s}"...'.format(
        field_name_grib1, grib_file_name
    ))
    main_field_matrix = nwp_model_io.read_field_from_grib_file(
        grib_file_name=grib_file_name, field_name_grib1=field_name_grib1,
        model_name=model_name, grid_id=grid_name,
        wgrib_exe_name=wgrib_exe_name, wgrib2_exe_name=wgrib2_exe_name
    )

    u_wind_name_grib1 = 'UGRD:{0:s}'.format(
        field_name_grib1.split(':')[-1]
    )
    u_wind_name_grib1 = u_wind_name_grib1.replace('2 m', '10 m')
    print('Reading field "{0:s}" from: "{1:s}"...'.format(
        u_wind_name_grib1, grib_file_name
    ))
    u_wind_matrix_m_s01 = nwp_model_io.read_field_from_grib_file(
        grib_file_name=grib_file_name, field_name_grib1=u_wind_name_grib1,
        model_name=model_name, grid_id=grid_name,
        wgrib_exe_name=wgrib_exe_name, wgrib2_exe_name=wgrib2_exe_name
    )

    v_wind_name_grib1 = 'VGRD:{0:s}'.format(
        u_wind_name_grib1.split(':')[-1]
    )
    print('Reading field "{0:s}" from: "{1:s}"...'.format(
        v_wind_name_grib1, grib_file_name
    ))
    v_wind_matrix_m_s01 = nwp_model_io.read_field_from_grib_file(
        grib_file_name=grib_file_name, field_name_grib1=v_wind_name_grib1,
        model_name=model_name, grid_id=grid_name,
        wgrib_exe_name=wgrib_exe_name, wgrib2_exe_name=wgrib2_exe_name
    )

    latitude_matrix_deg, longitude_matrix_deg = (
        nwp_model_utils.get_latlng_grid_point_matrices(
            model_name=model_name, grid_name=grid_name)
    )
    cosine_matrix, sine_matrix = nwp_model_utils.get_wind_rotation_angles(
        latitudes_deg=latitude_matrix_deg, longitudes_deg=longitude_matrix_deg,
        model_name=model_name
    )
    u_wind_matrix_m_s01, v_wind_matrix_m_s01 = (
        nwp_model_utils.rotate_winds_to_earth_relative(
            u_winds_grid_relative_m_s01=u_wind_matrix_m_s01,
            v_winds_grid_relative_m_s01=v_wind_matrix_m_s01,
            rotation_angle_cosines=cosine_matrix,
            rotation_angle_sines=sine_matrix)
    )

    min_plot_latitude_deg = (
        min([orig_latitude_deg, extrap_latitude_deg]) - latitude_buffer_deg
    )
    max_plot_latitude_deg = (
        max([orig_latitude_deg, extrap_latitude_deg]) + latitude_buffer_deg
    )
    min_plot_longitude_deg = (
        min([orig_longitude_deg, extrap_longitude_deg]) - longitude_buffer_deg
    )
    max_plot_longitude_deg = (
        max([orig_longitude_deg, extrap_longitude_deg]) + longitude_buffer_deg
    )

    row_limits, column_limits = nwp_plotting.latlng_limits_to_rowcol_limits(
        min_latitude_deg=min_plot_latitude_deg,
        max_latitude_deg=max_plot_latitude_deg,
        min_longitude_deg=min_plot_longitude_deg,
        max_longitude_deg=max_plot_longitude_deg,
        model_name=model_name, grid_id=grid_name
    )

    main_field_matrix = main_field_matrix[
        row_limits[0]:(row_limits[1] + 1),
        column_limits[0]:(column_limits[1] + 1)
    ]
    u_wind_matrix_m_s01 = u_wind_matrix_m_s01[
        row_limits[0]:(row_limits[1] + 1),
        column_limits[0]:(column_limits[1] + 1)
    ]
    v_wind_matrix_m_s01 = v_wind_matrix_m_s01[
        row_limits[0]:(row_limits[1] + 1),
        column_limits[0]:(column_limits[1] + 1)
    ]

    _, axes_object, basemap_object = nwp_plotting.init_basemap(
        model_name=model_name, grid_id=grid_name,
        first_row_in_full_grid=row_limits[0],
        last_row_in_full_grid=row_limits[1],
        first_column_in_full_grid=column_limits[0],
        last_column_in_full_grid=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,
        num_parallels=NUM_PARALLELS
    )
    plotting_utils.plot_meridians(
        basemap_object=basemap_object, axes_object=axes_object,
        num_meridians=NUM_MERIDIANS
    )

    min_colour_value = numpy.nanpercentile(
        main_field_matrix, 100. - MAX_COLOUR_PERCENTILE
    )
    max_colour_value = numpy.nanpercentile(
        main_field_matrix, MAX_COLOUR_PERCENTILE
    )

    nwp_plotting.plot_subgrid(
        field_matrix=main_field_matrix,
        model_name=model_name, grid_id=grid_name,
        axes_object=axes_object, basemap_object=basemap_object,
        colour_map_object=COLOUR_MAP_OBJECT, min_colour_value=min_colour_value,
        max_colour_value=max_colour_value,
        first_row_in_full_grid=row_limits[0],
        first_column_in_full_grid=column_limits[0]
    )

    nwp_plotting.plot_wind_barbs_on_subgrid(
        u_wind_matrix_m_s01=u_wind_matrix_m_s01,
        v_wind_matrix_m_s01=v_wind_matrix_m_s01,
        model_name=model_name, grid_id=grid_name,
        axes_object=axes_object, basemap_object=basemap_object,
        first_row_in_full_grid=row_limits[0],
        first_column_in_full_grid=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=True, colour_map=WIND_COLOUR_MAP_OBJECT,
        colour_minimum_kt=MIN_WIND_SPEED_KT, colour_maximum_kt=MAX_WIND_SPEED_KT
    )

    orig_x_metres, orig_y_metres = basemap_object(
        orig_longitude_deg, orig_latitude_deg
    )
    axes_object.plot(
        orig_x_metres, orig_y_metres, linestyle='None',
        marker=ORIGIN_MARKER_TYPE, markersize=ORIGIN_MARKER_SIZE,
        markeredgewidth=ORIGIN_MARKER_EDGE_WIDTH,
        markerfacecolor=MARKER_COLOUR, markeredgecolor=MARKER_COLOUR
    )

    extrap_x_metres, extrap_y_metres = basemap_object(
        extrap_longitude_deg, extrap_latitude_deg
    )
    axes_object.plot(
        extrap_x_metres, extrap_y_metres, linestyle='None',
        marker=EXTRAP_MARKER_TYPE, markersize=EXTRAP_MARKER_SIZE,
        markeredgewidth=EXTRAP_MARKER_EDGE_WIDTH,
        markerfacecolor=MARKER_COLOUR, markeredgecolor=MARKER_COLOUR
    )

    plotting_utils.plot_linear_colour_bar(
        axes_object_or_matrix=axes_object, data_matrix=main_field_matrix,
        colour_map_object=COLOUR_MAP_OBJECT,
        min_value=min_colour_value, max_value=max_colour_value,
        orientation_string='vertical'
    )

    output_file_name = '{0:s}/{1:s}_{2:s}.jpg'.format(
        output_dir_name, full_storm_id_string.replace('_', '-'),
        time_conversion.unix_sec_to_string(
            storm_time_unix_sec, FILE_NAME_TIME_FORMAT
        )
    )

    print('Saving figure to: "{0:s}"...'.format(output_file_name))
    pyplot.savefig(
        output_file_name, dpi=FIGURE_RESOLUTION_DPI,
        pad_inches=0, bbox_inches='tight'
    )
    pyplot.close()
def _run(myrorss_tracking_dir_name, gridrad_tracking_dir_name,
         max_distance_metres, source_dataset_name, first_spc_date_string,
         last_spc_date_string, output_dir_name):
    """Matches storm objects between MYRORSS and GridRad datasets.

    This is effectively the main method.

    :param myrorss_tracking_dir_name: See documentation at end of file.
    :param gridrad_tracking_dir_name: Same.
    :param max_distance_metres: Same.
    :param source_dataset_name: Same.
    :param first_spc_date_string: Same.
    :param last_spc_date_string: Same.
    :param output_dir_name: Same.
    :raises: ValueError: if `source_dataset_name not in VALID_DATASET_NAMES`.
    """

    if source_dataset_name not in VALID_DATASET_NAMES:
        error_string = (
            '\n{0:s}\nValid datasets (listed above) do not include "{1:s}".'
        ).format(str(VALID_DATASET_NAMES), source_dataset_name)

        raise ValueError(error_string)

    spc_date_strings = time_conversion.get_spc_dates_in_range(
        first_spc_date_string=first_spc_date_string,
        last_spc_date_string=last_spc_date_string)

    if source_dataset_name == radar_utils.MYRORSS_SOURCE_ID:
        source_tracking_dir_name = myrorss_tracking_dir_name
        target_tracking_dir_name = gridrad_tracking_dir_name
        target_dataset_name = radar_utils.GRIDRAD_SOURCE_ID
    else:
        source_tracking_dir_name = gridrad_tracking_dir_name
        target_tracking_dir_name = myrorss_tracking_dir_name
        target_dataset_name = radar_utils.MYRORSS_SOURCE_ID

    source_tracking_file_names = []
    target_tracking_file_names = []

    for this_spc_date_string in spc_date_strings:
        source_tracking_file_names += tracking_io.find_files_one_spc_date(
            top_tracking_dir_name=source_tracking_dir_name,
            tracking_scale_metres2=TRACKING_SCALE_METRES2,
            source_name=tracking_utils.SEGMOTION_NAME,
            spc_date_string=this_spc_date_string,
            raise_error_if_missing=True)[0]

        target_tracking_file_names += tracking_io.find_files_one_spc_date(
            top_tracking_dir_name=target_tracking_dir_name,
            tracking_scale_metres2=TRACKING_SCALE_METRES2,
            source_name=tracking_utils.SEGMOTION_NAME,
            spc_date_string=this_spc_date_string,
            raise_error_if_missing=True)[0]

    source_times_unix_sec = numpy.array(
        [tracking_io.file_name_to_time(f) for f in source_tracking_file_names],
        dtype=int)

    target_times_unix_sec = numpy.array(
        [tracking_io.file_name_to_time(f) for f in target_tracking_file_names],
        dtype=int)

    source_to_target_indices = _match_all_times(
        source_times_unix_sec=source_times_unix_sec,
        target_times_unix_sec=target_times_unix_sec,
        max_diff_seconds=MAX_TIME_DIFF_SECONDS)
    print(SEPARATOR_STRING)

    del target_times_unix_sec
    target_tracking_file_names = [
        target_tracking_file_names[k] for k in source_to_target_indices
    ]

    num_source_times = len(source_times_unix_sec)

    for i in range(num_source_times):
        print('Reading data from: "{0:s}"...'.format(
            source_tracking_file_names[i]))
        this_source_object_table = tracking_io.read_file(
            source_tracking_file_names[i])

        print('Reading data from: "{0:s}"...'.format(
            target_tracking_file_names[i]))
        this_target_object_table = tracking_io.read_file(
            target_tracking_file_names[i])

        this_source_to_target_dict = _match_locations_one_time(
            source_object_table=this_source_object_table,
            target_object_table=this_target_object_table,
            max_distance_metres=max_distance_metres)

        this_match_file_name = tracking_io.find_match_file(
            top_directory_name=output_dir_name,
            valid_time_unix_sec=source_times_unix_sec[i],
            raise_error_if_missing=False)

        print('Writing results to: "{0:s}"...\n'.format(this_match_file_name))
        tracking_io.write_matches(
            pickle_file_name=this_match_file_name,
            source_to_target_dict=this_source_to_target_dict,
            max_time_diff_seconds=MAX_TIME_DIFF_SECONDS,
            max_distance_metres=max_distance_metres,
            source_dataset_name=source_dataset_name,
            source_tracking_dir_name=source_tracking_dir_name,
            target_dataset_name=target_dataset_name,
            target_tracking_dir_name=target_tracking_dir_name)
Esempio n. 5
0
def _run(storm_metafile_name, top_tracking_dir_name, lead_time_seconds,
         output_file_name):
    """Plots spatial distribution of examples (storm objects) in file.

    This is effectively the main method.

    :param storm_metafile_name: See documentation at top of file.
    :param top_tracking_dir_name: Same.
    :param lead_time_seconds: Same.
    :param output_file_name: Same.
    """

    file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name)

    # Read storm metadata.
    print(
        'Reading storm metadata from: "{0:s}"...'.format(storm_metafile_name))
    orig_full_id_strings, orig_times_unix_sec = (
        tracking_io.read_ids_and_times(storm_metafile_name))
    orig_primary_id_strings = temporal_tracking.full_to_partial_ids(
        orig_full_id_strings)[0]

    # Find relevant tracking files.
    spc_date_strings = [
        time_conversion.time_to_spc_date_string(t) for t in orig_times_unix_sec
    ]
    spc_date_strings += [
        time_conversion.time_to_spc_date_string(t + lead_time_seconds)
        for t in orig_times_unix_sec
    ]
    spc_date_strings = list(set(spc_date_strings))

    tracking_file_names = []

    for this_spc_date_string in spc_date_strings:
        tracking_file_names += tracking_io.find_files_one_spc_date(
            top_tracking_dir_name=top_tracking_dir_name,
            tracking_scale_metres2=DUMMY_TRACKING_SCALE_METRES2,
            source_name=tracking_utils.SEGMOTION_NAME,
            spc_date_string=this_spc_date_string,
            raise_error_if_missing=False)[0]

    file_times_unix_sec = numpy.array(
        [tracking_io.file_name_to_time(f) for f in tracking_file_names],
        dtype=int)

    num_orig_storm_objects = len(orig_full_id_strings)
    num_files = len(file_times_unix_sec)
    keep_file_flags = numpy.full(num_files, 0, dtype=bool)

    for i in range(num_orig_storm_objects):
        these_flags = numpy.logical_and(
            file_times_unix_sec >= orig_times_unix_sec[i],
            file_times_unix_sec <= orig_times_unix_sec[i] + lead_time_seconds)
        keep_file_flags = numpy.logical_or(keep_file_flags, these_flags)

    del file_times_unix_sec
    keep_file_indices = numpy.where(keep_file_flags)[0]
    tracking_file_names = [tracking_file_names[k] for k in keep_file_indices]

    # Read relevant tracking files.
    num_files = len(tracking_file_names)
    storm_object_tables = [None] * num_files
    print(SEPARATOR_STRING)

    for i in range(num_files):
        print('Reading data from: "{0:s}"...'.format(tracking_file_names[i]))
        this_table = tracking_io.read_file(tracking_file_names[i])

        storm_object_tables[i] = this_table.loc[this_table[
            tracking_utils.PRIMARY_ID_COLUMN].isin(
                numpy.array(orig_primary_id_strings))]

        if i == 0:
            continue

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

    storm_object_table = pandas.concat(storm_object_tables,
                                       axis=0,
                                       ignore_index=True)
    print(SEPARATOR_STRING)

    # Find relevant storm objects.
    orig_object_rows = tracking_utils.find_storm_objects(
        all_id_strings=storm_object_table[
            tracking_utils.FULL_ID_COLUMN].values.tolist(),
        all_times_unix_sec=storm_object_table[
            tracking_utils.VALID_TIME_COLUMN].values,
        id_strings_to_keep=orig_full_id_strings,
        times_to_keep_unix_sec=orig_times_unix_sec)

    good_object_rows = numpy.array([], dtype=int)

    for i in range(num_orig_storm_objects):
        # Non-merging successors only!

        first_rows = temporal_tracking.find_successors(
            storm_object_table=storm_object_table,
            target_row=orig_object_rows[i],
            num_seconds_forward=lead_time_seconds,
            max_num_sec_id_changes=1,
            change_type_string=temporal_tracking.SPLIT_STRING,
            return_all_on_path=True)

        second_rows = temporal_tracking.find_successors(
            storm_object_table=storm_object_table,
            target_row=orig_object_rows[i],
            num_seconds_forward=lead_time_seconds,
            max_num_sec_id_changes=0,
            change_type_string=temporal_tracking.MERGER_STRING,
            return_all_on_path=True)

        first_rows = first_rows.tolist()
        second_rows = second_rows.tolist()
        these_rows = set(first_rows) & set(second_rows)
        these_rows = numpy.array(list(these_rows), dtype=int)

        good_object_rows = numpy.concatenate((good_object_rows, these_rows))

    good_object_rows = numpy.unique(good_object_rows)
    storm_object_table = storm_object_table.iloc[good_object_rows]

    times_of_day_sec = numpy.mod(
        storm_object_table[tracking_utils.VALID_TIME_COLUMN].values,
        NUM_SECONDS_IN_DAY)
    storm_object_table = storm_object_table.assign(
        **{tracking_utils.VALID_TIME_COLUMN: times_of_day_sec})

    min_plot_latitude_deg = -LATLNG_BUFFER_DEG + numpy.min(
        storm_object_table[tracking_utils.CENTROID_LATITUDE_COLUMN].values)
    max_plot_latitude_deg = LATLNG_BUFFER_DEG + numpy.max(
        storm_object_table[tracking_utils.CENTROID_LATITUDE_COLUMN].values)
    min_plot_longitude_deg = -LATLNG_BUFFER_DEG + numpy.min(
        storm_object_table[tracking_utils.CENTROID_LONGITUDE_COLUMN].values)
    max_plot_longitude_deg = LATLNG_BUFFER_DEG + numpy.max(
        storm_object_table[tracking_utils.CENTROID_LONGITUDE_COLUMN].values)

    _, axes_object, basemap_object = (
        plotting_utils.create_equidist_cylindrical_map(
            min_latitude_deg=min_plot_latitude_deg,
            max_latitude_deg=max_plot_latitude_deg,
            min_longitude_deg=min_plot_longitude_deg,
            max_longitude_deg=max_plot_longitude_deg,
            resolution_string='i'))

    plotting_utils.plot_coastlines(basemap_object=basemap_object,
                                   axes_object=axes_object,
                                   line_colour=BORDER_COLOUR,
                                   line_width=BORDER_WIDTH * 2)
    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,
                                  num_parallels=NUM_PARALLELS,
                                  line_width=BORDER_WIDTH)
    plotting_utils.plot_meridians(basemap_object=basemap_object,
                                  axes_object=axes_object,
                                  num_meridians=NUM_MERIDIANS,
                                  line_width=BORDER_WIDTH)

    # colour_bar_object = storm_plotting.plot_storm_tracks(
    #     storm_object_table=storm_object_table, axes_object=axes_object,
    #     basemap_object=basemap_object, colour_map_object=COLOUR_MAP_OBJECT,
    #     colour_min_unix_sec=0, colour_max_unix_sec=NUM_SECONDS_IN_DAY - 1,
    #     line_width=TRACK_LINE_WIDTH,
    #     start_marker_type=None, end_marker_type=None
    # )

    colour_bar_object = storm_plotting.plot_storm_centroids(
        storm_object_table=storm_object_table,
        axes_object=axes_object,
        basemap_object=basemap_object,
        colour_map_object=COLOUR_MAP_OBJECT,
        colour_min_unix_sec=0,
        colour_max_unix_sec=NUM_SECONDS_IN_DAY - 1)

    tick_times_unix_sec = numpy.linspace(0,
                                         NUM_SECONDS_IN_DAY,
                                         num=NUM_HOURS_IN_DAY + 1,
                                         dtype=int)
    tick_times_unix_sec = tick_times_unix_sec[:-1]
    tick_times_unix_sec = tick_times_unix_sec[::2]

    tick_time_strings = [
        time_conversion.unix_sec_to_string(t, COLOUR_BAR_TIME_FORMAT)
        for t in tick_times_unix_sec
    ]

    colour_bar_object.set_ticks(tick_times_unix_sec)
    colour_bar_object.set_ticklabels(tick_time_strings)

    print('Saving figure to: "{0:s}"...'.format(output_file_name))
    pyplot.savefig(output_file_name,
                   dpi=FIGURE_RESOLUTION_DPI,
                   pad_inches=0,
                   bbox_inches='tight')
    pyplot.close()
Esempio n. 6
0
def _run(prediction_file_name, top_tracking_dir_name, prob_threshold,
         grid_spacing_metres, output_dir_name):
    """Plots spatial distribution of false alarms.

    This is effectively the main method.

    :param prediction_file_name: See documentation at top of file.
    :param top_tracking_dir_name: Same.
    :param prob_threshold: Same.
    :param grid_spacing_metres: Same.
    :param output_dir_name: Same.
    """

    # Process input args.
    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=output_dir_name)
    error_checking.assert_is_greater(prob_threshold, 0.)
    error_checking.assert_is_less_than(prob_threshold, 1.)

    grid_metadata_dict = grids.create_equidistant_grid(
        min_latitude_deg=MIN_LATITUDE_DEG,
        max_latitude_deg=MAX_LATITUDE_DEG,
        min_longitude_deg=MIN_LONGITUDE_DEG,
        max_longitude_deg=MAX_LONGITUDE_DEG,
        x_spacing_metres=grid_spacing_metres,
        y_spacing_metres=grid_spacing_metres,
        azimuthal=False)

    # Read predictions and find positive forecasts and false alarms.
    print('Reading predictions from: "{0:s}"...'.format(prediction_file_name))
    prediction_dict = prediction_io.read_ungridded_predictions(
        prediction_file_name)

    observed_labels = prediction_dict[prediction_io.OBSERVED_LABELS_KEY]
    forecast_labels = (
        prediction_dict[prediction_io.PROBABILITY_MATRIX_KEY][:, -1] >=
        prob_threshold).astype(int)

    pos_forecast_indices = numpy.where(forecast_labels == 1)[0]
    false_alarm_indices = numpy.where(
        numpy.logical_and(observed_labels == 0, forecast_labels == 1))[0]

    num_examples = len(observed_labels)
    num_positive_forecasts = len(pos_forecast_indices)
    num_false_alarms = len(false_alarm_indices)

    print(('Probability threshold = {0:.3f} ... number of examples, positive '
           'forecasts, false alarms = {1:d}, {2:d}, {3:d}').format(
               prob_threshold, num_examples, num_positive_forecasts,
               num_false_alarms))

    # Find and read tracking files.
    pos_forecast_id_strings = [
        prediction_dict[prediction_io.STORM_IDS_KEY][k]
        for k in pos_forecast_indices
    ]
    pos_forecast_times_unix_sec = (
        prediction_dict[prediction_io.STORM_TIMES_KEY][pos_forecast_indices])

    file_times_unix_sec = numpy.unique(pos_forecast_times_unix_sec)
    num_files = len(file_times_unix_sec)
    storm_object_tables = [None] * num_files

    print(SEPARATOR_STRING)

    for i in range(num_files):
        this_tracking_file_name = tracking_io.find_file(
            top_tracking_dir_name=top_tracking_dir_name,
            tracking_scale_metres2=DUMMY_TRACKING_SCALE_METRES2,
            source_name=tracking_utils.SEGMOTION_NAME,
            valid_time_unix_sec=file_times_unix_sec[i],
            spc_date_string=time_conversion.time_to_spc_date_string(
                file_times_unix_sec[i]),
            raise_error_if_missing=True)

        print('Reading data from: "{0:s}"...'.format(this_tracking_file_name))
        this_table = tracking_io.read_file(this_tracking_file_name)
        storm_object_tables[i] = this_table.loc[this_table[
            tracking_utils.FULL_ID_COLUMN].isin(pos_forecast_id_strings)]

        if i == 0:
            continue

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

    storm_object_table = pandas.concat(storm_object_tables,
                                       axis=0,
                                       ignore_index=True)
    print(SEPARATOR_STRING)

    # Find latitudes and longitudes of false alarms.
    all_id_strings = (
        storm_object_table[tracking_utils.FULL_ID_COLUMN].values.tolist())
    all_times_unix_sec = (
        storm_object_table[tracking_utils.VALID_TIME_COLUMN].values)
    good_indices = tracking_utils.find_storm_objects(
        all_id_strings=all_id_strings,
        all_times_unix_sec=all_times_unix_sec,
        id_strings_to_keep=pos_forecast_id_strings,
        times_to_keep_unix_sec=pos_forecast_times_unix_sec,
        allow_missing=False)

    pos_forecast_latitudes_deg = storm_object_table[
        tracking_utils.CENTROID_LATITUDE_COLUMN].values[good_indices]

    pos_forecast_longitudes_deg = storm_object_table[
        tracking_utils.CENTROID_LONGITUDE_COLUMN].values[good_indices]

    false_alarm_id_strings = [
        prediction_dict[prediction_io.STORM_IDS_KEY][k]
        for k in false_alarm_indices
    ]
    false_alarm_times_unix_sec = (
        prediction_dict[prediction_io.STORM_TIMES_KEY][false_alarm_indices])
    good_indices = tracking_utils.find_storm_objects(
        all_id_strings=all_id_strings,
        all_times_unix_sec=all_times_unix_sec,
        id_strings_to_keep=false_alarm_id_strings,
        times_to_keep_unix_sec=false_alarm_times_unix_sec,
        allow_missing=False)

    false_alarm_latitudes_deg = storm_object_table[
        tracking_utils.CENTROID_LATITUDE_COLUMN].values[good_indices]

    false_alarm_longitudes_deg = storm_object_table[
        tracking_utils.CENTROID_LONGITUDE_COLUMN].values[good_indices]

    pos_forecast_x_coords_metres, pos_forecast_y_coords_metres = (
        projections.project_latlng_to_xy(
            latitudes_deg=pos_forecast_latitudes_deg,
            longitudes_deg=pos_forecast_longitudes_deg,
            projection_object=grid_metadata_dict[grids.PROJECTION_KEY]))

    num_pos_forecasts_matrix = grids.count_events_on_equidistant_grid(
        event_x_coords_metres=pos_forecast_x_coords_metres,
        event_y_coords_metres=pos_forecast_y_coords_metres,
        grid_point_x_coords_metres=grid_metadata_dict[grids.X_COORDS_KEY],
        grid_point_y_coords_metres=grid_metadata_dict[grids.Y_COORDS_KEY])[0]
    print(SEPARATOR_STRING)

    false_alarm_x_coords_metres, false_alarm_y_coords_metres = (
        projections.project_latlng_to_xy(
            latitudes_deg=false_alarm_latitudes_deg,
            longitudes_deg=false_alarm_longitudes_deg,
            projection_object=grid_metadata_dict[grids.PROJECTION_KEY]))

    num_false_alarms_matrix = grids.count_events_on_equidistant_grid(
        event_x_coords_metres=false_alarm_x_coords_metres,
        event_y_coords_metres=false_alarm_y_coords_metres,
        grid_point_x_coords_metres=grid_metadata_dict[grids.X_COORDS_KEY],
        grid_point_y_coords_metres=grid_metadata_dict[grids.Y_COORDS_KEY])[0]
    print(SEPARATOR_STRING)

    num_pos_forecasts_matrix = num_pos_forecasts_matrix.astype(float)
    num_pos_forecasts_matrix[num_pos_forecasts_matrix == 0] = numpy.nan
    num_false_alarms_matrix = num_false_alarms_matrix.astype(float)
    num_false_alarms_matrix[num_false_alarms_matrix == 0] = numpy.nan
    far_matrix = num_false_alarms_matrix / num_pos_forecasts_matrix

    this_max_value = numpy.nanpercentile(num_false_alarms_matrix,
                                         MAX_COUNT_PERCENTILE_TO_PLOT)
    if this_max_value < 10:
        this_max_value = numpy.nanmax(num_false_alarms_matrix)

    figure_object = plotter._plot_one_value(
        data_matrix=num_false_alarms_matrix,
        grid_metadata_dict=grid_metadata_dict,
        colour_map_object=CMAP_OBJECT_FOR_COUNTS,
        min_colour_value=0,
        max_colour_value=this_max_value,
        plot_cbar_min_arrow=False,
        plot_cbar_max_arrow=True)[0]

    num_false_alarms_file_name = '{0:s}/num_false_alarms.jpg'.format(
        output_dir_name)

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

    this_max_value = numpy.nanpercentile(num_pos_forecasts_matrix,
                                         MAX_COUNT_PERCENTILE_TO_PLOT)
    if this_max_value < 10:
        this_max_value = numpy.nanmax(num_pos_forecasts_matrix)

    figure_object = plotter._plot_one_value(
        data_matrix=num_pos_forecasts_matrix,
        grid_metadata_dict=grid_metadata_dict,
        colour_map_object=CMAP_OBJECT_FOR_COUNTS,
        min_colour_value=0,
        max_colour_value=this_max_value,
        plot_cbar_min_arrow=False,
        plot_cbar_max_arrow=True)[0]

    num_pos_forecasts_file_name = '{0:s}/num_positive_forecasts.jpg'.format(
        output_dir_name)

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

    this_max_value = numpy.nanpercentile(far_matrix,
                                         MAX_FAR_PERCENTILE_TO_PLOT)
    this_min_value = numpy.nanpercentile(far_matrix,
                                         100. - MAX_FAR_PERCENTILE_TO_PLOT)

    figure_object = plotter._plot_one_value(
        data_matrix=far_matrix,
        grid_metadata_dict=grid_metadata_dict,
        colour_map_object=CMAP_OBJECT_FOR_FAR,
        min_colour_value=this_min_value,
        max_colour_value=this_max_value,
        plot_cbar_min_arrow=this_min_value > 0.,
        plot_cbar_max_arrow=this_max_value < 1.)[0]

    far_file_name = '{0:s}/false_alarm_ratio.jpg'.format(output_dir_name)

    print('Saving figure to: "{0:s}"...'.format(far_file_name))
    figure_object.savefig(far_file_name,
                          dpi=FIGURE_RESOLUTION_DPI,
                          pad_inches=0,
                          bbox_inches='tight')
    pyplot.close(figure_object)
def _run(top_radar_dir_name, top_echo_classifn_dir_name, valid_time_string,
         min_latitude_deg, max_latitude_deg, min_longitude_deg,
         max_longitude_deg, output_dir_name):
    """Makes figure to explain storm detection.

    This is effectively the main method.

    :param top_radar_dir_name: See documentation at top of file.
    :param top_echo_classifn_dir_name: Same.
    :param valid_time_string: Same.
    :param min_latitude_deg: Same.
    :param max_latitude_deg: Same.
    :param min_longitude_deg: Same.
    :param max_longitude_deg: Same.
    :param output_dir_name: Same.
    """

    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=output_dir_name
    )

    valid_time_unix_sec = time_conversion.string_to_unix_sec(
        valid_time_string, TIME_FORMAT
    )
    spc_date_string = time_conversion.time_to_spc_date_string(
        valid_time_unix_sec
    )

    num_trials = len(MIN_POLYGON_SIZES_PX)
    tracking_dir_names = [None] * num_trials

    for k in range(num_trials):
        tracking_dir_names[k] = (
            '{0:s}/tracking/min-polygon-size-px={1:d}_recompute-centroids={2:d}'
        ).format(
            output_dir_name, MIN_POLYGON_SIZES_PX[k],
            int(RECOMPUTE_CENTROID_FLAGS[k])
        )

        echo_top_tracking.run_tracking(
            top_radar_dir_name=top_radar_dir_name,
            top_output_dir_name=tracking_dir_names[k],
            first_spc_date_string=spc_date_string,
            last_spc_date_string=spc_date_string,
            first_time_unix_sec=valid_time_unix_sec,
            last_time_unix_sec=valid_time_unix_sec + 1,
            top_echo_classifn_dir_name=top_echo_classifn_dir_name,
            min_polygon_size_pixels=MIN_POLYGON_SIZES_PX[k],
            recompute_centroids=RECOMPUTE_CENTROID_FLAGS[k]
        )
        print(SEPARATOR_STRING)

    echo_top_file_name = myrorss_and_mrms_io.find_raw_file(
        top_directory_name=top_radar_dir_name,
        unix_time_sec=valid_time_unix_sec, spc_date_string=spc_date_string,
        field_name=radar_utils.ECHO_TOP_40DBZ_NAME,
        data_source=radar_utils.MYRORSS_SOURCE_ID, raise_error_if_missing=True
    )

    print('Reading data from: "{0:s}"...'.format(echo_top_file_name))

    metadata_dict = myrorss_and_mrms_io.read_metadata_from_raw_file(
        netcdf_file_name=echo_top_file_name,
        data_source=radar_utils.MYRORSS_SOURCE_ID
    )

    sparse_grid_table = myrorss_and_mrms_io.read_data_from_sparse_grid_file(
        netcdf_file_name=echo_top_file_name,
        field_name_orig=metadata_dict[
            myrorss_and_mrms_io.FIELD_NAME_COLUMN_ORIG],
        data_source=radar_utils.MYRORSS_SOURCE_ID,
        sentinel_values=metadata_dict[radar_utils.SENTINEL_VALUE_COLUMN]
    )

    echo_top_matrix_km_asl, radar_latitudes_deg, radar_longitudes_deg = (
        radar_s2f.sparse_to_full_grid(
            sparse_grid_table=sparse_grid_table, metadata_dict=metadata_dict)
    )

    echo_top_matrix_km_asl = numpy.flip(echo_top_matrix_km_asl, axis=0)
    radar_latitudes_deg = radar_latitudes_deg[::-1]

    echo_classifn_file_name = echo_classifn.find_classification_file(
        top_directory_name=top_echo_classifn_dir_name,
        valid_time_unix_sec=valid_time_unix_sec,
        desire_zipped=True, allow_zipped_or_unzipped=True,
        raise_error_if_missing=True
    )

    print('Reading data from: "{0:s}"...'.format(echo_classifn_file_name))
    convective_flag_matrix = echo_classifn.read_classifications(
        echo_classifn_file_name
    )[0]

    good_indices = numpy.where(numpy.logical_and(
        radar_latitudes_deg >= min_latitude_deg,
        radar_latitudes_deg <= max_latitude_deg
    ))[0]

    echo_top_matrix_km_asl = echo_top_matrix_km_asl[good_indices, ...]
    convective_flag_matrix = convective_flag_matrix[good_indices, ...]
    radar_latitudes_deg = radar_latitudes_deg[good_indices]

    good_indices = numpy.where(numpy.logical_and(
        radar_longitudes_deg >= min_longitude_deg,
        radar_longitudes_deg <= max_longitude_deg
    ))[0]

    echo_top_matrix_km_asl = echo_top_matrix_km_asl[..., good_indices]
    convective_flag_matrix = convective_flag_matrix[..., good_indices]
    radar_longitudes_deg = radar_longitudes_deg[good_indices]

    this_figure_object, this_axes_object = _plot_echo_tops(
        echo_top_matrix_km_asl=echo_top_matrix_km_asl,
        latitudes_deg=radar_latitudes_deg, longitudes_deg=radar_longitudes_deg,
        plot_colour_bar=False, convective_flag_matrix=None
    )[:2]

    this_axes_object.set_title('All echoes')
    plotting_utils.label_axes(axes_object=this_axes_object, label_string='(a)')

    panel_file_names = [
        '{0:s}/before_echo_classification.jpg'.format(output_dir_name)
    ]

    print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1]))
    this_figure_object.savefig(
        panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI,
        pad_inches=0, bbox_inches='tight'
    )
    pyplot.close(this_figure_object)

    this_figure_object, this_axes_object = _plot_echo_tops(
        echo_top_matrix_km_asl=echo_top_matrix_km_asl,
        latitudes_deg=radar_latitudes_deg, longitudes_deg=radar_longitudes_deg,
        plot_colour_bar=False, convective_flag_matrix=convective_flag_matrix
    )[:2]

    this_axes_object.set_title('Convective echoes only')
    plotting_utils.label_axes(axes_object=this_axes_object, label_string='(b)')

    panel_file_names.append(
        '{0:s}/after_echo_classification.jpg'.format(output_dir_name)
    )

    print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1]))
    this_figure_object.savefig(
        panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI,
        pad_inches=0, bbox_inches='tight'
    )
    pyplot.close(this_figure_object)

    letter_label = 'b'

    for k in range(num_trials):
        this_tracking_file_name = tracking_io.find_file(
            top_tracking_dir_name=tracking_dir_names[k],
            tracking_scale_metres2=
            echo_top_tracking.DUMMY_TRACKING_SCALE_METRES2,
            source_name=tracking_utils.SEGMOTION_NAME,
            valid_time_unix_sec=valid_time_unix_sec,
            spc_date_string=spc_date_string,
            raise_error_if_missing=True
        )

        print('Reading data from: "{0:s}"...'.format(this_tracking_file_name))
        this_storm_object_table = tracking_io.read_file(this_tracking_file_name)

        this_figure_object, this_axes_object, this_basemap_object = (
            _plot_echo_tops(
                echo_top_matrix_km_asl=echo_top_matrix_km_asl,
                latitudes_deg=radar_latitudes_deg,
                longitudes_deg=radar_longitudes_deg, plot_colour_bar=k > 0,
                convective_flag_matrix=convective_flag_matrix)
        )

        storm_plotting.plot_storm_outlines(
            storm_object_table=this_storm_object_table,
            axes_object=this_axes_object, basemap_object=this_basemap_object,
            line_width=POLYGON_WIDTH, line_colour=POLYGON_COLOUR
        )

        these_x_metres, these_y_metres = this_basemap_object(
            this_storm_object_table[
                tracking_utils.CENTROID_LONGITUDE_COLUMN].values,
            this_storm_object_table[
                tracking_utils.CENTROID_LATITUDE_COLUMN].values
        )

        this_axes_object.plot(
            these_x_metres, these_y_metres, linestyle='None',
            marker=MARKER_TYPE, markersize=MARKER_SIZE,
            markerfacecolor=MARKER_COLOUR, markeredgecolor=MARKER_COLOUR,
            markeredgewidth=MARKER_EDGE_WIDTH
        )

        this_title_string = (
            'Minimum size = {0:d} GP, {1:s} storm centers'
        ).format(
            MIN_POLYGON_SIZES_PX[k],
            'recomputed' if RECOMPUTE_CENTROID_FLAGS[k] else 'original'
        )

        this_axes_object.set_title(this_title_string)

        letter_label = chr(ord(letter_label) + 1)
        plotting_utils.label_axes(
            axes_object=this_axes_object,
            label_string='({0:s})'.format(letter_label)
        )

        panel_file_names.append(
            '{0:s}/detection{1:d}.jpg'.format(output_dir_name, k)
        )

        print('Saving figure to: "{0:s}"...'.format(panel_file_names[-1]))
        this_figure_object.savefig(
            panel_file_names[-1], dpi=FIGURE_RESOLUTION_DPI,
            pad_inches=0, bbox_inches='tight'
        )
        pyplot.close(this_figure_object)

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

    imagemagick_utils.concatenate_images(
        input_file_names=panel_file_names, output_file_name=concat_file_name,
        num_panel_rows=3, num_panel_columns=2
    )