Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature 1714 tc_gen #1750

Merged
merged 19 commits into from
Apr 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c18601b
Per #1714, add tc_gen genesis_match_window configuration option to de…
JohnHalleyGotway Mar 15, 2021
93d0312
Per #1714, clarify docs to state the genesis_match_window.end = 12 al…
JohnHalleyGotway Mar 15, 2021
7ae5b68
Merge branch 'develop' into feature_1714_tc_gen
JohnHalleyGotway Mar 15, 2021
b46c078
Merge branch 'develop' into feature_1714_tc_gen
JohnHalleyGotway Apr 2, 2021
3d90539
Per #1714, switch ops_hit_tdiff to ops_hit_window.
JohnHalleyGotway Apr 2, 2021
0022754
Per #1714, skip genesis events for tracks where the cyclone number is…
JohnHalleyGotway Apr 2, 2021
f784f8f
Per #1714, only discard cyclone numbers > 50 from the Best track, not…
JohnHalleyGotway Apr 2, 2021
1d42f40
Per #1716, add note to the tc_gen chapter about skipping Best tracks …
JohnHalleyGotway Apr 2, 2021
2581161
Merge branch 'develop' into feature_1714_tc_gen
JohnHalleyGotway Apr 5, 2021
5cfd9d0
Per #1714, adding genesis_match_point_to_track config file option for…
JohnHalleyGotway Apr 7, 2021
d91f9fd
Per #1714, the logic for checking the operational tracks is pretty si…
JohnHalleyGotway Apr 7, 2021
d0a774b
Per #1714, update the tc-gen user's guide chapter to describe the upd…
JohnHalleyGotway Apr 7, 2021
75a0161
Per #1714, fix the logic of the is_match() function.
JohnHalleyGotway Apr 7, 2021
f843da1
Per #1714, reconfigure the call to tc_gen to exercise the new genesis…
JohnHalleyGotway Apr 7, 2021
612db89
Per #1714, just fixing spacing in source code.
JohnHalleyGotway Apr 7, 2021
1569668
Committing 2 small changes not specifically related to #1714, but rel…
JohnHalleyGotway Apr 8, 2021
f9457f6
Merge remote-tracking branch 'origin/develop' into feature_1714_tc_gen
Apr 8, 2021
f35a777
Per #1714, fix an error in the logic of GenesisInfo::is_match(const G…
Apr 8, 2021
9f41da5
Per #1714, correcting logic for parsing the storm_id and warning_time…
JohnHalleyGotway Apr 9, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions met/data/config/TCGenConfig_default
Original file line number Diff line number Diff line change
Expand Up @@ -150,29 +150,48 @@ 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;
end = 24;
}

//
// 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
Expand Down
36 changes: 29 additions & 7 deletions met/docs/Users_Guide/tc-gen.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,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.

Expand Down Expand Up @@ -251,11 +251,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.

______________________

Expand All @@ -274,15 +293,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.

______________________

Expand Down
4 changes: 3 additions & 1 deletion met/src/basic/vx_config/config_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
16 changes: 11 additions & 5 deletions met/src/libcode/vx_tc_util/atcf_line_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -252,7 +255,8 @@ ConcatString ATCFLineBase::basin() const {
////////////////////////////////////////////////////////////////////////

ConcatString ATCFLineBase::cyclone_number() const {
return(get_item(CycloneNumberOffset)); }
return(get_item(CycloneNumberOffset));
}

////////////////////////////////////////////////////////////////////////

Expand Down Expand Up @@ -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();
Expand Down
25 changes: 22 additions & 3 deletions met/src/libcode/vx_tc_util/genesis_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ void GenesisInfo::set_dland(double d) {

bool GenesisInfo::set(const TrackInfo &ti,
const GenesisEventInfo &event_info) {

// Initialize
clear();

Expand Down Expand Up @@ -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
Expand Down
14 changes: 8 additions & 6 deletions met/src/libcode/vx_tc_util/genesis_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -93,6 +90,8 @@ class GenesisInfo : public TrackInfo {
// get stuff
//

const TrackPoint *genesis() const;

double lat() const;
double lon() const;
double dland() const;
Expand All @@ -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;
};

////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -161,7 +164,6 @@ class GenesisInfoArray {
const GenesisInfo & operator[](int) const;
int n() const;
int n_technique() const;

};

////////////////////////////////////////////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion met/src/libcode/vx_tc_util/track_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Loading