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 1695 ensemble single file (ensemble_stat) #2007

Merged
merged 57 commits into from
Jan 14, 2022
Merged
Show file tree
Hide file tree
Changes from 55 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
06b2bfb
added make.log to git ignore file since this file is typically create…
georgemccabe Dec 28, 2021
c64f718
per #1695, added logic to replace value set in environment variable M…
georgemccabe Dec 28, 2021
02d27c0
removed include because file includes itself
georgemccabe Dec 28, 2021
f399191
per #1695, added support for reading ens_member_ids and control_id fr…
georgemccabe Dec 28, 2021
d779e0f
renamed n_ens to n_ens_files for clarity
georgemccabe Dec 29, 2021
0f81e60
read ens_member_ids and control_id from config file, pass number of e…
georgemccabe Dec 29, 2021
44370e1
clean up comments in config file
georgemccabe Dec 29, 2021
ecc6f2f
per #1695, created a structs to hold field info, file info, nc_var_st…
georgemccabe Dec 29, 2021
a2e5ac8
remove unused variable
georgemccabe Dec 29, 2021
1951290
changed return value of string_value function from ConcatString* to C…
georgemccabe Dec 29, 2021
a7e2449
output log for each field info from the same file
georgemccabe Dec 29, 2021
868e78b
added support for getting control member from single file
georgemccabe Dec 29, 2021
8071aec
added GitHub Actions workflow to build a Docker image and push it to …
georgemccabe Dec 29, 2021
4d7cadd
added variable to trigger GHA
georgemccabe Dec 29, 2021
3c94663
renamed files to be more clear of their purpose, added groups for Git…
georgemccabe Dec 30, 2021
be60222
test triggering a workflow in another repository
georgemccabe Dec 30, 2021
500bd08
fixed typo in workflow id
georgemccabe Dec 30, 2021
fe74c21
fixed formatting of workflow file
georgemccabe Dec 30, 2021
201aeda
changed automation logic to only trigger on develop branch (for now) …
georgemccabe Dec 30, 2021
de1cedf
added current path to end of new path
georgemccabe Jan 4, 2022
1a033ae
renamed EnsInfo to EnsVarInfo
georgemccabe Jan 4, 2022
f2f5a46
warn if control_id is set in conf but -ctrl not set
georgemccabe Jan 4, 2022
ef81fb0
create class to hold ensemble var info, use class functions to obsfus…
georgemccabe Jan 4, 2022
c028a16
formatting
georgemccabe Jan 4, 2022
399f28f
error if control_id is found in ens_member_ids list
georgemccabe Jan 4, 2022
4bf7a56
removed logs used for debugging
georgemccabe Jan 4, 2022
afd74c6
unset MET_ENS_MEMBER_ID before reading config because otherwise value…
georgemccabe Jan 4, 2022
a500c77
created function to handle getting raw magic string
georgemccabe Jan 4, 2022
62d38a9
removed files from this branch to add in a different pull request
georgemccabe Jan 5, 2022
246b048
added documentation for new config variables in gen_ens_prod
georgemccabe Jan 5, 2022
bc084c9
clean up formatting in docs
georgemccabe Jan 5, 2022
a43fac0
added unit tests for new GenEnsProd logic
georgemccabe Jan 5, 2022
be623ff
Merge branch 'develop' into feature_1695_ensemble_single_file
georgemccabe Jan 6, 2022
4cc6492
per #1695, added unit tests for single file gen_ens_prod runs on NetC…
georgemccabe Jan 6, 2022
2f23dd0
renamed n_ens to n_ens_files for clarity
georgemccabe Jan 6, 2022
b99b35f
reference n_ens_files instead of ens_file_list.n()
georgemccabe Jan 6, 2022
1cc8d48
do not error out if control file is in list of ensemble files if proc…
georgemccabe Jan 6, 2022
5262be2
warn if control_id is set in config file but no control file is speci…
georgemccabe Jan 6, 2022
1767614
fixed typos
georgemccabe Jan 6, 2022
c0f1b8f
moved control_id variable to correct class
georgemccabe Jan 6, 2022
164e607
per #1695, added new config variables to default EnsembleStat config …
georgemccabe Jan 10, 2022
0b41e52
per #1695, moved EnsVarInfo class up to library with VarInfo so it ca…
georgemccabe Jan 10, 2022
600fbc3
per #1695, changed type of fcst_info from VarInfo to EnsVarInfo to st…
georgemccabe Jan 10, 2022
4acd9aa
per #1695, implement similar logic added to GenEnsProd to handle mult…
georgemccabe Jan 10, 2022
c6fc368
per #1695, added new ensemble_stat tests for single input file
georgemccabe Jan 10, 2022
988c5a4
per #1695, fixed logic for handling forecast data to properly include…
georgemccabe Jan 11, 2022
dbde68e
per #1695, added 4 unit tests for single input file to EnsembleStat: …
georgemccabe Jan 11, 2022
8864334
per #1695, added documentation to describe new config variables added…
georgemccabe Jan 11, 2022
a447732
changed comment to be more accurate
georgemccabe Jan 11, 2022
3c423df
changed error log for valid threshold check to be more clear what it …
georgemccabe Jan 11, 2022
0a66129
merged develop and resolved conflict
georgemccabe Jan 12, 2022
7be44b0
merged develop after pr #2001 and resolved conflicts
georgemccabe Jan 12, 2022
8b8bfd6
added new config variables to all EnsembleStat test config files for …
georgemccabe Jan 12, 2022
dde7c57
per #1695, fixed bug when using Python Embedding in EnsembleStat/GenE…
georgemccabe Jan 13, 2022
ca4303d
fixed bug printing field info before env var substitution when Python…
georgemccabe Jan 13, 2022
783a846
Update EnsembleStatConfig_single_file_grib
JohnHalleyGotway Jan 14, 2022
8883b58
Update EnsembleStatConfig_single_file_nc
JohnHalleyGotway Jan 14, 2022
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
7 changes: 7 additions & 0 deletions met/data/config/EnsembleStatConfig_default
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ ens = {
];
}

//
// IDs for ensemble members
// Only set if processing a single file with all ensembles
//
ens_member_ids = [];
control_id = "";

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

//
Expand Down
46 changes: 45 additions & 1 deletion met/docs/Users_Guide/ensemble-stat.rst
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ Optional arguments for ensemble_stat

6. To override the simple ensemble mean value of the input ensemble members for the ECNT, SSVAR, and ORANK line types, the **-ens_mean file** option specifies an ensemble mean model data file. This option replaces the **-ssvar_mean file** option from earlier versions of MET.

7. The **-ctrl file** option specifies an ensemble control member data file. The control member is included in the computation of the ensemble mean but excluded from the spread. The control file should not appear in the list of ensemble member files.
7. The **-ctrl file** option specifies an ensemble control member data file. The control member is included in the computation of the ensemble mean but excluded from the spread. The control file should not appear in the list of ensemble member files (unless processing a single file that contains all ensemble members).

8. To filter point observations by time, use **-obs_valid_beg time** in YYYYMMDD[_HH[MMSS]] format to set the beginning of the matching observation time window.

Expand Down Expand Up @@ -188,6 +188,50 @@ For each **field** listed in the forecast field, give the name and vertical or a

_______________________

.. code-block:: none

ens_member_ids = [];
control_id = "";

The **ens_member_ids** array is only used if reading a single file that contains all ensemble members.
It should contain a list of string identifiers that are substituted into the **ens** and/or **fcst** dictionary fields
to determine which data to read from the file.
The length of the array determines how many ensemble members will be processed for a given field.
Each value in the array will replace the text **MET_ENS_MEMBER_ID**.

**NetCDF Example:**

.. code-block:: none

ens = {
field = [
{
name = "fcst";
level = "(MET_ENS_MEMBER_ID,0,*,*)";
}
];
}

**GRIB Example:**

.. code-block:: none

ens = {
field = [
{
name = "fcst";
level = "L0";
GRIB_ens = "MET_ENS_MEMBER_ID";
}
];
}

**control_id** is a string that is substituted in the same way as the **ens_member_ids** values
to read a control member. This value is only used when the **-ctrl** command line argument is
used. The value should not be found in the **ens_member_ids** array.

_______________________

.. code-block:: none

nbrhd_prob = {
Expand Down
2 changes: 1 addition & 1 deletion met/docs/Users_Guide/gen-ens-prod.rst
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ Each value in the array will replace the text **MET_ENS_MEMBER_ID**.
{
name = "fcst";
level = "L0";
GRIB_ens = "+MET_ENS_MEMBER_ID";
GRIB_ens = "MET_ENS_MEMBER_ID";
}
];
}
Expand Down
123 changes: 123 additions & 0 deletions met/src/libcode/vx_data2d/var_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -790,3 +790,126 @@ int parse_set_attr_flag(Dictionary &dict, const char *key) {
}

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

////////////////////////////////////////////////////////////////////////
//
// Code for class EnsVarInfo
//
////////////////////////////////////////////////////////////////////////

EnsVarInfo::EnsVarInfo() {
ctrl_info = NULL;
}

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

EnsVarInfo::~EnsVarInfo() {
clear();
}
///////////////////////////////////////////////////////////////////////////////

EnsVarInfo::EnsVarInfo(const EnsVarInfo &f) {

clear();

assign(f);
}

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

void EnsVarInfo::clear() {
vector<InputInfo>::const_iterator it;
for(it = inputs.begin(); it != inputs.end(); it++) {
if((*it).var_info) { delete (*it).var_info; }
}

if(ctrl_info) { delete ctrl_info; }
}

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

void EnsVarInfo::assign(const EnsVarInfo &v) {

// Copy
inputs = v.inputs;
ctrl_info = v.ctrl_info;

nc_var_str = v.nc_var_str;
cat_ta = v.cat_ta;
raw_magic_str = v.raw_magic_str;

return;
}

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

void EnsVarInfo::add_input(InputInfo input) {
inputs.push_back(input);
}

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

int EnsVarInfo::inputs_n() {
return inputs.size();
}

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

void EnsVarInfo::set_ctrl(VarInfo * ctrl) {
ctrl_info = ctrl;
}

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

VarInfo * EnsVarInfo::get_ctrl(int index) {
if(ctrl_info) {
return ctrl_info;
}
return inputs[index].var_info;
}

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

VarInfo * EnsVarInfo::get_var_info(int index) {
if(inputs[index].var_info) {
return inputs[index].var_info;
}
return inputs[0].var_info;
}

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

ConcatString EnsVarInfo::get_file(int index) {
int file_index = inputs[index].file_index;
return (*inputs[index].file_list)[file_index];
}

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

int EnsVarInfo::get_file_index(int index) {
return inputs[index].file_index;
}

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

ConcatString raw_magic_str(Dictionary i_edict, GrdFileType file_type) {
ConcatString magic_str;

ConcatString name = i_edict.lookup_string("name");
ConcatString level = i_edict.lookup_string("level", false);

if(level.empty()) {
return name;
}

if(level[0] != '(') {
magic_str << name << "/" << level;
} else {
magic_str << name << level;
}

return magic_str;

}

////////////////////////////////////////////////////////////////////////
48 changes: 48 additions & 0 deletions met/src/libcode/vx_data2d/var_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,54 @@ inline unixtime VarInfo::valid_attr() const { return(SetAttrValid); }
inline int VarInfo::lead_attr() const { return(SetAttrLead); }
inline int VarInfo::accum_attr() const { return(SetAttrAccum); }

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

//
// Struct to store input file and field information
//

struct InputInfo {
VarInfo * var_info; // Variable information to read
int file_index; // Index in file_list of file to read
StringArray * file_list; // Array of files (unallocated)
};

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

//
// Struct to store ensemble information
//
class EnsVarInfo {

private:
vector<InputInfo> inputs; // Vector of InputInfo
VarInfo * ctrl_info; // Field info for control member
public:
EnsVarInfo();
~EnsVarInfo();
EnsVarInfo(const EnsVarInfo &);

void clear();
void assign(const EnsVarInfo &);

void add_input(InputInfo);
int inputs_n();

void set_ctrl(VarInfo *);
VarInfo * get_ctrl(int);

// Get VarInfo from first InputInfo if requested VarInfo is NULL
VarInfo * get_var_info(int index=0);
ConcatString get_file(int index=0);
int get_file_index(int index=0);

ConcatString nc_var_str; // Ensemble variable name strings
ThreshArray cat_ta; // Ensemble categorical thresholds
ConcatString raw_magic_str; // Magic string w/o var substitution
};

ConcatString raw_magic_str(Dictionary i_edict, GrdFileType file_type);

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

#endif // __VAR_INFO_H__
Expand Down
29 changes: 14 additions & 15 deletions met/src/libcode/vx_statistics/pair_data_ensemble.cc
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ VxPairDataEnsemble & VxPairDataEnsemble::operator=(const VxPairDataEnsemble &vx_

void VxPairDataEnsemble::init_from_scratch() {

fcst_info = (VarInfo *) 0;
fcst_info = (EnsVarInfo *) 0;
climo_info = (VarInfo *) 0;
obs_info = (VarInfo *) 0;
pd = (PairDataEnsemble ***) 0;
Expand All @@ -910,7 +910,7 @@ void VxPairDataEnsemble::init_from_scratch() {
void VxPairDataEnsemble::clear() {
int i, j, k;

if(fcst_info) { delete fcst_info; fcst_info = (VarInfo *) 0; }
if(fcst_info) { delete fcst_info; fcst_info = (EnsVarInfo *) 0; }
if(climo_info) { delete climo_info; climo_info = (VarInfo *) 0; }
if(obs_info) { delete obs_info; obs_info = (VarInfo *) 0; }

Expand Down Expand Up @@ -993,15 +993,14 @@ void VxPairDataEnsemble::assign(const VxPairDataEnsemble &vx_pd) {

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

void VxPairDataEnsemble::set_fcst_info(VarInfo *info) {
void VxPairDataEnsemble::set_fcst_info(EnsVarInfo *info) {
VarInfoFactory f;

// Deallocate, if necessary
if(fcst_info) { delete fcst_info; fcst_info = (VarInfo *) 0; }
if(fcst_info) { delete fcst_info; fcst_info = (EnsVarInfo *) 0; }

// Perform a deep copy
fcst_info = f.new_var_info(info->file_type());
*fcst_info = *info;
fcst_info = new EnsVarInfo(*info);

return;
}
Expand Down Expand Up @@ -1458,7 +1457,7 @@ void VxPairDataEnsemble::add_point_obs(float *hdr_arr, int *hdr_typ_arr,
// below the observation point.
else {
// Interpolate using the observation pressure level or height
to_lvl = (fcst_info->level().type() == LevelType_Pres ?
to_lvl = (fcst_info->get_var_info()->level().type() == LevelType_Pres ?
obs_lvl : obs_hgt);
find_vert_lvl(climo_mn_dpa, to_lvl, cmn_lvl_blw, cmn_lvl_abv);
}
Expand All @@ -1472,7 +1471,7 @@ void VxPairDataEnsemble::add_point_obs(float *hdr_arr, int *hdr_typ_arr,
// levels above and below the observation point.
else {
// Interpolate using the observation pressure level or height
to_lvl = (fcst_info->level().type() == LevelType_Pres ?
to_lvl = (fcst_info->get_var_info()->level().type() == LevelType_Pres ?
obs_lvl : obs_hgt);
find_vert_lvl(climo_sd_dpa, to_lvl, csd_lvl_blw, csd_lvl_abv);
}
Expand All @@ -1486,7 +1485,7 @@ void VxPairDataEnsemble::add_point_obs(float *hdr_arr, int *hdr_typ_arr,
}

// Set flag for specific humidity
bool spfh_flag = fcst_info->is_specific_humidity() &&
bool spfh_flag = fcst_info->get_var_info()->is_specific_humidity() &&
obs_info->is_specific_humidity();

// Store pointer to ObsErrorEntry
Expand Down Expand Up @@ -1561,7 +1560,7 @@ void VxPairDataEnsemble::add_point_obs(float *hdr_arr, int *hdr_typ_arr,

// Compute the interpolated climatology values using the
// observation pressure level or height
to_lvl = (fcst_info->level().type() == LevelType_Pres ?
to_lvl = (fcst_info->get_var_info()->level().type() == LevelType_Pres ?
obs_lvl : obs_hgt);

// Compute the interpolated climatology mean
Expand All @@ -1570,7 +1569,7 @@ void VxPairDataEnsemble::add_point_obs(float *hdr_arr, int *hdr_typ_arr,
pd[0][0][k].interp_mthd, pd[0][0][k].interp_wdth,
pd[0][0][k].interp_shape, gr.wrap_lon(),
interp_thresh, spfh_flag,
fcst_info->level().type(),
fcst_info->get_var_info()->level().type(),
to_lvl, cmn_lvl_blw, cmn_lvl_abv);

// Check for bad data
Expand All @@ -1597,7 +1596,7 @@ void VxPairDataEnsemble::add_point_obs(float *hdr_arr, int *hdr_typ_arr,
pd[0][0][k].interp_mthd, pd[0][0][k].interp_wdth,
pd[0][0][k].interp_shape, gr.wrap_lon(),
interp_thresh, spfh_flag,
fcst_info->level().type(),
fcst_info->get_var_info()->level().type(),
to_lvl, csd_lvl_blw, csd_lvl_abv);

// Check for bad data
Expand Down Expand Up @@ -1630,7 +1629,7 @@ void VxPairDataEnsemble::add_ens(int member, bool mn, Grid &gr) {
double to_lvl, fcst_v;

// Set flag for specific humidity
bool spfh_flag = fcst_info->is_specific_humidity() &&
bool spfh_flag = fcst_info->get_var_info()->is_specific_humidity() &&
obs_info->is_specific_humidity();

// Loop through all the PairDataEnsemble objects and interpolate
Expand All @@ -1642,7 +1641,7 @@ void VxPairDataEnsemble::add_ens(int member, bool mn, Grid &gr) {
for(l=0; l<pd[i][j][k].n_obs; l++) {

// Interpolate using the observation pressure level or height
to_lvl = (fcst_info->level().type() == LevelType_Pres ?
to_lvl = (fcst_info->get_var_info()->level().type() == LevelType_Pres ?
pd[i][j][k].lvl_na[l] : pd[i][j][k].elv_na[l]);

// For a single forecast field
Expand All @@ -1668,7 +1667,7 @@ void VxPairDataEnsemble::add_ens(int member, bool mn, Grid &gr) {
pd[0][0][k].interp_shape,
gr.wrap_lon(),
interp_thresh, spfh_flag,
fcst_info->level().type(),
fcst_info->get_var_info()->level().type(),
to_lvl, f_lvl_blw, f_lvl_abv);

// Store the ensemble mean
Expand Down
Loading