Skip to content

Commit

Permalink
Per #1810, update the ProbGenPCTInfo and TCGenVxOpt with changes to h…
Browse files Browse the repository at this point in the history
…andle the new GenShapeInfo objects. TCGenVxOpt applies the configuration options to filter them, and Nx2 contingency tables can be populated with them.
  • Loading branch information
JohnHalleyGotway committed Jan 7, 2022
1 parent d0b99fd commit 70e7d93
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 43 deletions.
125 changes: 95 additions & 30 deletions met/src/tools/tc_utils/tc_gen/tc_gen_conf_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ void TCGenVxOpt::clear() {
ValidBeg = ValidEnd = (unixtime) 0;
InitHour.clear();
Lead.clear();
VxMaskConf.clear();
VxMaskName.clear();
VxPolyMask.clear();
VxGridMask.clear();
Expand Down Expand Up @@ -228,8 +229,9 @@ void TCGenVxOpt::process_config(Dictionary &dict) {
}

// Conf: vx_mask
if(nonempty(dict.lookup_string(conf_key_vx_mask).c_str())) {
file_name = replace_path(dict.lookup_string(conf_key_vx_mask));
VxMaskConf = dict.lookup_string(conf_key_vx_mask);
if(VxMaskConf.nonempty()) {
file_name = replace_path(VxMaskConf);
mlog << Debug(2) << "Masking File: " << file_name << "\n";
parse_poly_mask(file_name, VxPolyMask, VxGridMask, VxAreaMask,
VxMaskName);
Expand Down Expand Up @@ -359,7 +361,8 @@ void TCGenVxOpt::process_basin_mask(const Grid &basin_grid,
if(!basin_abbr.has(VxBasinMask[i], j)) {
mlog << Error << "\nTCGenConfInfo::process_basin_mask() -> "
<< "\"" << VxBasinMask[i]
<< "\" is not a valid basin name!\n\n";
<< "\" is not a valid basin name ("
<< write_css(basin_abbr) << ")!\n\n";
exit(1);
}

Expand Down Expand Up @@ -570,6 +573,60 @@ bool TCGenVxOpt::is_keeper(const ProbGenInfo &gi) const {

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

bool TCGenVxOpt::is_keeper(const GenShapeInfo &gsi) const {
bool keep = true;

// ATCF ID and storm name do not apply

// Initialization time
if((InitBeg > 0 && InitBeg > gsi.issue_time()) ||
(InitEnd > 0 && InitEnd < gsi.issue_time()) ||
(InitInc.n() > 0 && !InitInc.has(gsi.issue_time())) ||
(InitExc.n() > 0 && InitExc.has(gsi.issue_time())))
keep = false;

// Initialization hours
if(InitHour.n() > 0 && !InitHour.has(gsi.issue_hour()))
keep = false;

// Lead and valid times:
// GenShapeInfo objects contain multiple lead/valid times.
// Do not filter by them here.

// If VxMaskConf set, filter spatially by the center of the shape
if(keep && VxMaskConf.nonempty()) {

// Poly masking: use center lat/lon
if(VxPolyMask.n_points() > 0 &&
!VxPolyMask.latlon_is_inside(gsi.center_lat(), gsi.center_lon()))
keep = false;

// Area masking: use center lat/lon
if(!VxAreaMask.is_empty()) {
double x, y;
VxGridMask.latlon_to_xy(gsi.center_lat(), -1.0*gsi.center_lon(), x, y);
if(x < 0 || x >= VxGridMask.nx() ||
y < 0 || y >= VxGridMask.ny()) {
keep = false;
}
else {
keep = VxAreaMask(nint(x), nint(y));
}
}
}
// Otherwise, if VxBasinMask set, filter by the GenShapeArea basin
else if(keep && VxBasinMask.n() > 0) {
keep = VxBasinMask.has(gsi.basin());
}

// Distance to land does not apply

// Return the keep status
return(keep);
}

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

STATOutputType TCGenVxOpt::output_map(STATLineType t) const {
return(OutputMap.at(t));
}
Expand Down Expand Up @@ -1249,8 +1306,9 @@ void ProbGenPCTInfo::clear() {
BestBeg = BestEnd = (unixtime) 0;

PCTMap.clear();
FcstGenMap.clear();
FcstIdxMap.clear();
ProbGenMap.clear();
GenShapeMap.clear();
ProbIdxMap.clear();
BestGenMap.clear();
BestEvtMap.clear();

Expand Down Expand Up @@ -1279,18 +1337,18 @@ void ProbGenPCTInfo::set_vx_opt(const TCGenVxOpt *vx_opt) {

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

void ProbGenPCTInfo::add_pgi(const ProbGenInfo &fgi, int index,
const GenesisInfo *bgi, bool is_event) {
void ProbGenPCTInfo::add_probgen(const ProbGenInfo &pgi, int index,
const GenesisInfo *bgi, bool is_event) {
unixtime ut;

// Store the model and variable names
if(Model.empty()) Model = fgi.technique();
if(Model.empty()) Model = pgi.technique();
if(VarName.empty()) VarName = prob_genesis_name;
if(VxMask.empty()) VxMask = (VxOpt->VxMaskName.empty() ?
na_str : VxOpt->VxMaskName);

// Track the range of forecast initalization times
ut = fgi.init();
ut = pgi.init();
if(InitBeg == 0 || InitBeg > ut) InitBeg = ut;
if(InitEnd == 0 || InitEnd < ut) InitEnd = ut;

Expand All @@ -1302,28 +1360,28 @@ void ProbGenPCTInfo::add_pgi(const ProbGenInfo &fgi, int index,
}

// Current lead time and probability value
int lead_hr = nint(fgi.prob_item(index));
double prob = fgi.prob(index) / 100.0;
int lead_hr = nint(pgi.prob_item(index));
double prob = pgi.prob(index) / 100.0;

// Add new map entries, if needed
if(!LeadTimes.has(lead_hr)) {

LeadTimes.add(lead_hr);
vector<const ProbGenInfo *> empty_fgi;
vector<const ProbGenInfo *> empty_pgi;
vector<int> empty_idx;
vector<const GenesisInfo *> empty_bgi;
vector<bool> empty_evt;

PCTMap [lead_hr] = DefaultPCT;
FcstGenMap[lead_hr] = empty_fgi;
FcstIdxMap[lead_hr] = empty_idx;
ProbGenMap[lead_hr] = empty_pgi;
ProbIdxMap[lead_hr] = empty_idx;
BestGenMap[lead_hr] = empty_bgi;
BestEvtMap[lead_hr] = empty_evt;
}

// Update map entries
FcstGenMap[lead_hr].push_back(&fgi);
FcstIdxMap[lead_hr].push_back(index);
ProbGenMap[lead_hr].push_back(&pgi);
ProbIdxMap[lead_hr].push_back(index);
BestGenMap[lead_hr].push_back(bgi);
BestEvtMap[lead_hr].push_back(is_event);

Expand All @@ -1336,18 +1394,19 @@ void ProbGenPCTInfo::add_pgi(const ProbGenInfo &fgi, int index,

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

void ProbGenPCTInfo::add_shape(const ConcatString &basin, unixtime issue_ut,
int lead_hr, double prob, const GenesisInfo *bgi,
bool is_event) {
void ProbGenPCTInfo::add_genshape(const GenShapeInfo &gsi, int index,
const GenesisInfo *bgi, bool is_event) {
unixtime ut;
int lead_hr;

// Store the model and variable names
if(Model.empty()) Model = "OPER";
if(VarName.empty()) VarName = genesis_shape_name;
if(VxMask.empty()) VxMask = basin;
if(VxMask.empty()) VxMask = (VxOpt->VxMaskName.empty() ?
na_str : VxOpt->VxMaskName);

// Track the range of forecast issue times
ut = issue_ut;
ut = gsi.issue_time();
if(InitBeg == 0 || InitBeg > ut) InitBeg = ut;
if(InitEnd == 0 || InitEnd < ut) InitEnd = ut;

Expand All @@ -1359,25 +1418,31 @@ void ProbGenPCTInfo::add_shape(const ConcatString &basin, unixtime issue_ut,
}

// Add new map entries, if needed
lead_hr = gsi.lead_sec(index)/sec_per_hour;
if(!LeadTimes.has(lead_hr)) {

LeadTimes.add(lead_hr);
vector<const GenesisInfo *> empty_bgi;
vector<bool> empty_evt;

PCTMap [lead_hr] = DefaultPCT;
BestGenMap[lead_hr] = empty_bgi;
BestEvtMap[lead_hr] = empty_evt;
vector<const GenShapeInfo *> empty_gsi;
vector<int> empty_idx;
vector<const GenesisInfo *> empty_bgi;
vector<bool> empty_evt;

PCTMap [lead_hr] = DefaultPCT;
GenShapeMap[lead_hr] = empty_gsi;
ProbIdxMap[lead_hr] = empty_idx;
BestGenMap[lead_hr] = empty_bgi;
BestEvtMap[lead_hr] = empty_evt;
}

// Update map entries
GenShapeMap[lead_hr].push_back(&gsi);
ProbIdxMap[lead_hr].push_back(index);
BestGenMap[lead_hr].push_back(bgi);
BestEvtMap[lead_hr].push_back(is_event);

// Increment counts
prob /= 100.0;
if(is_event) PCTMap[lead_hr].pct.inc_event (prob);
else PCTMap[lead_hr].pct.inc_nonevent(prob);
if(is_event) PCTMap[lead_hr].pct.inc_event (gsi.prob_val(index));
else PCTMap[lead_hr].pct.inc_nonevent(gsi.prob_val(index));

return;
}
Expand Down
26 changes: 13 additions & 13 deletions met/src/tools/tc_utils/tc_gen/tc_gen_conf_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ static const string ncout_str[n_ncout] = {
fops_fyoy_str, fops_fyon_str, bops_fyoy_str, bops_fnoy_str
};



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

struct TCGenNcOutInfo {
Expand Down Expand Up @@ -139,6 +137,7 @@ class TCGenVxOpt {
NumArray Lead;

// Spatial masking information
ConcatString VxMaskConf;
ConcatString VxMaskName;
MaskPoly VxPolyMask;
Grid VxGridMask;
Expand Down Expand Up @@ -178,8 +177,9 @@ class TCGenVxOpt {
const StringArray &);
void parse_nc_info(Dictionary &);

bool is_keeper(const GenesisInfo &) const;
bool is_keeper(const ProbGenInfo &) const;
bool is_keeper(const GenesisInfo &) const;
bool is_keeper(const ProbGenInfo &) const;
bool is_keeper(const GenShapeInfo &) const;

STATOutputType output_map(STATLineType) const;
};
Expand Down Expand Up @@ -353,23 +353,23 @@ class ProbGenPCTInfo {
map<int,PCTInfo> PCTMap;

// Map of lead times to vectors of pair info
map<int,vector<const ProbGenInfo *> > FcstGenMap;
map<int,vector<int> > FcstIdxMap;
map<int,vector<const GenesisInfo *> > BestGenMap;
map<int,vector<bool> > BestEvtMap;
map<int,vector<const ProbGenInfo *> > ProbGenMap;
map<int,vector<const GenShapeInfo *> > GenShapeMap;
map<int,vector<int> > ProbIdxMap;
map<int,vector<const GenesisInfo *> > BestGenMap;
map<int,vector<bool> > BestEvtMap;

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

void clear();

void set_vx_opt(const TCGenVxOpt *);

void add_pgi(const ProbGenInfo &, int,
const GenesisInfo *, bool);
void add_probgen(const ProbGenInfo &, int,
const GenesisInfo *, bool);

void add_shape(const ConcatString &, unixtime,
int, double, const GenesisInfo *,
bool);
void add_genshape(const GenShapeInfo &, int,
const GenesisInfo *, bool);

};

Expand Down

0 comments on commit 70e7d93

Please sign in to comment.