Skip to content

Commit

Permalink
Feature 2476 tc pairs diag (#2694)
Browse files Browse the repository at this point in the history
Co-authored-by: John Halley Gotway <johnhg@ucar.edu>
Co-authored-by: Seth Linden <linden@seneca.rap.ucar.edu>
  • Loading branch information
3 people authored Oct 4, 2023
1 parent 9594696 commit a0200a4
Show file tree
Hide file tree
Showing 10 changed files with 312 additions and 21 deletions.
2 changes: 1 addition & 1 deletion data/config/TCPairsConfig_default
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ diag_info_map = [
diag_source = "CIRA_DIAG_RT";
track_source = "GFS";
field_source = "GFS_0p50";
match_to_track = [ "GFS" ];
match_to_track = [];
diag_name = [];
},
{
Expand Down
8 changes: 6 additions & 2 deletions docs/Users_Guide/tc-pairs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ ____________________
diag_source = "CIRA_DIAG_RT";
track_source = "GFS";
field_source = "GFS_0p50";
match_to_track = [ "GFS" ];
match_to_track = [];
diag_name = [];
},
{
Expand All @@ -307,7 +307,11 @@ A TCMPR line is written to the output for each track point. If diagnostics data

The **diag_info_map** entries define how the diagnostics read with the **-diag** command line option should be used. Each array element is a dictionary consisting of entries for **diag_source**, **track_source**, **field_source**, **match_to_track**, and **diag_name**.

The **diag_source** entry is one of the supported diagnostics data sources. The **track_source** entry is a string defining the ATCF ID of the track data used to define the locations at which diagnostics are computed. This string is written to the **TRACK_SOURCE** column of the TCDIAG output line. The **field_source** entry is a string describing the gridded model data from which the diagnostics are computed. This string is written to the **FIELD_SOURCE** column of the TCDIAG output line type. The **match_to_track** entry specifies a comma-separated list of strings defining the ATCF ID(s) of the tracks to which these diagnostic values should be matched. The **diag_name** entry specifies a comma-separated list of strings for the tropical cyclone diagnostics of interest. If a non-zero list of diagnostic names is specified, only those diagnostics appearing in the list are written to the TCDIAG output line type. If defined as an empty list (default), all diagnostics found in the input are written to the TCDIAG output lines.
- The **diag_source** entry is one of the supported diagnostics data sources.
- The **track_source** entry is a string defining the ATCF ID of the track data used to define the locations at which diagnostics are computed. This string is written to the **TRACK_SOURCE** column of the TCDIAG output line.
- The **field_source** entry is a string describing the gridded model data from which the diagnostics are computed. This string is written to the **FIELD_SOURCE** column of the TCDIAG output line type.
- The **match_to_track** entry specifies a comma-separated list of strings defining the ATCF ID(s) of the tracks to which these diagnostic values should be matched. For the SHIPS_DIAG_RT source, this is required since it is the only way to associate diagnostics with track ATCF IDs. For the CIRA_DIAG_RT source, this is optional. If a non-zero list is provided, the diagnostics will be matched to tracks for the specified ATCF ID(s). If defined as an empty list (default), the ATCF ID will be extracted from each CIRA diagnostic file and used to match the diagnostics to track data.
- The **diag_name** entry specifies a comma-separated list of strings for the tropical cyclone diagnostics of interest. If a non-zero list of diagnostic names is specified, only those diagnostics appearing in the list are written to the TCDIAG output line type. If defined as an empty list (default), all diagnostics found in the input are written to the TCDIAG output lines.

____________________

Expand Down
2 changes: 1 addition & 1 deletion internal/test_unit/config/TCPairsConfig_DIAGNOSTICS
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ diag_info_map = [
diag_source = "CIRA_DIAG_RT";
track_source = "GFS";
field_source = "GFS_0p50";
match_to_track = [ "GFS" ];
match_to_track = [];
diag_name = [ ${CIRA_RT_DIAG_NAME} ];
},
{
Expand Down
175 changes: 175 additions & 0 deletions internal/test_unit/config/TCPairsConfig_DIAGNOSTICS_CONSENSUS
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
////////////////////////////////////////////////////////////////////////////////
//
// TC-Pairs configuration file.
//
// For additional information, please see the MET User's Guide.
//
////////////////////////////////////////////////////////////////////////////////

//
// ATCF file format reference:
// http://www.nrlmry.navy.mil/atcf_web/docs/database/new/abrdeck.html
//

//
// Models
//
model = [ "GFSI", "EMXI" ];

//
// Description
//
desc = "NA";

//
// Storm identifiers
//
storm_id = [ ${STORM_ID} ];

//
// Basins
//
basin = [];

//
// Cyclone numbers
//
cyclone = [];

//
// Storm names
//
storm_name = [];

//
// Model initialization time windows to include or exclude
//
init_beg = "";
init_end = "";
init_inc = [ ${INIT_INC} ];
init_exc = [];

//
// Valid model time windows to include or exclude
//
valid_beg = "";
valid_end = "";
valid_inc = [];
valid_exc = [];

//
// Valid times for which output should be written
//
write_valid = [];

//
// Model initialization hours
//
init_hour = [];

//
// Required lead time in hours
//
lead_req = [];

//
// lat/lon polylines defining masking regions
//
init_mask = "";
valid_mask = "";

//
// Specify if the code should check for duplicate ATCF lines
//
check_dup = TRUE;

//
// Specify special processing to be performed for interpolated models.
// Set to NONE, FILL, or REPLACE.
//
interp12 = NONE;

//
// Specify how consensus forecasts should be defined
// See NHC Consensus Definitions in Table 2:
// https://www.nhc.noaa.gov/modelsummary.shtml
//
consensus = [
{
name = "GFEX_CONS";
members = [ "GFSI", "EMXI" ];
required = [];
min_req = 2;
write_members = TRUE;
}
];

//
// Forecast lag times
//
lag_time = [];

//
// CLIPER/SHIFOR baseline forecasts to be derived from the BEST
// and operational (CARQ) tracks.
//
best_baseline = [];
oper_baseline = [];

//
// Specify if only those track points common to both the ADECK and BDECK
// tracks be written out.
//
match_points = TRUE;

//
// Specify the NetCDF output of the gen_dland tool containing a gridded
// representation of the minimum distance to land.
//
dland_file = "${MET_TEST_OUTPUT}/tc_dland/tc_dland_half_deg.nc";

//
// Specify watch/warning information:
// - Input watch/warning filename
// - Watch/warning time offset in seconds
//
watch_warn = {
file_name = "MET_BASE/tc_data/wwpts_us.txt";
time_offset = -14400;
}

//
// Diagnostics to be extracted
//
diag_info_map = [
{
diag_source = "CIRA_DIAG_RT";
track_source = "TRACK_MODEL";
field_source = "0p50RES";
match_to_track = [ ];
diag_name = [ ${CIRA_RT_DIAG_NAME} ];
}
];

//
// Unit conversions to be applied based on diagnostic names and units
// Commented out to use settings from the default config file
//
// diag_convert_map = [];

//
// Modify basin names to make them consistent across ATCF input files.
//
basin_map = [
{ key = "SI"; val = "SH"; },
{ key = "SP"; val = "SH"; },
{ key = "AU"; val = "SH"; },
{ key = "AB"; val = "IO"; },
{ key = "BB"; val = "IO"; }
];

//
// Indicate a version number for the contents of this configuration file.
// The value should generally not be modified.
//
version = "V12.0.0";
23 changes: 23 additions & 0 deletions internal/test_unit/xml/unit_tc_pairs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,27 @@
</output>
</test>

<test name="tc_pairs_DIAGNOSTICS_CONSENSUS">
<exec>&MET_BIN;/tc_pairs</exec>
<env>
<pair><name>STORM_ID</name> <value>"AL092022"</value></pair>
<pair><name>INIT_INC</name> <value>"20220926_06", "20220926_18"</value></pair>
<pair><name>CIRA_RT_DIAG_NAME</name> <value>"TPW", "LAND", "SHR_MAG", "STM_SPD"</value></pair>
</env>
<param> \
-adeck &DATA_DIR;/adeck/aal092022.dat \
-bdeck &DATA_DIR;/bdeck/bal092022.dat \
-diag CIRA_DIAG_RT &DATA_DIR;/diag/cira_diag_rt/2022/GFSI/sal092022_avni_doper_20220926*_diag.dat \
-diag CIRA_DIAG_RT &DATA_DIR;/diag/cira_diag_rt/2022/EMXI/sal092022_emxi_doper_20220926*_diag.dat \
-config &CONFIG_DIR;/TCPairsConfig_DIAGNOSTICS_CONSENSUS \
-out &OUTPUT_DIR;/tc_pairs/al092022_20220926_DIAGNOSTICS_CONSENSUS \
-log &OUTPUT_DIR;/tc_pairs/tc_pairs_DIAGNOSTICS_CONSENSUS.log \
-v 4
</param>
<output>
<stat>&OUTPUT_DIR;/tc_pairs/al092022_20220926_DIAGNOSTICS_CONSENSUS.tcst</stat>
</output>
</test>


</met_test>
74 changes: 67 additions & 7 deletions src/libcode/vx_tc_util/track_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,6 @@ bool TrackInfo::add_diag_data(DiagFile &diag_file, const StringArray &req_diag_n
// Store the diagnostic name
DiagName.add(diag_file.diag_name()[i_name]);
NumArray diag_val = diag_file.diag_val(diag_file.diag_name()[i_name]);

// Add diagnostic values to the TrackPoints
for(i_time=0; i_time<diag_file.n_time(); i_time++) {

Expand Down Expand Up @@ -618,6 +617,16 @@ void TrackInfo::add_diag_value(int i_pnt, double val) {

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

void TrackInfo::add_uniq_diag_name(const string diag_name) {

// Store the diagnostic name
DiagName.add_uniq(diag_name);

return;
}

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

bool TrackInfo::has(const ATCFTrackLine &l) const {
return(TrackLines.has(l.get_line()));
}
Expand Down Expand Up @@ -965,11 +974,10 @@ int TrackInfoArray::add_diag_data(DiagFile &diag_file, const StringArray &diag_n
TrackInfo consensus(const TrackInfoArray &tracks,
const ConcatString &model, int req,
const StringArray &req_list) {
int i, j, i_pnt;
int i, j, k, i_pnt;
bool skip;
TrackInfo tavg;
NumArray lead_list;

// Variables for average TrackPoint
int pcnt;
TrackPoint pavg, psum;
Expand All @@ -993,7 +1001,6 @@ TrackInfo consensus(const TrackInfoArray &tracks,
tavg.set_technique(model.c_str());
tavg.set_init(tracks[0].init());
tavg.set_storm_id();

// Loop through the tracks and build a list of lead times
for(i=0; i<tracks.n(); i++) {

Expand All @@ -1016,6 +1023,12 @@ TrackInfo consensus(const TrackInfoArray &tracks,
<< tracks[i].technique_number() << ").\n\n";
}

// Get unique diag names
// Store diag_names in tavg object
for(j=0; j<tracks[i].diag_name().n(); j++) {
tavg.add_uniq_diag_name(tracks[i].diag_name()[j]);
}

// Loop through the points for the lead times
for(j=0; j<tracks[i].n_points(); j++) {

Expand Down Expand Up @@ -1056,11 +1069,17 @@ TrackInfo consensus(const TrackInfoArray &tracks,
}
continue;
}

// Increment the TrackPoint count and sums
// Remove diagnostic values from the TrackPoint object (psum) for the consensus values
// Consensus diag values computed below this
pcnt++;
if(pcnt == 1) psum = tracks.Track[j][i_pnt];
else psum += tracks.Track[j][i_pnt];
if(pcnt == 1) {
psum = tracks.Track[j][i_pnt];
psum.clear_diag_value();
}
else {
psum += tracks.Track[j][i_pnt];
}

// Store the track point latitude, longitude v_max and mslp values
plon.add(tracks.Track[j][i_pnt].lon());
Expand Down Expand Up @@ -1138,6 +1157,47 @@ TrackInfo consensus(const TrackInfoArray &tracks,
// Compute consensus CycloneLevel
if(!is_bad_data(pavg.v_max())) pavg.set_level(wind_speed_to_cyclonelevel(pavg.v_max()));

// Loop over the diag name and the input track points and get consensus diag value
// (mean value across all members that have the diag value)
for (j=0; j<tavg.diag_name().n(); j++){
mlog << Debug(4) << "Computing consensus \"" << tavg.diag_name()[j] << "\" diagnostic value.\n";

// Store diag_vals for one diag_name across all lead-times (track points)
NumArray diag_vals;
double cons_diag_val;

// Initializ diag_vals array for this diag name
diag_vals.clear();

// Loop through the tracks to get average diagnostic values
for(k=0; k<tracks.n(); k++) {

// Get the index of the TrackPoint for this lead time
i_pnt = tracks.Track[k].lead_index(nint(lead_list[i]));

// Check for missing TrackPoint in a required member
if(i_pnt < 0) {
if(req_list.has(tracks.Track[k].technique())) {
skip = true;
break;
}
continue;
}

// Add non-missing diag values to local NumArray
if(!is_bad_data( tracks.Track[k][i_pnt].get_diag_val(tavg.diag_name(), tavg.diag_name()[j]) )) {
diag_vals.add(tracks.Track[k][i_pnt].get_diag_val(tavg.diag_name(), tavg.diag_name()[j]));
}

} // end loop over ensemble of tracks (for given lead-time: i_pnt)

// Compute cons_diag_val (the mean value)
// add it to the pavg DiagVal NumArray
cons_diag_val = diag_vals.mean();
pavg.add_diag_value(cons_diag_val);

} // end loop over diag names

// Add the current track point
tavg.add(pavg);
}
Expand Down
3 changes: 2 additions & 1 deletion src/libcode/vx_tc_util/track_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ class TrackInfo {
void add_watch_warn(const ConcatString &, WatchWarnType, unixtime);
bool add_diag_data(DiagFile &, const StringArray &);
void add_diag_value(int, double);

void add_uniq_diag_name(const std::string);

bool has(const ATCFTrackLine &) const;

bool is_match(const ATCFTrackLine &);
Expand Down
Loading

0 comments on commit a0200a4

Please sign in to comment.