From 11866b3d663cf1268c5dfdef0aa13f926b53c5b0 Mon Sep 17 00:00:00 2001 From: johnhg Date: Fri, 9 Apr 2021 15:14:15 -0600 Subject: [PATCH] Feature 1714 tc_gen (#1750) * Per #1714, add tc_gen genesis_match_window configuration option to define a search window relative to the forecast genesis time. * Per #1714, clarify docs to state the genesis_match_window.end = 12 allows for matches for early forecasts. Also add an example of this option to the tc_gen unit test. * Per #1714, switch ops_hit_tdiff to ops_hit_window. * Per #1714, skip genesis events for tracks where the cyclone number is > 50. * Per #1714, only discard cyclone numbers > 50 from the Best track, not the forecast tracks. * Per #1716, add note to the tc_gen chapter about skipping Best tracks with cyclone number > 50. * Per #1714, adding genesis_match_point_to_track config file option for TC-Gen. Note that this version of the code is close but doesn't actually compile yet. I still need to figure out exactly how to process the operational tracks. Should this logic also apply to the matching for those tracks? * Per #1714, the logic for checking the operational tracks is pretty simple. We only store/check operational track points for lead time = 0. So applying the genesis_match_point_to_track boolean config option does not make sense. * Per #1714, update the tc-gen user's guide chapter to describe the updated logic and new config file option. * Per #1714, fix the logic of the is_match() function. * Per #1714, reconfigure the call to tc_gen to exercise the new genesis_match_track_to_point option. * Per #1714, just fixing spacing in source code. * Committing 2 small changes not specifically related to #1714, but related the processing of genesis tracks. When getting items from ATCFGenLines, the columns to be shifted are off by one. We had been shifting offset 2 up to 3, but it should have remained at 2. Also when initializing a TrackInfo object, set the StormID by calling ATCFLineBase::storm_id() instead of constructing it from BASIN:CYCLONE:YYYY. For ATCFGenLines we want to set the Storm ID equal to the 3rd column rather than constructing it! * Per #1714, fix an error in the logic of GenesisInfo::is_match(const GenesisInfo &,...). I was using the index of the current GenesisInfo object instead of the one from the input argument. Fix this by adding GenesisInfo::genesis() member function to return a reference the TrackPoint for Genesis. * Per #1714, correcting logic for parsing the storm_id and warning_time columns for ATCFGen and regular ATCF line types. For ATCFGen line types, the code was incorrectly using the 3rd column when it should have used the 4th column! Co-authored-by: John Halley Gotway --- met/data/config/TCGenConfig_default | 27 +++++- met/docs/Users_Guide/tc-gen.rst | 36 +++++-- met/src/basic/vx_config/config_constants.h | 4 +- met/src/libcode/vx_tc_util/atcf_line_base.cc | 16 +++- met/src/libcode/vx_tc_util/genesis_info.cc | 25 ++++- met/src/libcode/vx_tc_util/genesis_info.h | 14 +-- met/src/libcode/vx_tc_util/track_info.cc | 2 +- met/src/tools/tc_utils/tc_gen/tc_gen.cc | 95 +++++++++++++------ met/src/tools/tc_utils/tc_gen/tc_gen.h | 4 + .../tools/tc_utils/tc_gen/tc_gen_conf_info.cc | 28 ++++-- .../tools/tc_utils/tc_gen/tc_gen_conf_info.h | 14 +-- test/config/TCGenConfig_2016 | 40 +++++++- 12 files changed, 229 insertions(+), 76 deletions(-) diff --git a/met/data/config/TCGenConfig_default b/met/data/config/TCGenConfig_default index db38b1302b..1a135491f5 100644 --- a/met/data/config/TCGenConfig_default +++ b/met/data/config/TCGenConfig_default @@ -150,18 +150,34 @@ dland_thresh = NA; // //////////////////////////////////////////////////////////////////////////////// +// +// Genesis matching logic. Compare the forecast genesis point to all points in +// the Best track (TRUE) or the single Best track genesis point (FALSE). +// +genesis_match_point_to_track = TRUE; + // // Radius in km to search for a matching genesis event // genesis_match_radius = 500; +// +// Time window in hours, relative to the model genesis time, to search for a +// matching Best track point +// +genesis_match_window = { + beg = 0; + end = 0; +} + // // Radius in km for a development scoring method hit // dev_hit_radius = 500; // -// Time window in hours for a development scoring method hit +// Time window in hours, relative to the model genesis time, for a development +// scoring method hit // dev_hit_window = { beg = -24; @@ -169,10 +185,13 @@ dev_hit_window = { } // -// Maximum Best track genesis minus model initialization time difference for an -// operational scoring method hit +// Time window in hours for the Best track genesis minus model initialization +// time difference for an operational scoring method hit // -ops_hit_tdiff = 48; +ops_hit_window = { + beg = 0; + end = 48; +} // // Discard genesis forecasts for initializations at or after the matching diff --git a/met/docs/Users_Guide/tc-gen.rst b/met/docs/Users_Guide/tc-gen.rst index 90bf81ec86..763c5663b4 100644 --- a/met/docs/Users_Guide/tc-gen.rst +++ b/met/docs/Users_Guide/tc-gen.rst @@ -65,15 +65,15 @@ The TC-Gen tool implements the following logic: * Parse the forecast genesis data and identify forecast genesis events separately for each model present. -* Parse the Best and operational track data, and identify Best track genesis events. +* Parse the Best and operational track data, and identify Best track genesis events. Note that Best tracks with a cyclone number greater than 50 are automatically discarded from the analysis. Large cyclone numbers are used for pre-season testing or to track invests prior to a storm actually forming. Running this tool at verbosity level 6 (-v 6) prints details about which tracks are discarded. * Loop over the filters defined in the configuration file and apply the following logic for each. * For each Best track genesis event meeting the filter critera, determine the initialization and lead times for which the model had an opportunity to forecast that genesis event. Store an unmatched genesis pair for each case. - * For each forecast genesis event, search for a matching Best track. A Best track matches if the valid time of one of its track points matches the forecast genesis time and is within a configurable radius of the forecast genesis location. If a Best track match is found, store the storm ID. + * For each forecast genesis event, search for a matching Best track. A configurable boolean option controls whether all Best track points are considered for a match or only the single Best track genesis point. A match occurs if the Best track point valid time is within a configurable window around the forecast genesis time and the Best track point location is within a configurable radius of the forecast genesis location. If a Best track match is found, store the storm ID. - * In no Best track match is found, apply the same logic to search the 0-hour operational track points. If an operational match is found, store the storm ID. + * In no Best track match is found, apply the same logic to search the operational track points with lead time of 0 hours. If an operational match is found, store the storm ID. * If a matching storm ID is found, match the forecast genesis event to the Best track genesis event for that storm ID. @@ -255,11 +255,30 @@ The **dland_thresh** entry is a threshold defining whether the genesis event sho ______________________ +.. code-block:: none + + genesis_match_point_to_track = TRUE; + +The **genesis_match_point_to_track** entry is a boolean which controls the matching logic. When set to its default value of TRUE, for each forecast genesis event, all Best track points are searched for a match. This logic implements the method used by the NOAA National Hurricane Center. When set to FALSE, only the single Best track genesis point is considered for a match. When selecting FALSE, users are encouraged to adjust the **genesis_match_radius** and/or **gensesis_match_window** options, described below, to enable matches to be found. + +______________________ + .. code-block:: none genesis_match_radius = 500; -The **genesis_match_radius** entry defines a search radius, in km, relative to the forecast genesis location. When searching for a match, only those Best genesis events which occur within this radius will be considered. Increasing this search radius should lead to an increase in the number of matched genesis pairs. +The **genesis_match_radius** entry defines a search radius, in km, relative to the forecast genesis location. When searching for a match, only Best or operational tracks with a track point within this radius will be considered. Increasing this search radius should lead to an increase in the number of matched genesis pairs. + +______________________ + +.. code-block:: none + + genesis_match_window = { + beg = 0; + end = 0; + } + +The **genesis_match_window** entry defines a time window, in hours, relative to the forecast genesis time. When searching for a match, only Best or operational tracks with a track point falling within this time window will be considered. The default time window of 0 requires a Best or operational track to exist at the forecast genesis time for a match to be found. Increasing this time window should lead to an increase in the number matched genesis pairs. For example, setting *end = 12;* would allow forecast genesis events to match Best tracks up to 12 hours prior to their existence. ______________________ @@ -278,15 +297,18 @@ ______________________ end = 24; } -The **dev_hit_window** entry defines a time window, in hours, relative to the forecast genesis time. The Best track genesis event must occur within this time window for the pair to be counted as contingency table HIT for the development scoring method. Tightening this window may cause development method HITS to become FALSE ALARMS. +The **dev_hit_window** entry defines a time window, in hours, relative to the forecast genesis time. The Best track genesis event must occur within this time window for the pair to be counted as a contingency table HIT for the development scoring method. Tightening this window may cause development method HITS to become FALSE ALARMS. ______________________ .. code-block:: none - ops_hit_tdiff = 48; + ops_hit_window = { + beg = 0; + end = 48; + } -The **ops_hit_tdiff** entry is an integer which defines a maximum allowable time difference in hours. For each matching forecast and Best track genesis event, if the difference between the Best track genesis time and the forecast initialization time is less than or equal to this value, then the pair is counted as a contingency table HIT for the operational scoring method. Otherwise, it is counted as a FALSE ALARM. +The **ops_hit_window** entry defines a time window, in hours, relative to the Best track genesis time. The model initialization time for the forecast genesis event must occur within this time window for the pairs to be counted as a contingency table HIT for the operationl scoring method. Otherwise, the pair is counted as a FALSE ALARM. ______________________ diff --git a/met/src/basic/vx_config/config_constants.h b/met/src/basic/vx_config/config_constants.h index bc82d55625..a6431fca54 100644 --- a/met/src/basic/vx_config/config_constants.h +++ b/met/src/basic/vx_config/config_constants.h @@ -1076,10 +1076,12 @@ static const char conf_key_category[] = "category"; static const char conf_key_vmax_thresh[] = "vmax_thresh"; static const char conf_key_mslp_thresh[] = "mslp_thresh"; static const char conf_key_basin_mask[] = "basin_mask"; +static const char conf_key_genesis_match_point_to_track[] = "genesis_match_point_to_track"; static const char conf_key_genesis_match_radius[] = "genesis_match_radius"; +static const char conf_key_genesis_match_window[] = "genesis_match_window"; static const char conf_key_dev_hit_radius[] = "dev_hit_radius"; static const char conf_key_dev_hit_window[] = "dev_hit_window"; -static const char conf_key_ops_hit_tdiff[] = "ops_hit_tdiff"; +static const char conf_key_ops_hit_window[] = "ops_hit_window"; static const char conf_key_discard_init_post_genesis_flag[] = "discard_init_post_genesis_flag"; static const char conf_key_dev_method_flag[] = "dev_method_flag"; static const char conf_key_ops_method_flag[] = "ops_method_flag"; diff --git a/met/src/libcode/vx_tc_util/atcf_line_base.cc b/met/src/libcode/vx_tc_util/atcf_line_base.cc index 5ae638f44f..aa970dc117 100644 --- a/met/src/libcode/vx_tc_util/atcf_line_base.cc +++ b/met/src/libcode/vx_tc_util/atcf_line_base.cc @@ -211,9 +211,12 @@ ConcatString ATCFLineBase::get_item(int i) const { int i_col = i; // For ATCFLineType_GenTrack: - // Columns 1 and 2 are consistent, use offsets 0 and 1 - // Columns 4-20 are the same as columns 3-19 of ATCFLineType_Track - // Shift those column indices by 1. + // Columns 1 and 2 are consistent: + // Use offsets 0 and 1 + // Column 3 for is an EXTRA column for this line type: + // Add special handling in storm_id() + // Columns 4-20 are the same as columns 3-19 of ATCFLineType_Track: + // Shift those column indices by 1. if(Type == ATCFLineType_GenTrack && i >= 2 && i <= 18) i_col++; cs = DataLine::get_item(i_col); @@ -252,7 +255,8 @@ ConcatString ATCFLineBase::basin() const { //////////////////////////////////////////////////////////////////////// ConcatString ATCFLineBase::cyclone_number() const { - return(get_item(CycloneNumberOffset)); } + return(get_item(CycloneNumberOffset)); +} //////////////////////////////////////////////////////////////////////// @@ -357,8 +361,10 @@ int ATCFLineBase::lead() const { ConcatString ATCFLineBase::storm_id() const { ConcatString cs; + // For ATCFLineType_GenTrack, use the contents of the extra 3rd column + // Call DataLine::get_item() to avoid the column shifting logic if(Type == ATCFLineType_GenTrack) { - cs = get_item(GenStormIdOffset); + cs = DataLine::get_item(GenStormIdOffset); } else { unixtime ut = valid(); diff --git a/met/src/libcode/vx_tc_util/genesis_info.cc b/met/src/libcode/vx_tc_util/genesis_info.cc index 8cc5ea36d9..91c708ff82 100644 --- a/met/src/libcode/vx_tc_util/genesis_info.cc +++ b/met/src/libcode/vx_tc_util/genesis_info.cc @@ -259,6 +259,7 @@ void GenesisInfo::set_dland(double d) { bool GenesisInfo::set(const TrackInfo &ti, const GenesisEventInfo &event_info) { + // Initialize clear(); @@ -298,14 +299,32 @@ int GenesisInfo::genesis_fhr() const { //////////////////////////////////////////////////////////////////////// -bool GenesisInfo::is_match(const TrackPoint &p, - const double rad) const { +const TrackPoint * GenesisInfo::genesis() const { + return(is_bad_data(GenesisIndex) ? 0 : &(Point[GenesisIndex])); +} + +//////////////////////////////////////////////////////////////////////// + +bool GenesisInfo::is_match(const TrackPoint &p, const double rad, + const int beg, const int end) const { // Check for matching in time and space - return(GenesisTime == p.valid() && + return(p.valid() >= (GenesisTime + beg) && + p.valid() <= (GenesisTime + end) && gc_dist(Lat, Lon, p.lat(), p.lon()) <= rad); } +//////////////////////////////////////////////////////////////////////// + +bool GenesisInfo::is_match(const GenesisInfo &gi, const double rad, + const int beg, const int end) const { + + // Input genesis point + const TrackPoint *p = gi.genesis(); + + return(p ? is_match(*p, rad, beg, end) : false); +} + //////////////////////////////////////////////////////////////////////// // // Code for class GenesisInfoArray diff --git a/met/src/libcode/vx_tc_util/genesis_info.h b/met/src/libcode/vx_tc_util/genesis_info.h index bc4a511020..9ef8afb742 100644 --- a/met/src/libcode/vx_tc_util/genesis_info.h +++ b/met/src/libcode/vx_tc_util/genesis_info.h @@ -55,11 +55,8 @@ class GenesisInfo : public TrackInfo { bool IsSet; - // TrackInfo for this Genesis event - TrackInfo Track; - int GenesisIndex; - // Genesis Information + int GenesisIndex; unixtime GenesisTime; int GenesisLead; double Lat; @@ -93,6 +90,8 @@ class GenesisInfo : public TrackInfo { // get stuff // + const TrackPoint *genesis() const; + double lat() const; double lon() const; double dland() const; @@ -105,7 +104,11 @@ class GenesisInfo : public TrackInfo { // bool is_match(const TrackPoint &, - const double) const; + const double, + const int, const int) const; + bool is_match(const GenesisInfo &, + const double, + const int, const int) const; }; //////////////////////////////////////////////////////////////////////// @@ -161,7 +164,6 @@ class GenesisInfoArray { const GenesisInfo & operator[](int) const; int n() const; int n_technique() const; - }; //////////////////////////////////////////////////////////////////////// diff --git a/met/src/libcode/vx_tc_util/track_info.cc b/met/src/libcode/vx_tc_util/track_info.cc index 312d9aa620..215f0c3b38 100644 --- a/met/src/libcode/vx_tc_util/track_info.cc +++ b/met/src/libcode/vx_tc_util/track_info.cc @@ -299,7 +299,7 @@ void TrackInfo::initialize(const ATCFTrackLine &l, bool check_anly) { MinValidTime = MaxValidTime = l.valid(); // Create the storm id - set_storm_id(); + set_storm_id(l.storm_id().c_str()); return; } diff --git a/met/src/tools/tc_utils/tc_gen/tc_gen.cc b/met/src/tools/tc_utils/tc_gen/tc_gen.cc index f3b614960c..743db7fd44 100644 --- a/met/src/tools/tc_utils/tc_gen/tc_gen.cc +++ b/met/src/tools/tc_utils/tc_gen/tc_gen.cc @@ -19,6 +19,7 @@ // 002 12/15/20 Halley Gotway Matching logic for MET #1448 // 003 12/31/20 Halley Gotway Add NetCDF output for MET #1430 // 004 01/14/21 Halley Gotway Add GENMPR output for MET #1597 +// 005 04/02/21 Halley Gotway Refinements for MET #1714 // //////////////////////////////////////////////////////////////////////// @@ -82,7 +83,7 @@ static void do_genesis_ctc (const TCGenVxOpt &, static int find_genesis_match (const GenesisInfo &, const GenesisInfoArray &, const TrackInfoArray &, - double); + bool, double, int, int); static void setup_txt_files (int, int); static void setup_table (AsciiTable &); @@ -370,14 +371,17 @@ void get_genesis_pairs(const TCGenVxOpt &vx_opt, conf_info.InitFreqHr*sec_per_hour, vx_opt.InitBeg, vx_opt.InitEnd, vx_opt.InitInc, vx_opt.InitExc); - } + } // end for i bga // Loop over the model genesis events looking for pairs. for(i=0; igenesis_time() - fgi->init(); offset_cs << cs_erase << "with an init vs genesis time offset of " << diff.OpsDSec/sec_per_hour << " hours.\n"; - if(diff.OpsDSec <= vx_opt.OpsHitDSec) { + // Ops Method: + // HIT if forecast init time is close enough to + // the BEST genesis time. + if(diff.OpsDSec >= vx_opt.OpsHitBeg && + diff.OpsDSec <= vx_opt.OpsHitEnd) { mlog << Debug(4) << case_cs << " is an ops method HIT " << offset_cs; @@ -591,10 +595,9 @@ void do_genesis_ctc(const TCGenVxOpt &vx_opt, int find_genesis_match(const GenesisInfo &fcst_gi, const GenesisInfoArray &bga, const TrackInfoArray &ota, - const double rad) { - int i, j; - int i_best = bad_data_int; - int i_oper = bad_data_int; + bool point2track, double rad, + int beg, int end) { + int i, j, i_best, i_oper; ConcatString case_cs; case_cs << fcst_gi.technique() << " " @@ -605,20 +608,36 @@ int find_genesis_match(const GenesisInfo &fcst_gi, << " forecast genesis at (" << fcst_gi.lat() << ", " << fcst_gi.lon() << ")"; - // Search the BEST track points for a match + // Search for a BEST track genesis match for(i=0, i_best=bad_data_int; i conf_info.FcstSecEnd) { - mlog << Debug(6) << "Skipping genesis event for forecast hour " - << fcst_gi.genesis_fhr() << ".\n"; + mlog << Debug(6) + << "Skipping forecast genesis event for forecast hour " + << fcst_gi.genesis_fhr() << " not between " + << conf_info.FcstSecBeg/sec_per_hour << " and " + << conf_info.FcstSecEnd/sec_per_hour << ".\n"; continue; } // Check the forecast track minimum duration if(fcst_gi.duration() < conf_info.MinDur*sec_per_hour) { - mlog << Debug(6) << "Skipping genesis event for track duration of " - << fcst_gi.duration()/sec_per_hour << ".\n"; + mlog << Debug(6) + << "Skipping forecast genesis event for track duration of " + << fcst_gi.duration()/sec_per_hour << " < " + << conf_info.MinDur << ".\n"; continue; } @@ -899,6 +925,15 @@ void process_best_tracks(const StringArray &files, continue; } + // Skip invest tracks with a large cyclone number + if(atof(best_ta[i].cyclone().c_str()) > max_best_cyclone_number) { + mlog << Debug(6) + << "Skipping Best track genesis event for cyclone number " + << best_ta[i].cyclone() << " > " << max_best_cyclone_number + << ".\n"; + continue; + } + // Check for duplicates if(best_ga.has_storm(best_gi, i_bga)) { diff --git a/met/src/tools/tc_utils/tc_gen/tc_gen.h b/met/src/tools/tc_utils/tc_gen/tc_gen.h index 3d6ff17e9c..10118842c6 100644 --- a/met/src/tools/tc_utils/tc_gen/tc_gen.h +++ b/met/src/tools/tc_utils/tc_gen/tc_gen.h @@ -77,6 +77,10 @@ const ConcatString genesis_name ("GENESIS"); const ConcatString genesis_dev_name("GENESIS_DEV"); const ConcatString genesis_ops_name("GENESIS_OPS"); +// Maximum Best track cyclone number to be processed +// Cyclone numbers > 50 are for testing or invests +static const int max_best_cyclone_number = 50; + //////////////////////////////////////////////////////////////////////// // // Variables for Command Line Arguments diff --git a/met/src/tools/tc_utils/tc_gen/tc_gen_conf_info.cc b/met/src/tools/tc_utils/tc_gen/tc_gen_conf_info.cc index cdab8c11da..e2046c0c13 100644 --- a/met/src/tools/tc_utils/tc_gen/tc_gen_conf_info.cc +++ b/met/src/tools/tc_utils/tc_gen/tc_gen_conf_info.cc @@ -156,10 +156,12 @@ void TCGenVxOpt::clear() { VxBasinMask.clear(); VxAreaMask.clear(); DLandThresh.clear(); + GenesisMatchPointTrack = false; GenesisMatchRadius = bad_data_double; + GenesisMatchBeg = GenesisMatchEnd = bad_data_int; DevHitRadius = bad_data_double; DevHitBeg = DevHitEnd = bad_data_int; - OpsHitDSec = bad_data_int; + OpsHitBeg = OpsHitEnd = bad_data_int; DiscardFlag = false; DevFlag = OpsFlag = false; CIAlpha = bad_data_double; @@ -242,24 +244,34 @@ void TCGenVxOpt::process_config(Dictionary &dict) { // Conf: dland_thresh DLandThresh = dict.lookup_thresh(conf_key_dland_thresh); + // Conf: genesis_match_point_to_track + GenesisMatchPointTrack = + dict.lookup_bool(conf_key_genesis_match_point_to_track); + // Conf: genesis_match_radius GenesisMatchRadius = dict.lookup_double(conf_key_genesis_match_radius); + // Conf: genesis_match_window + dict2 = dict.lookup_dictionary(conf_key_genesis_match_window); + parse_conf_range_int(dict2, beg, end); + GenesisMatchBeg = beg*sec_per_hour; + GenesisMatchEnd = end*sec_per_hour; + // Conf: dev_hit_radius - DevHitRadius = - dict.lookup_double(conf_key_dev_hit_radius); + DevHitRadius = dict.lookup_double(conf_key_dev_hit_radius); - // Conf: genesis_hit_window + // Conf: dev_hit_window dict2 = dict.lookup_dictionary(conf_key_dev_hit_window); parse_conf_range_int(dict2, beg, end); DevHitBeg = beg*sec_per_hour; DevHitEnd = end*sec_per_hour; - // Conf: ops_hit_tdiff - OpsHitDSec = nint( - dict.lookup_double(conf_key_ops_hit_tdiff) * - sec_per_hour); + // Conf: ops_hit_window + dict2 = dict.lookup_dictionary(conf_key_ops_hit_window); + parse_conf_range_int(dict2, beg, end); + OpsHitBeg = beg*sec_per_hour; + OpsHitEnd = end*sec_per_hour; // Conf: discard_init_post_genesis_flag DiscardFlag = diff --git a/met/src/tools/tc_utils/tc_gen/tc_gen_conf_info.h b/met/src/tools/tc_utils/tc_gen/tc_gen_conf_info.h index de7d14c1d9..0769f64f8f 100644 --- a/met/src/tools/tc_utils/tc_gen/tc_gen_conf_info.h +++ b/met/src/tools/tc_utils/tc_gen/tc_gen_conf_info.h @@ -131,16 +131,18 @@ class TCGenVxOpt { // Distance to land threshold SingleThresh DLandThresh; + // Matching logic + bool GenesisMatchPointTrack; + // Temporal and spatial matching criteria double GenesisMatchRadius; + int GenesisMatchBeg, GenesisMatchEnd; + + // Temporal and spatial scoring options double DevHitRadius; int DevHitBeg, DevHitEnd; - int OpsHitDSec; - - // Scoring methods - bool DiscardFlag; - bool DevFlag; - bool OpsFlag; + int OpsHitBeg, OpsHitEnd; + bool DiscardFlag, DevFlag, OpsFlag; // Output file options double CIAlpha; diff --git a/test/config/TCGenConfig_2016 b/test/config/TCGenConfig_2016 index 6d46d9f528..28ec263e85 100644 --- a/test/config/TCGenConfig_2016 +++ b/test/config/TCGenConfig_2016 @@ -90,6 +90,17 @@ filter = [ nc_pairs_flag = TRUE; output_flag = { genmpr = BOTH; } }, + { + desc = "AL_MATCH24HR"; + basin_mask = "AL"; + genesis_match_window = { beg = 0; end = 24; }; + }, + { + desc = "AL_POINT2POINT"; + basin_mask = "AL"; + genesis_match_window = { beg = 0; end = 24; }; + genesis_match_point_to_track = FALSE; + }, { desc = "AL_DLAND_300NM"; basin_mask = "AL"; @@ -119,7 +130,7 @@ filter = [ { desc = "ALL_MATCH_600KM_OPS60HR"; genesis_match_radius = 600; - ops_hit_tdiff = 60; + ops_hit_window = { beg = -60; end = 60; }; dev_method_flag = FALSE; ops_method_flag = TRUE; } @@ -193,18 +204,34 @@ dland_thresh = NA; // //////////////////////////////////////////////////////////////////////////////// +// +// Genesis matching logic. Compare the forecast genesis point to all points in +// the Best track (TRUE) or the single Best track genesis point (FALSE). +// +genesis_match_point_to_track = TRUE; + // // Radius in km to search for a matching genesis event // genesis_match_radius = 500; +// +// Time window in hours, relative to the model genesis time, to search for a +// matching Best track point +// +genesis_match_window = { + beg = 0; + end = 0; +} + // // Radius in km for a development scoring method hit // dev_hit_radius = 500; // -// Time window in hours for a development scoring method hit +// Time window in hours, relative to the model genesis time, for a development +// scoring method hit // dev_hit_window = { beg = -24; @@ -212,10 +239,13 @@ dev_hit_window = { } // -// Maximum Best track genesis minus model initialization time difference for an -// operational scoring method hit +// Time window in hours for the Best track genesis minus model initialization +// time difference for an operational scoring method hit // -ops_hit_tdiff = 48; +ops_hit_window = { + beg = 0; + end = 48; +} // // Discard genesis forecasts for initializations at or after the matching