Skip to content

Commit

Permalink
Per #2279, add the MaskSID struct to store information about station …
Browse files Browse the repository at this point in the history
…id names and corresponding weights.
  • Loading branch information
JohnHalleyGotway committed Oct 9, 2024
1 parent 9e4f00f commit 4bbe2ae
Show file tree
Hide file tree
Showing 15 changed files with 206 additions and 94 deletions.
27 changes: 27 additions & 0 deletions src/basic/vx_config/config_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,33 @@ struct MaskLatLon {

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

//
// Struct to store masking station id information
//

struct MaskSID {

// Mask name
ConcatString name;

// Vector of SID name and corresponding weights
std::vector<std::pair<std::string, double>> sid_list;

void clear();
bool operator==(const MaskSID &) const;
MaskSID &operator=(const MaskSID &a) noexcept;

int n() const;

// Formatted as: station_name(numeric_weight)
void add(const std::string &);
void add_css(const std::string &);
bool has(const std::string &);
void sort();
};

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

//
// Enumeration for duplicate_flag configuration parameter
//
Expand Down
155 changes: 125 additions & 30 deletions src/basic/vx_config/config_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -597,19 +597,115 @@ StringArray parse_conf_message_type(Dictionary *dict, bool error_out) {
return sa;
}

///////////////////////////////////////////////////////////////////////////////
//
// Code for MaskSID struct
//
///////////////////////////////////////////////////////////////////////////////

void MaskSID::clear() {
name.clear();
sid_list.clear();
}

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

bool MaskSID::operator==(const MaskSID &v) const {
bool match = true;

if(!(name == v.name ) ||
!(sid_list == v.sid_list)) {
match = false;
}

return match;
}

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

MaskSID &MaskSID::operator=(const MaskSID &a) noexcept {
if(this != &a) {
name = a.name;
sid_list = a.sid_list;
}
return *this;
}

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

int MaskSID::n() const {
return sid_list.size();
}

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

void MaskSID::add(const string &text) {
size_t pos = 0;
ConcatString sid;
double wgt = 1.0;

// Parse station id and optional weight
if((pos = text.find("(")) != string::npos) {
sid = text.substr(0, pos);
wgt = stod(text.substr(pos));
}
// No weight specified
else {
sid = text;
}

// Store the pair
sid_list.push_back(pair<string,double>(sid,wgt));

return;
}

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

void MaskSID::add_css(const string &text) {
StringArray sa;
sa.add_css(text);
for(int i=0; i<sa.n(); i++) add(sa[i]);
return;
}

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

bool MaskSID::has(const string &s) {
bool match = false;

for(auto item : sid_list) {
if(s == item.first) {
match = true;
break;
}
}

return match;
}

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

void MaskSID::sort() {

std::sort(sid_list.begin(), sid_list.end());

return;
}

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

StringArray parse_conf_sid_list(Dictionary *dict, const char *conf_key) {
StringArray sa, cur, sid_sa;
ConcatString mask_name;
MaskSID cur;
StringArray sid_sa;
const char *method_name = "parse_conf_sid_list() -> ";

sa = parse_conf_string_array(dict, conf_key, method_name);
StringArray sa(parse_conf_string_array(dict, conf_key, method_name));

// Parse station ID's to exclude from each entry
// Append to the list of station ID's
for(int i=0; i<sa.n(); i++) {
parse_sid_mask(string(sa[i]), cur, mask_name);
sid_sa.add(cur);
cur = parse_sid_mask(string(sa[i]));
for(auto item : cur.sid_list) sid_sa.add(item.first);
}

mlog << Debug(4) << method_name
Expand All @@ -631,71 +727,67 @@ StringArray parse_conf_sid_list(Dictionary *dict, const char *conf_key) {
//
///////////////////////////////////////////////////////////////////////////////

void parse_sid_mask(const ConcatString &mask_sid_str,
StringArray &mask_sid, ConcatString &mask_name) {
ifstream in;
ConcatString tmp_file;
MaskSID parse_sid_mask(const ConcatString &mask_sid_str) {
MaskSID mask_sid;
std::string sid_str;

// Initialize
mask_sid.clear();
mask_name = na_str;
const char *method_name = "parse_sid_mask() -> ";

// Check for an empty length string
if(mask_sid_str.empty()) return;
if(mask_sid_str.empty()) return mask_sid;

// Replace any instances of MET_BASE with it's expanded value
tmp_file = replace_path(mask_sid_str.c_str());
ConcatString tmp_file(replace_path(mask_sid_str.c_str()));

// Process file name
if(file_exists(tmp_file.c_str())) {

mlog << Debug(4) << "parse_sid_mask() -> "
mlog << Debug(4) << method_name
<< "parsing station ID masking file \"" << tmp_file << "\"\n";

// Open the mask station id file specified
ifstream in;
in.open(tmp_file.c_str());

if(!in) {
mlog << Error << "\nparse_sid_mask() -> "
mlog << Error << "\n" << method_name
<< "Can't open the station ID masking file \""
<< tmp_file << "\".\n\n";
exit(1);
}

// Store the first entry as the name of the mask
in >> sid_str;
mask_name = sid_str;
mask_sid.name = sid_str;

// Store the rest of the entries as masking station ID's
while(in >> sid_str) mask_sid.add(sid_str.c_str());

// Close the input file
in.close();

mlog << Debug(4) << "parse_sid_mask() -> "
mlog << Debug(4) << method_name
<< "parsed " << mask_sid.n() << " station ID's for the \""
<< mask_name << "\" mask from file \"" << tmp_file << "\"\n";
<< mask_sid.name << "\" mask from file \"" << tmp_file << "\"\n";
}
// Process list of strings
else {

// Print a warning if the string contains a dot which suggests
// the user was trying to specify a file name.
if(check_reg_exp("[.]", mask_sid_str.c_str())) {
mlog << Warning << "\nparse_sid_mask() -> "
mlog << Warning << "\n" << method_name
<< "unable to process \"" << mask_sid_str
<< "\" as a file name and processing it as a single "
<< "station ID mask instead.\n\n";
}

mlog << Debug(4) << "parse_sid_mask() -> "
mlog << Debug(4) << method_name
<< "storing single station ID mask \"" << mask_sid_str << "\"\n";

// Check for embedded whitespace or slashes
if(check_reg_exp(ws_reg_exp, mask_sid_str.c_str()) ||
check_reg_exp("[/]", mask_sid_str.c_str())) {
mlog << Error << "\nparse_sid_mask() -> "
mlog << Error << "\n" << method_name
<< "masking station ID string can't contain whitespace or "
<< "slashes \"" << mask_sid_str << "\".\n\n";
exit(1);
Expand All @@ -708,15 +800,16 @@ void parse_sid_mask(const ConcatString &mask_sid_str,
// One elements means no colon was specified
if(sa.n() == 1) {
mask_sid.add_css(sa[0]);
mask_name = ( mask_sid.n() == 1 ? mask_sid[0] : "MASK_SID" );
mask_sid.name = (mask_sid.sid_list.size() == 1 ?
mask_sid.sid_list[0].first : "MASK_SID");
}
// Two elements means one colon was specified
else if(sa.n() == 2) {
mask_name = sa[0];
mask_sid.add_css(sa[1]);
mask_sid.name = sa[0];
}
else {
mlog << Error << "\nparse_sid_mask() -> "
mlog << Error << "\n" << method_name
<< "masking station ID string may contain at most one colon to "
<< "specify the mask name \"" << mask_sid_str << "\".\n\n";
exit(1);
Expand All @@ -727,11 +820,14 @@ void parse_sid_mask(const ConcatString &mask_sid_str,
// Sort the mask_sid's
mask_sid.sort();

return;
return mask_sid;
}

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

//
// Code for MaskLatLon struct
//
///////////////////////////////////////////////////////////////////////////////

void MaskLatLon::clear() {
name.clear();
Expand Down Expand Up @@ -764,7 +860,6 @@ MaskLatLon &MaskLatLon::operator=(const MaskLatLon &a) noexcept {
return *this;
}


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

vector<MaskLatLon> parse_conf_llpnt_mask(Dictionary *dict) {
Expand Down
5 changes: 1 addition & 4 deletions src/basic/vx_config/config_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,7 @@ extern StringArray parse_conf_message_type(
extern StringArray parse_conf_sid_list(
Dictionary *dict,
const char *);
extern void parse_sid_mask(
const ConcatString &,
StringArray &,
ConcatString &);
extern MaskSID parse_sid_mask(const ConcatString &);
extern std::vector<MaskLatLon>
parse_conf_llpnt_mask(Dictionary *dict);
extern StringArray parse_conf_obs_qty_inc(Dictionary *dict);
Expand Down
9 changes: 4 additions & 5 deletions src/libcode/vx_analysis_util/stat_job.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1802,20 +1802,19 @@ void STATAnalysisJob::set_mask_sid(const char *c) {

if(!c) return;

ConcatString mask_name;

mask_sid_str = c;

// List the station ID mask
mlog << Debug(1)
<< "Station ID Mask: " << mask_sid_str << "\n";

parse_sid_mask(mask_sid_str, mask_sid, mask_name);
MaskSID ms = parse_sid_mask(mask_sid_str);
for(auto item : ms.sid_list) mask_sid.add(item.first);

// List the length of the station ID mask
mlog << Debug(2)
<< "Parsed Station ID Mask: " << mask_name
<< " containing " << mask_sid.n() << " points\n";
<< "Parsed Station ID Mask: " << ms.name
<< " containing " << mask_sid.n() << " stations\n";

return;
}
Expand Down
26 changes: 14 additions & 12 deletions src/libcode/vx_statistics/pair_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ void PairBase::clear() {
IsPointVx = false;

mask_name.clear();
mask_area_ptr = (MaskPlane *) nullptr; // Not allocated
mask_sid_ptr = (StringArray *) nullptr; // Not allocated
mask_llpnt_ptr = (MaskLatLon *) nullptr; // Not allocated
mask_area_ptr = (MaskPlane *) nullptr; // Not allocated
mask_sid_ptr = (MaskSID *) nullptr; // Not allocated
mask_llpnt_ptr = (MaskLatLon *) nullptr; // Not allocated

cdf_info_ptr = (const ClimoCDFInfo *) nullptr; // Not allocated

Expand Down Expand Up @@ -133,9 +133,9 @@ void PairBase::erase() {
IsPointVx = false;

mask_name.erase();
mask_area_ptr = (MaskPlane *) nullptr; // Not allocated
mask_sid_ptr = (StringArray *) nullptr; // Not allocated
mask_llpnt_ptr = (MaskLatLon *) nullptr; // Not allocated
mask_area_ptr = (MaskPlane *) nullptr; // Not allocated
mask_sid_ptr = (MaskSID *) nullptr; // Not allocated
mask_llpnt_ptr = (MaskLatLon *) nullptr; // Not allocated

cdf_info_ptr = (const ClimoCDFInfo *) nullptr; // Not allocated

Expand Down Expand Up @@ -205,9 +205,9 @@ void PairBase::extend(int n) {

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

void PairBase::set_mask_name(const char *c) {
void PairBase::set_mask_name(const string &s) {

mask_name = c;
mask_name = s;

return;
}
Expand All @@ -223,9 +223,9 @@ void PairBase::set_mask_area_ptr(MaskPlane *mp_ptr) {

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

void PairBase::set_mask_sid_ptr(StringArray *sid_ptr) {
void PairBase::set_mask_sid_ptr(MaskSID *ms_ptr) {

mask_sid_ptr = sid_ptr;
mask_sid_ptr = ms_ptr;

return;
}
Expand Down Expand Up @@ -1293,13 +1293,15 @@ void VxPairBase::set_mask_area(int i_mask, const char *name,
////////////////////////////////////////////////////////////////////////

void VxPairBase::set_mask_sid(int i_mask, const char *name,
StringArray *sid_ptr) {
MaskSID *ms_ptr) {

if(!ms_ptr) return;

for(int i_msg_typ=0; i_msg_typ<n_msg_typ; i_msg_typ++) {
for(int i_interp=0; i_interp<n_interp; i_interp++) {
int n = three_to_one(i_msg_typ, i_mask, i_interp);
pb_ptr[n]->set_mask_name(name);
pb_ptr[n]->set_mask_sid_ptr(sid_ptr);
pb_ptr[n]->set_mask_sid_ptr(ms_ptr);
}
}

Expand Down
Loading

0 comments on commit 4bbe2ae

Please sign in to comment.