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
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)
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)
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()
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 )