コード例 #1
0
def _run(top_linkage_dir_name, genesis_only, max_link_distance_metres,
         first_spc_date_string, last_spc_date_string, num_colours,
         min_plot_latitude_deg, max_plot_latitude_deg, min_plot_longitude_deg,
         max_plot_longitude_deg, output_file_name):
    """Plots tornado reports, storm tracks, and linkages.

    This is effectively the main method.

    :param top_linkage_dir_name: See documentation at top of file.
    :param genesis_only: Same.
    :param max_link_distance_metres: Same.
    :param first_spc_date_string: Same.
    :param last_spc_date_string: Same.
    :param num_colours: Same.
    :param min_plot_latitude_deg: Same.
    :param max_plot_latitude_deg: Same.
    :param min_plot_longitude_deg: Same.
    :param max_plot_longitude_deg: Same.
    :param output_file_name: Same.
    """

    if max_link_distance_metres < 0:
        max_link_distance_metres = None

    colour_map_object = _truncate_colour_map(
        orig_colour_map_object=pyplot.cm.get_cmap('YlOrRd'),
        num_colours=num_colours)

    event_type_string = (linkage.TORNADOGENESIS_EVENT_STRING
                         if genesis_only else linkage.TORNADO_EVENT_STRING)

    if min_plot_latitude_deg <= SENTINEL_VALUE:
        min_plot_latitude_deg = None
    if max_plot_latitude_deg <= SENTINEL_VALUE:
        max_plot_latitude_deg = None
    if min_plot_longitude_deg <= SENTINEL_VALUE:
        min_plot_longitude_deg = None
    if max_plot_longitude_deg <= SENTINEL_VALUE:
        max_plot_longitude_deg = None

    file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name)

    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)

    list_of_linkage_tables = []
    list_of_tornado_tables = []
    linkage_metadata_dict = None

    for this_spc_date_string in spc_date_strings:
        this_file_name = linkage.find_linkage_file(
            top_directory_name=top_linkage_dir_name,
            event_type_string=event_type_string,
            spc_date_string=this_spc_date_string,
            raise_error_if_missing=False)

        if not os.path.isfile(this_file_name):
            continue

        print('Reading data from: "{0:s}"...'.format(this_file_name))
        this_linkage_table, linkage_metadata_dict, this_tornado_table = (
            linkage.read_linkage_file(this_file_name))

        list_of_linkage_tables.append(this_linkage_table)
        list_of_tornado_tables.append(this_tornado_table)

        if len(list_of_linkage_tables) == 1:
            continue

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

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

    print(SEPARATOR_STRING)

    storm_to_tornadoes_table = pandas.concat(list_of_linkage_tables,
                                             axis=0,
                                             ignore_index=True)
    tornado_table = pandas.concat(list_of_tornado_tables,
                                  axis=0,
                                  ignore_index=True)

    column_dict_old_to_new = {
        linkage.EVENT_TIME_COLUMN: tornado_io.TIME_COLUMN,
        linkage.EVENT_LATITUDE_COLUMN: tornado_io.LATITUDE_COLUMN,
        linkage.EVENT_LONGITUDE_COLUMN: tornado_io.LONGITUDE_COLUMN
    }

    tornado_table.rename(columns=column_dict_old_to_new, inplace=True)
    tornado_table = tornado_io.segments_to_tornadoes(tornado_table)

    tornado_table = tornado_table.assign(
        **{
            SHORT_TORNADO_ID_COLUMN:
            _long_to_short_tornado_ids(tornado_table[
                tornado_io.TORNADO_ID_COLUMN].values)
        })

    if min_plot_latitude_deg is None:
        min_plot_latitude_deg = numpy.min(
            storm_to_tornadoes_table[tracking_utils.CENTROID_LATITUDE_COLUMN].
            values) - LATLNG_BUFFER_DEG

    if max_plot_latitude_deg is None:
        max_plot_latitude_deg = numpy.max(
            storm_to_tornadoes_table[tracking_utils.CENTROID_LATITUDE_COLUMN].
            values) + LATLNG_BUFFER_DEG

    if min_plot_longitude_deg is None:
        min_plot_longitude_deg = numpy.min(
            storm_to_tornadoes_table[tracking_utils.CENTROID_LONGITUDE_COLUMN].
            values) - LATLNG_BUFFER_DEG

    if max_plot_longitude_deg is None:
        max_plot_longitude_deg = numpy.max(
            storm_to_tornadoes_table[tracking_utils.CENTROID_LONGITUDE_COLUMN].
            values) + LATLNG_BUFFER_DEG

    # TODO(thunderhoser): Should maybe restrict this to an inner domain.
    storm_to_tornadoes_table = storm_to_tornadoes_table.loc[
        (storm_to_tornadoes_table[tracking_utils.CENTROID_LATITUDE_COLUMN] >=
         min_plot_latitude_deg)
        & (storm_to_tornadoes_table[tracking_utils.CENTROID_LATITUDE_COLUMN] <=
           max_plot_latitude_deg)]

    storm_to_tornadoes_table = storm_to_tornadoes_table.loc[
        (storm_to_tornadoes_table[tracking_utils.CENTROID_LONGITUDE_COLUMN] >=
         min_plot_longitude_deg)
        & (storm_to_tornadoes_table[tracking_utils.CENTROID_LONGITUDE_COLUMN]
           <= max_plot_longitude_deg)]

    tornado_io.subset_tornadoes(tornado_table=tornado_table,
                                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)

    # TODO(thunderhoser): Make this subsetting optional.
    storm_to_tornadoes_table = _subset_storms_by_time(
        storm_to_tornadoes_table=storm_to_tornadoes_table,
        tornado_table=tornado_table,
        linkage_metadata_dict=linkage_metadata_dict,
        genesis_only=genesis_only)

    print(SEPARATOR_STRING)

    _, 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)

    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)

    print('Plotting storm tracks...')
    storm_plotting.plot_storm_tracks(
        storm_object_table=storm_to_tornadoes_table,
        axes_object=axes_object,
        basemap_object=basemap_object,
        colour_map_object=colour_map_object,
        start_marker_type=None,
        end_marker_type=None)

    num_tornadoes = len(tornado_table.index)
    if num_tornadoes == 0:
        print('Saving figure to: "{0:s}"...'.format(output_file_name))
        pyplot.savefig(output_file_name, dpi=FIGURE_RESOLUTION_DPI)
        pyplot.close()
        return

    colour_norm_object = pyplot.Normalize(
        numpy.min(
            storm_to_tornadoes_table[tracking_utils.VALID_TIME_COLUMN].values),
        numpy.max(
            storm_to_tornadoes_table[tracking_utils.VALID_TIME_COLUMN].values))

    print('Plotting tornado markers...')
    _plot_tornadoes(tornado_table=tornado_table,
                    colour_map_object=colour_map_object,
                    colour_norm_object=colour_norm_object,
                    genesis_only=genesis_only,
                    axes_object=axes_object,
                    basemap_object=basemap_object)

    print('Plotting tornado IDs with storm objects...')
    num_storm_objects = len(storm_to_tornadoes_table.index)

    for i in range(num_storm_objects):
        _plot_linkages_one_storm_object(
            storm_to_tornadoes_table=storm_to_tornadoes_table,
            storm_object_index=i,
            tornado_table=tornado_table,
            colour_map_object=colour_map_object,
            colour_norm_object=colour_norm_object,
            axes_object=axes_object,
            basemap_object=basemap_object,
            max_link_distance_metres=max_link_distance_metres)

    print('Saving figure to: "{0:s}"...'.format(output_file_name))
    pyplot.savefig(output_file_name, dpi=FIGURE_RESOLUTION_DPI)
    pyplot.close()
コード例 #2
0
def _run(tornado_dir_name, top_linkage_dir_name, top_myrorss_dir_name,
         genesis_only, spc_date_string, max_link_distance_metres,
         radar_field_name, radar_height_m_asl, output_dir_name):
    """Plots tornado reports that could not be linked to a storm.

    This is effectively the main method.

    :param tornado_dir_name: See documentation at top of file.
    :param top_linkage_dir_name: Same.
    :param top_myrorss_dir_name: Same.
    :param genesis_only: Same.
    :param spc_date_string: Same.
    :param max_link_distance_metres: Same.
    :param radar_field_name: Same.
    :param radar_height_m_asl: Same.
    :param output_dir_name: Same.
    """

    event_type_string = (linkage.TORNADOGENESIS_EVENT_STRING
                         if genesis_only else linkage.TORNADO_EVENT_STRING)

    if max_link_distance_metres <= 0.:
        max_link_distance_metres = numpy.inf

    file_system_utils.mkdir_recursive_if_necessary(
        directory_name=output_dir_name)

    linkage_file_name = linkage.find_linkage_file(
        top_directory_name=top_linkage_dir_name,
        event_type_string=event_type_string,
        spc_date_string=spc_date_string)

    print('Reading data from: "{0:s}"...'.format(linkage_file_name))
    storm_to_tornadoes_table, metadata_dict = linkage.read_linkage_file(
        linkage_file_name)[:2]

    num_storm_objects = len(storm_to_tornadoes_table.index)
    if num_storm_objects == 0:
        print(
            'No storms for SPC date "{0:s}".  There is nothing to do!'.format(
                spc_date_string))

        return

    print('Removing linkages with distance > {0:.1f} metres...'.format(
        max_link_distance_metres))

    for i in range(num_storm_objects):
        these_link_distance_metres = storm_to_tornadoes_table[
            linkage.LINKAGE_DISTANCES_COLUMN].values[i]

        if len(these_link_distance_metres) == 0:
            continue

        these_good_indices = numpy.where(
            these_link_distance_metres <= max_link_distance_metres)[0]

        storm_to_tornadoes_table[linkage.TORNADO_IDS_COLUMN].values[i] = [
            storm_to_tornadoes_table[linkage.TORNADO_IDS_COLUMN].values[i][k]
            for k in these_good_indices
        ]

    # TODO(thunderhoser): Might be able to just read this from linkage file.
    tornado_table = linkage._read_input_tornado_reports(
        input_directory_name=tornado_dir_name,
        storm_times_unix_sec=storm_to_tornadoes_table[
            tracking_utils.VALID_TIME_COLUMN].values,
        max_time_before_storm_start_sec=metadata_dict[
            linkage.MAX_TIME_BEFORE_START_KEY],
        max_time_after_storm_end_sec=metadata_dict[
            linkage.MAX_TIME_AFTER_END_KEY])

    num_tornadoes = len(tornado_table.index)
    if num_tornadoes == 0:
        print(('No tornadoes for SPC date "{0:s}".  There is nothing to do!'
               ).format(spc_date_string))

        return

    print('\nRemoving tornadoes outside bounding box of storms...')

    min_storm_latitude_deg = numpy.min(storm_to_tornadoes_table[
        tracking_utils.CENTROID_LATITUDE_COLUMN].values)
    max_storm_latitude_deg = numpy.max(storm_to_tornadoes_table[
        tracking_utils.CENTROID_LATITUDE_COLUMN].values)
    min_storm_longitude_deg = numpy.min(storm_to_tornadoes_table[
        tracking_utils.CENTROID_LONGITUDE_COLUMN].values)
    max_storm_longitude_deg = numpy.max(storm_to_tornadoes_table[
        tracking_utils.CENTROID_LONGITUDE_COLUMN].values)

    latitude_flags = numpy.logical_and(
        tornado_table[linkage.EVENT_LATITUDE_COLUMN].values >=
        min_storm_latitude_deg,
        tornado_table[linkage.EVENT_LATITUDE_COLUMN].values <=
        max_storm_latitude_deg)

    longitude_flags = numpy.logical_and(
        tornado_table[linkage.EVENT_LONGITUDE_COLUMN].values >=
        min_storm_longitude_deg,
        tornado_table[linkage.EVENT_LONGITUDE_COLUMN].values <=
        max_storm_longitude_deg)

    good_indices = numpy.where(
        numpy.logical_and(latitude_flags, longitude_flags))[0]

    tornado_table = tornado_table.iloc[good_indices]
    num_tornadoes = len(tornado_table.index)

    if num_tornadoes == 0:
        print('No tornadoes in bounding box.  There is nothing more to do!')
        return

    print('Finding unlinked tornadoes...')

    tornado_table = tornado_io.add_tornado_ids_to_table(tornado_table)

    linked_tornado_id_strings = list(
        chain(*storm_to_tornadoes_table[linkage.TORNADO_IDS_COLUMN].values))

    unlinked_flags = numpy.array([
        s not in linked_tornado_id_strings
        for s in tornado_table[tornado_io.TORNADO_ID_COLUMN].values
    ],
                                 dtype=bool)

    unlinked_indices = numpy.where(unlinked_flags)[0]
    if len(unlinked_indices) == 0:
        print('All tornadoes were linked.  Success!')
        return

    print(SEPARATOR_STRING)

    unlinked_indices = numpy.array(unlinked_indices, dtype=int)
    tornado_table = tornado_table.iloc[unlinked_indices]
    num_tornadoes = len(tornado_table.index)

    for j in range(num_tornadoes):
        this_output_file_name = (
            '{0:s}/unlinked_tornado_{1:s}_{2:03d}.jpg').format(
                output_dir_name, spc_date_string, j)

        _plot_tornado_and_radar(top_myrorss_dir_name=top_myrorss_dir_name,
                                radar_field_name=radar_field_name,
                                radar_height_m_asl=radar_height_m_asl,
                                spc_date_string=spc_date_string,
                                tornado_table=tornado_table,
                                tornado_row=j,
                                output_file_name=this_output_file_name)
コード例 #3
0
def _run(top_linkage_dir_name, spc_date_string, min_lead_times_sec,
         max_lead_times_sec, min_link_distances_metres,
         max_link_distances_metres, event_type_string,
         wind_speed_percentile_level, wind_speed_cutoffs_kt,
         top_output_dir_name):
    """Computes target value for ea storm object, lead-time window, and buffer.

    This is effectively the main method.

    :param top_linkage_dir_name: See documentation at top of file.
    :param spc_date_string: Same.
    :param min_lead_times_sec: Same.
    :param max_lead_times_sec: Same.
    :param min_link_distances_metres: Same.
    :param max_link_distances_metres: Same.
    :param event_type_string: Same.
    :param wind_speed_percentile_level: Same.
    :param wind_speed_cutoffs_kt: Same.
    :param top_output_dir_name: Same.
    """

    num_lead_time_windows = len(min_lead_times_sec)
    error_checking.assert_is_numpy_array(
        max_lead_times_sec,
        exact_dimensions=numpy.array([num_lead_time_windows])
    )

    num_distance_buffers = len(min_link_distances_metres)
    error_checking.assert_is_numpy_array(
        max_link_distances_metres,
        exact_dimensions=numpy.array([num_distance_buffers])
    )

    linkage_file_name = linkage.find_linkage_file(
        top_directory_name=top_linkage_dir_name,
        event_type_string=event_type_string, spc_date_string=spc_date_string)

    print 'Reading data from: "{0:s}"...'.format(linkage_file_name)
    storm_to_events_table = linkage.read_linkage_file(linkage_file_name)

    if event_type_string == linkage.WIND_EVENT_STRING:
        list_of_cutoff_arrays_kt = general_utils.split_array_by_nan(
            wind_speed_cutoffs_kt)
        num_cutoff_sets = len(wind_speed_cutoffs_kt)
    else:
        list_of_cutoff_arrays_kt = None
        num_cutoff_sets = 1

    target_names = []

    for i in range(num_lead_time_windows):
        for j in range(num_distance_buffers):
            for k in range(num_cutoff_sets):
                if event_type_string == linkage.WIND_EVENT_STRING:
                    this_target_name = target_val_utils.target_params_to_name(
                        min_lead_time_sec=min_lead_times_sec[i],
                        max_lead_time_sec=max_lead_times_sec[i],
                        min_link_distance_metres=min_link_distances_metres[j],
                        max_link_distance_metres=max_link_distances_metres[j],
                        wind_speed_percentile_level=wind_speed_percentile_level,
                        wind_speed_cutoffs_kt=list_of_cutoff_arrays_kt[k])

                    target_names.append(this_target_name)
                    print 'Computing values for "{0:s}"...'.format(
                        target_names[-1])

                    storm_to_events_table = (
                        target_val_utils.create_wind_classification_targets(
                            storm_to_winds_table=storm_to_events_table,
                            min_lead_time_sec=min_lead_times_sec[i],
                            max_lead_time_sec=max_lead_times_sec[i],
                            min_link_distance_metres=min_link_distances_metres[
                                j],
                            max_link_distance_metres=max_link_distances_metres[
                                j],
                            percentile_level=wind_speed_percentile_level,
                            class_cutoffs_kt=list_of_cutoff_arrays_kt[k])
                    )
                else:
                    this_target_name = target_val_utils.target_params_to_name(
                        min_lead_time_sec=min_lead_times_sec[i],
                        max_lead_time_sec=max_lead_times_sec[i],
                        min_link_distance_metres=min_link_distances_metres[j],
                        max_link_distance_metres=max_link_distances_metres[j])

                    target_names.append(this_target_name)
                    print 'Computing values for "{0:s}"...'.format(
                        target_names[-1])

                    storm_to_events_table = (
                        target_val_utils.create_tornado_targets(
                            storm_to_tornadoes_table=storm_to_events_table,
                            min_lead_time_sec=min_lead_times_sec[i],
                            max_lead_time_sec=max_lead_times_sec[i],
                            min_link_distance_metres=min_link_distances_metres[
                                j],
                            max_link_distance_metres=max_link_distances_metres[
                                j]
                        )
                    )

    target_file_name = target_val_utils.find_target_file(
        top_directory_name=top_output_dir_name,
        event_type_string=event_type_string, spc_date_string=spc_date_string,
        raise_error_if_missing=False)

    print 'Writing target values to: "{0:s}"...'.format(target_file_name)
    target_val_utils.write_target_values(
        storm_to_events_table=storm_to_events_table, target_names=target_names,
        netcdf_file_name=target_file_name)
コード例 #4
0
def _run(top_linkage_dir_name, first_spc_date_string, last_spc_date_string,
         min_lead_times_sec, max_lead_times_sec, min_link_distances_metres,
         max_link_distances_metres, event_type_string,
         wind_speed_percentile_level, wind_speed_cutoffs_kt,
         top_output_dir_name):
    """Computes target value for ea storm object, lead-time window, and buffer.

    This is effectively the main method.

    :param top_linkage_dir_name: See documentation at top of file.
    :param first_spc_date_string: Same.
    :param last_spc_date_string: Same.
    :param min_lead_times_sec: Same.
    :param max_lead_times_sec: Same.
    :param min_link_distances_metres: Same.
    :param max_link_distances_metres: Same.
    :param event_type_string: Same.
    :param wind_speed_percentile_level: Same.
    :param wind_speed_cutoffs_kt: Same.
    :param top_output_dir_name: Same.
    """

    num_lead_time_windows = len(min_lead_times_sec)
    these_expected_dim = numpy.array([num_lead_time_windows], dtype=int)
    error_checking.assert_is_numpy_array(max_lead_times_sec,
                                         exact_dimensions=these_expected_dim)

    num_distance_buffers = len(min_link_distances_metres)
    these_expected_dim = numpy.array([num_distance_buffers], dtype=int)
    error_checking.assert_is_numpy_array(max_link_distances_metres,
                                         exact_dimensions=these_expected_dim)

    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:
        this_linkage_file_name = linkage.find_linkage_file(
            top_directory_name=top_linkage_dir_name,
            event_type_string=event_type_string,
            spc_date_string=this_spc_date_string,
            raise_error_if_missing=False)

        if not os.path.isfile(this_linkage_file_name):
            continue

        print('Reading data from: "{0:s}"...'.format(this_linkage_file_name))
        this_storm_to_events_table = linkage.read_linkage_file(
            this_linkage_file_name)[0]

        _compute_targets_one_day(
            storm_to_events_table=this_storm_to_events_table,
            spc_date_string=this_spc_date_string,
            min_lead_times_sec=min_lead_times_sec,
            max_lead_times_sec=max_lead_times_sec,
            min_link_distances_metres=min_link_distances_metres,
            max_link_distances_metres=max_link_distances_metres,
            event_type_string=event_type_string,
            wind_speed_percentile_level=wind_speed_percentile_level,
            wind_speed_cutoffs_kt=wind_speed_cutoffs_kt,
            top_output_dir_name=top_output_dir_name)