From 80e909574e365bd4ed347d571d12d1e7dfbf75e2 Mon Sep 17 00:00:00 2001 From: johnhg Date: Tue, 20 Sep 2022 23:18:54 -0600 Subject: [PATCH] Feature 1908 remove ens (#2265) --- data/config/EnsembleStatConfig_default | 78 +- docs/Users_Guide/ensemble-stat.rst | 185 +-- internal/test_unit/config/EnsembleStatConfig | 82 +- .../config/EnsembleStatConfig_MASK_SID | 81 +- .../test_unit/config/EnsembleStatConfig_climo | 75 +- .../config/EnsembleStatConfig_grid_weight | 74 +- .../config/EnsembleStatConfig_one_cdf_bin | 62 +- .../config/EnsembleStatConfig_python | 79 +- .../config/EnsembleStatConfig_qty_inc_exc | 77 +- .../EnsembleStatConfig_single_file_grib | 79 +- .../config/EnsembleStatConfig_single_file_nc | 95 +- .../test_unit/xml/unit_climatology_1.0deg.xml | 2 - internal/test_unit/xml/unit_ensemble_stat.xml | 11 - internal/test_unit/xml/unit_grid_weight.xml | 6 +- .../test_unit/xml/unit_met_test_scripts.xml | 1 - internal/test_unit/xml/unit_python.xml | 3 +- .../test_unit/xml/unit_quality_filter.xml | 1 - scripts/config/EnsembleStatConfig | 98 +- src/basic/vx_config/config_constants.h | 38 +- src/basic/vx_util/data_plane.cc | 86 +- src/basic/vx_util/data_plane.h | 6 +- src/libcode/vx_statistics/met_stats.cc | 124 +- src/tools/core/ensemble_stat/ensemble_stat.cc | 1224 ++++------------- src/tools/core/ensemble_stat/ensemble_stat.h | 42 +- .../ensemble_stat/ensemble_stat_conf_info.cc | 435 ++---- .../ensemble_stat/ensemble_stat_conf_info.h | 38 +- src/tools/other/ascii2nc/aeronet_handler.cc | 9 +- src/tools/other/ascii2nc/airnow_handler.cc | 24 +- 28 files changed, 802 insertions(+), 2313 deletions(-) diff --git a/data/config/EnsembleStatConfig_default b/data/config/EnsembleStatConfig_default index 93380170ef..04bf1fd6ee 100644 --- a/data/config/EnsembleStatConfig_default +++ b/data/config/EnsembleStatConfig_default @@ -37,30 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 1.0; - vld_thresh = 1.0; - - field = [ - { - name = "APCP"; - level = "A03"; - cat_thresh = [ >0.0, >=5.0 ]; - } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -68,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -110,12 +59,16 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 1.0; + vld_thresh = 1.0; + field = [ { name = "APCP"; @@ -262,6 +215,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = NONE; @@ -281,22 +235,16 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; mean = TRUE; - stdev = TRUE; - minus = TRUE; - plus = TRUE; - min = TRUE; - max = TRUE; - range = TRUE; - vld_count = TRUE; - frequency = TRUE; - nep = FALSE; - nmep = FALSE; + raw = TRUE; rank = TRUE; + pit = TRUE; + vld_count = TRUE; weight = FALSE; } diff --git a/docs/Users_Guide/ensemble-stat.rst b/docs/Users_Guide/ensemble-stat.rst index 6eb9f008d3..2036ab4457 100644 --- a/docs/Users_Guide/ensemble-stat.rst +++ b/docs/Users_Guide/ensemble-stat.rst @@ -7,26 +7,13 @@ Ensemble-Stat Tool Introduction ============ -The Ensemble-Stat tool may be run to create simple ensemble forecasts (mean, probability, spread, etc) from a set of several forecast model files to be used by the MET statistics tools. If observations are also included, ensemble statistics such as rank histograms, probability integral transform histograms, spread/skill variance, relative position and continuous ranked probability score are produced. Climatological mean and standard deviation data may also be provided, and will be used as a reference forecast in several of the output statistics. Finally, observation error perturbations can be included prior to calculation of statistics. Details about and equations for the statistics produced for ensembles are given in :numref:`Appendix C, Section %s `. +The Ensemble-Stat tool verifies deterministic ensemble members against gridded and/or point observations. It computes ensemble statistics such as rank histograms, probability integral transform histograms, spread/skill variance, relative position and continuous ranked probability score. Climatological mean and standard deviation data may also be provided, and is used as a reference forecast in several of the output statistics. Finally, observation error perturbations can be included prior to calculation of statistics. Details about and equations for the statistics produced for ensembles are given in :numref:`Appendix C, Section %s `. -.. note:: This tool will be changing! The ensemble product generation step provided by Ensemble-Stat is now found within the :ref:`Gen-Ens-Prod Tool`. The Gen-Ens-Prod tool replaces and extends that functionality. Users are strongly encouraged to migrate ensemble product generation from Ensemble-Stat to Gen-Ens-Prod, as new features will only be added to Gen-Ens-Prod and the existing Ensemble-Stat functionality will be deprecated in a future version. +.. note:: Earlier versions of the Ensemble-Stat tool supported both ensemble product generation and ensemble verification. However, the ensemble product generation logic has moved to the :ref:`Gen-Ens-Prod Tool`, which replaces and extends that functionality. Ensemble product generation was removed from Ensemble-Stat in version 11.0.0. Scientific and statistical aspects ================================== -Ensemble forecasts derived from a set of deterministic ensemble members ------------------------------------------------------------------------ - -Ensemble forecasts are often created as a set of deterministic forecasts. The ensemble members are rarely used separately. Instead, they can be combined in various ways to produce a forecast. MET can combine the ensemble members into some type of summary forecast according to user specifications. Ensemble means are the most common, and can be paired with the ensemble variance or spread. Maximum, minimum and other summary values are also available, with details in the practical information section. - -Typically an ensemble is constructed by selecting a single forecast value from each member for each observation. When the High Resolution Assessment (HiRA) interpolation method is chosen, all of the nearby neighborhood points surrounding each observation from each member are used. Therefore, processing an N-member ensemble using a HiRA neighborhood of size M produces ensemble output with size N*M. This approach fully leverages information from all nearby grid points to evaluate the ensemble quality. - -The ensemble relative frequency is the simplest method for turning a set of deterministic forecasts into something resembling a probability forecast. For each categorical threshold (cat_thresh) listed for each field array entry of the ensemble dictionary (ens.field), MET will create the ensemble relative frequency as the proportion of ensemble members forecasting that event. For example, if 5 out of 10 ensemble members predict measurable precipitation at a grid location, then the ensemble relative frequency of precipitation will be :math:`5/10=0.5`. If the ensemble relative frequency is calibrated (unlikely) then this could be thought of as a probability of precipitation. - -The neighborhood ensemble probability (NEP) and neighborhood maximum ensemble probability (NMEP) methods are described in :ref:`Schwartz and Sobash (2017) `. They are an extension of the ensemble relative frequencies described above. The NEP value is computed by averaging the relative frequency of the event within the neighborhood over all ensemble members. The NMEP value is computed as the fraction of ensemble members for which the event is occurring somewhere within the surrounding neighborhood. The NMEP output is typically smoothed using a Gaussian kernel filter. The neighborhood sizes and smoothing options can be customized in the configuration file. - -The Ensemble-Stat tool writes the gridded relative frequencies, NEP, and NMEP fields to a NetCDF output file. Probabilistic verification methods can then be applied to those fields by evaluating them with the Grid-Stat and/or Point-Stat tools. - Ensemble statistics ------------------- @@ -168,33 +155,16 @@ ____________________ output_prefix = ""; version = "VN.N"; + The configuration options listed above are common to many MET tools and are described in :numref:`config_options`. Note that the **HIRA** interpolation method is only supported in Ensemble-Stat. _____________________ -.. code-block:: none - - ens = { - ens_thresh = 1.0; - vld_thresh = 1.0; - field = [ - { - name = "APCP"; - level = "A03"; - cat_thresh = [ >0.0, >=5.0 ]; - } - ]; - } - -The **ens** dictionary defines which ensemble fields should be processed. - -When summarizing the ensemble, compute a ratio of the number of valid ensemble fields to the total number of ensemble members. If this ratio is less than the **ens_thresh**, then quit with an error. This threshold must be between 0 and 1. Setting this threshold to 1 will require that all ensemble members be present to be processed. - - -When summarizing the ensemble, for each grid point compute a ratio of the number of valid data values to the number of ensemble members. If that ratio is less than **vld_thresh**, write out bad data. This threshold must be between 0 and 1. Setting this threshold to 1 will require each grid point to contain valid data for all ensemble members. +When processing the **fcst** data, compute a ratio of the number of valid ensemble fields to the total number of ensemble members. If this ratio is less than the **ens_thresh**, then quit with an error. This threshold must be between 0 and 1. Setting this threshold to 1 will require that all ensemble members be present to be processed. +When processing the **fcst** data, for each grid point compute a ratio of the number of valid data values to the number of ensemble members. If that ratio is less than **vld_thresh**, write out bad data. This threshold must be between 0 and 1. Setting this threshold to 1 will require each grid point to contain valid data for all ensemble members. For each **field** listed in the forecast field, give the name and vertical or accumulation level, plus one or more categorical thresholds. The thresholds are specified using symbols, as shown above. It is the user's responsibility to know the units for each model variable and to choose appropriate threshold values. The thresholds are used to define ensemble relative frequencies, e.g. a threshold of >=5 can be used to compute the proportion of ensemble members predicting precipitation of at least 5mm at each grid point. @@ -205,6 +175,7 @@ _______________________ 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. @@ -215,7 +186,7 @@ Each value in the array will replace the text **MET_ENS_MEMBER_ID**. .. code-block:: none - ens = { + fcst = { field = [ { name = "fcst"; @@ -224,11 +195,12 @@ Each value in the array will replace the text **MET_ENS_MEMBER_ID**. ]; } + **GRIB Example:** .. code-block:: none - ens = { + fcst = { field = [ { name = "fcst"; @@ -238,52 +210,11 @@ Each value in the array will replace the text **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 = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; - } - - -The **nbrhd_prob** dictionary defines the neighborhoods used to compute NEP and NMEP output. - - -The neighborhood **shape** is a **SQUARE** or **CIRCLE** centered on the current point, and the **width** array specifies the width of the square or diameter of the circle as an odd integer. The **vld_thresh** entry is a number between 0 and 1 specifying the required ratio of valid data in the neighborhood for an output value to be computed. - - -If **ensemble_flag.nep** is set to TRUE, NEP output is created for each combination of the categorical threshold (**cat_thresh**) and neighborhood width specified. - -_____________________ - -.. code-block:: none - - nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; - } - - -Similar to the **interp** dictionary, the **nmep_smooth** dictionary includes a **type** array of dictionaries to define one or more methods for smoothing the NMEP data. Setting the interpolation method to nearest neighbor (**NEAREST**) effectively disables this smoothing step. - - -If **ensemble_flag.nmep** is set to TRUE, NMEP output is created for each combination of the categorical threshold (**cat_thresh**), neighborhood width (**nbrhd_prob.width**), and smoothing method(**nmep_smooth.type**) specified. - _____________________ .. code-block:: none @@ -334,6 +265,7 @@ The **prob_pct_thresh** entry is an array of thresholds which define the Nx2 pro prob_cat_thresh = [ ==0.25 ]; + __________________ .. code-block:: none @@ -386,7 +318,6 @@ _________________ The **output_flag** array controls the type of output that is generated. Each flag corresponds to an output line type in the STAT file. Setting the flag to NONE indicates that the line type should not be generated. Setting the flag to STAT indicates that the line type should be written to the STAT file only. Setting the flag to BOTH indicates that the line type should be written to the STAT file as well as a separate ASCII file where the data is grouped by line type. The output flags correspond to the following output line types: - 1. **ECNT** for Continuous Ensemble Statistics 2. **RPS** for Ranked Probability Score Statistics @@ -414,53 +345,33 @@ The **output_flag** array controls the type of output that is generated. Each fl _____________________ .. code-block:: none - - ensemble_flag = { + + nc_orank_flag = { latlon = TRUE; - mean = TRUE; - stdev = TRUE; - minus = TRUE; - plus = TRUE; - min = TRUE; - max = TRUE; - range = TRUE; - vld_count = TRUE; - frequency = TRUE; - nep = FALSE; - nmep = FALSE; - rank = TRUE; - weight = FALSE; + mean = TRUE; + raw = TRUE; + rank = TRUE; + pit = TRUE; + vld_count = TRUE; + weight = FALSE; } -The **ensemble_flag** specifies which derived ensemble fields should be calculated and output. Setting the flag to TRUE produces output of the specified field, while FALSE produces no output for that field type. The flags correspond to the following output line types: - -1. Grid Latitude and Longitude Fields - -2. Ensemble Mean Field - -3. Ensemble Standard Deviation Field -4. Ensemble Mean - One Standard Deviation Field +The **nc_orank_flag** specifies which gridded verification output types should be written to the Observation Rank (**_orank.nc**) NetCDF file. This output file is only created when gridded observations have been provided with the -grid_obs command line option. Setting the flag to TRUE produces output of the specified field, while FALSE produces no output for that field type. The flags correspond to the following output line types: -5. Ensemble Mean + One Standard Deviation Field - -6. Ensemble Minimum Field - -7. Ensemble Maximum Field - -8. Ensemble Range Field +1. Grid Latitude and Longitude Fields -9. Ensemble Valid Data Count +2. Ensemble mean field -10. Ensemble Relative Frequency for each categorical threshold (**cat_thresh**) specified. This is an uncalibrated probability forecast. +3. Raw observation values -11. Neighborhood Ensemble Probability for each categorical threshold (**cat_thresh**) and neighborhood width (**nbrhd_prob.width**) specified. +4. Observation ranks -12. Neighborhood Maximum Ensemble Probability for each categorical threshold (**cat_thresh**), neighborhood width (**nbrhd_prob.width**), and smoothing method (**nmep_smooth.type**) specified. +5. Observation probability-integral transform values -13. Observation Ranks for input gridded observations are written to a separate NetCDF output file. +6. Ensemble valid data count -14. The grid area weights applied are written to the Observation Rank output file. +7. Grid area weight values __________________ @@ -505,49 +416,15 @@ ensemble_stat_PREFIX_YYYYMMDD_HHMMSSV.stat where PREFIX indicates the user-defin The output ASCII files are named similarly: -ensemble_stat_PREFIX_YYYYMMDD_HHMMSSV_TYPE.txt where TYPE is one of ecnt, rps, rhist, phist, relp, orank, and ssvar to indicate the line type it contains. - - -When fields are requested in the ens dictionary of the configuration file or verification against gridded fields is performed, ensemble_stat can produce output NetCDF files using the following naming convention: - - -ensemble_stat_PREFIX_YYYYMMDD_HHMMSSV_TYPE.nc where TYPE is either ens or orank. The orank NetCDF output file contains gridded fields of observation ranks when the -grid_obs command line option is used. The ens NetCDF output file contains ensemble products derived from the fields requested in the ens dictionary of the configuration file. The Ensemble-Stat tool can calculate any of the following fields from the input ensemble members, as specified in the ensemble_flag dictionary in the configuration file: - - -Ensemble Mean fields - - -Ensemble Standard Deviation fields - - -Ensemble Mean - 1 Standard Deviation fields - - -Ensemble Mean + 1 Standard Deviation fields - - -Ensemble Minimum fields - - -Ensemble Maximum fields - - -Ensemble Range fields - - -Ensemble Valid Data Count fields - - -Ensemble Relative Frequency by threshold fields (e.g. ensemble probabilities) - +ensemble_stat_PREFIX_YYYYMMDD_HHMMSSV_TYPE.txt where TYPE is one of elements of the **output_flag** configuration option to indicate the line type it contains. -Neighborhood Ensemble Probability and Neighborhood Maximum Ensemble Probability +When verification against gridded analyses is performed, Ensemble-Stat can produce output NetCDF files using the following naming convention: -Rank for each Observation Value (if gridded observation field provided) +ensemble_stat_PREFIX_YYYYMMDD_HHMMSSV_orank.nc contains gridded fields of observation ranks when the -grid_obs command line option is used. Its contents are specified by the **nc_orank_flag** configuration option. -When gridded or point observations are provided, using the -grid_obs and -point_obs command line options, respectively, the Ensemble-Stat tool can compute the following statistics for the fields specified in the fcst and obs dictionaries of the configuration file: +The Ensemble-Stat tool can compute the following statistics for the fields specified in the fcst and obs dictionaries of the configuration file: Continuous Ensemble Statistics diff --git a/internal/test_unit/config/EnsembleStatConfig b/internal/test_unit/config/EnsembleStatConfig index 1e9c7cf244..4922db14e4 100644 --- a/internal/test_unit/config/EnsembleStatConfig +++ b/internal/test_unit/config/EnsembleStatConfig @@ -37,35 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 0.75; - vld_thresh = 1.0; - - field = [ - { - name = "TMP"; - level = "Z2"; - cat_thresh = [ <=273.15, >273.15 ]; - }, - { - name = "APCP"; - level = "A24"; - cat_thresh = [ >0.0 ]; - } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -73,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -115,12 +59,15 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 0.75; + vld_thresh = 1.0; message_type = [ "ADPSFC" ]; obs_quality_inc = []; obs_quality_exc = []; @@ -234,6 +181,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = BOTH; @@ -253,22 +201,16 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; mean = TRUE; - stdev = TRUE; - minus = TRUE; - plus = TRUE; - min = TRUE; - max = TRUE; - range = TRUE; - vld_count = TRUE; - frequency = TRUE; - nep = FALSE; - nmep = FALSE; + raw = TRUE; rank = TRUE; + pit = TRUE; + vld_count = TRUE; weight = FALSE; } diff --git a/internal/test_unit/config/EnsembleStatConfig_MASK_SID b/internal/test_unit/config/EnsembleStatConfig_MASK_SID index fab2c42267..38a9174064 100644 --- a/internal/test_unit/config/EnsembleStatConfig_MASK_SID +++ b/internal/test_unit/config/EnsembleStatConfig_MASK_SID @@ -37,32 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 0.75; - vld_thresh = 1.0; - - field = [ - { - name = "APCP"; - level = "A24"; - cat_thresh = [ >0.0 ]; - censor_thresh = [ ${CENSOR_THRESH} ]; - censor_val = [ ${CENSOR_VAL} ]; - } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -70,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -112,13 +59,16 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { - message_type = [ "ADPSFC" ]; + ens_thresh = 0.75; + vld_thresh = 1.0; + message_type = [ "ADPSFC" ]; field = [ { @@ -223,6 +173,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = STAT; @@ -242,22 +193,16 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; mean = TRUE; - stdev = TRUE; - minus = FALSE; - plus = FALSE; - min = TRUE; - max = TRUE; - range = TRUE; - vld_count = FALSE; - frequency = TRUE; - nep = FALSE; - nmep = FALSE; + raw = FALSE; rank = FALSE; + pit = FALSE; + vld_count = FALSE; weight = FALSE; } diff --git a/internal/test_unit/config/EnsembleStatConfig_climo b/internal/test_unit/config/EnsembleStatConfig_climo index f2018f80c6..3b118c06ec 100644 --- a/internal/test_unit/config/EnsembleStatConfig_climo +++ b/internal/test_unit/config/EnsembleStatConfig_climo @@ -37,27 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 0.75; - vld_thresh = 1.0; - - field = [ - { name = "TMP"; level = "Z2"; }, - { name = "TMP"; level = "P850"; } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -65,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -107,12 +59,16 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 0.75; + vld_thresh = 1.0; + field = [ { name = "TMP"; level = "Z2"; message_type = [ "ADPSFC" ]; }, { name = "TMP"; level = "P850"; message_type = [ "ADPUPA" ]; } @@ -246,6 +202,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = BOTH; @@ -265,22 +222,16 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = FALSE; mean = TRUE; - stdev = FALSE; - minus = FALSE; - plus = FALSE; - min = FALSE; - max = FALSE; - range = FALSE; - vld_count = FALSE; - frequency = FALSE; - nep = FALSE; - nmep = FALSE; + raw = TRUE; rank = TRUE; + pit = TRUE; + vld_count = FALSE; weight = FALSE; } diff --git a/internal/test_unit/config/EnsembleStatConfig_grid_weight b/internal/test_unit/config/EnsembleStatConfig_grid_weight index 011c18daed..bb07dbca49 100644 --- a/internal/test_unit/config/EnsembleStatConfig_grid_weight +++ b/internal/test_unit/config/EnsembleStatConfig_grid_weight @@ -37,25 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -tmp_field = [ { name = "TMP"; level = [ "Z2" ]; } ]; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 0.75; - vld_thresh = 1.0; - field = tmp_field; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -63,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -105,12 +59,17 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; +tmp_field = [ { name = "TMP"; level = [ "Z2" ]; } ]; + // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 0.75; + vld_thresh = 1.0; message_type = [ "APDSFC" ]; sid_inc = []; sid_exc = []; @@ -231,6 +190,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = STAT; @@ -250,22 +210,16 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; mean = TRUE; - stdev = FALSE; - minus = FALSE; - plus = FALSE; - min = FALSE; - max = FALSE; - range = FALSE; - vld_count = FALSE; - frequency = FALSE; - nep = FALSE; - nmep = FALSE; + raw = FALSE; rank = FALSE; + pit = FALSE; + vld_count = FALSE; weight = TRUE; } diff --git a/internal/test_unit/config/EnsembleStatConfig_one_cdf_bin b/internal/test_unit/config/EnsembleStatConfig_one_cdf_bin index a2fee38da0..9a638d89cd 100644 --- a/internal/test_unit/config/EnsembleStatConfig_one_cdf_bin +++ b/internal/test_unit/config/EnsembleStatConfig_one_cdf_bin @@ -37,27 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 0.75; - vld_thresh = 1.0; - - field = [ - { name = "TMP"; level = "Z2"; }, - { name = "TMP"; level = "P850"; } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -65,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -107,12 +59,16 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 0.75; + vld_thresh = 1.0; + field = [ { name = "TMP"; level = "Z2"; message_type = [ "ADPSFC" ]; }, { name = "TMP"; level = "P850"; message_type = [ "ADPUPA" ]; } @@ -239,6 +195,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = BOTH; @@ -258,9 +215,10 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = false; +nc_orank_flag = false; //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_python b/internal/test_unit/config/EnsembleStatConfig_python index e51aeb9e8a..734479b93d 100644 --- a/internal/test_unit/config/EnsembleStatConfig_python +++ b/internal/test_unit/config/EnsembleStatConfig_python @@ -37,24 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 1.0; - vld_thresh = 1.0; - file_type = PYTHON_NUMPY; - field = [ { name = "${FCST_COMMAND}"; } ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -62,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -104,13 +59,20 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // -fcst = ens; -obs = { +fcst = { + ens_thresh = 1.0; + vld_thresh = 1.0; + + file_type = PYTHON_NUMPY; + field = [ { name = "${FCST_COMMAND}"; } ]; +} +obs = { file_type = PYTHON_NUMPY; field = [ { name = "${OBS_COMMAND}"; } ]; } @@ -215,6 +177,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = STAT; @@ -234,22 +197,16 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; mean = TRUE; - stdev = FALSE; - minus = FALSE; - plus = FALSE; - min = FALSE; - max = FALSE; - range = FALSE; - vld_count = TRUE; - frequency = FALSE; - nep = FALSE; - nmep = FALSE; + raw = FALSE; rank = FALSE; + pit = FALSE; + vld_count = TRUE; weight = FALSE; } diff --git a/internal/test_unit/config/EnsembleStatConfig_qty_inc_exc b/internal/test_unit/config/EnsembleStatConfig_qty_inc_exc index cc0838f25e..5fd29fce6f 100644 --- a/internal/test_unit/config/EnsembleStatConfig_qty_inc_exc +++ b/internal/test_unit/config/EnsembleStatConfig_qty_inc_exc @@ -37,30 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 1.0; - vld_thresh = 1.0; - - field = [ - { - name = "TMP"; - level = [ "Z2" ]; - cat_thresh = [ <=273, >273 ]; - } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -68,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -110,12 +59,15 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 1.0; + vld_thresh = 1.0; message_type = [ "ADPSFC" ]; sid_inc = []; sid_exc = []; @@ -238,6 +190,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = BOTH; @@ -257,22 +210,16 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; mean = TRUE; - stdev = TRUE; - minus = TRUE; - plus = TRUE; - min = TRUE; - max = TRUE; - range = TRUE; - vld_count = TRUE; - frequency = TRUE; - nep = FALSE; - nmep = FALSE; + raw = TRUE; rank = TRUE; + pit = TRUE; + vld_count = TRUE; weight = FALSE; } diff --git a/internal/test_unit/config/EnsembleStatConfig_single_file_grib b/internal/test_unit/config/EnsembleStatConfig_single_file_grib index e731c8074f..fa9430c1d6 100644 --- a/internal/test_unit/config/EnsembleStatConfig_single_file_grib +++ b/internal/test_unit/config/EnsembleStatConfig_single_file_grib @@ -37,31 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 1.0; - vld_thresh = 1.0; - - field = [ - { - name = "PRMSL"; - level = "L0"; - lead_time = "06"; - GRIB_ens = "MET_ENS_MEMBER_ID"; - } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -69,38 +44,11 @@ ens = { ens_member_ids = ["+1", "+2", "+3", "+4", "+5", "+6", "+7", "+8", "+9", "+10", "+11", "+12", "+13", "+14", "+15", "+16", "+17", "+18", "+19", "+20"]; control_id = "hi_res_ctl"; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -111,12 +59,16 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 1.0; + vld_thresh = 1.0; + field = [ { name = "PRMSL"; @@ -274,6 +226,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = STAT; @@ -293,22 +246,16 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; mean = TRUE; - stdev = TRUE; - minus = FALSE; - plus = FALSE; - min = TRUE; - max = TRUE; - range = FALSE; - vld_count = TRUE; - frequency = FALSE; - nep = FALSE; - nmep = FALSE; + raw = TRUE; rank = TRUE; + pit = TRUE; + vld_count = TRUE; weight = FALSE; } diff --git a/internal/test_unit/config/EnsembleStatConfig_single_file_nc b/internal/test_unit/config/EnsembleStatConfig_single_file_nc index 285ea922fc..bcf58eb3cb 100644 --- a/internal/test_unit/config/EnsembleStatConfig_single_file_nc +++ b/internal/test_unit/config/EnsembleStatConfig_single_file_nc @@ -37,38 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Override the NetCDF CFS variable names and times -// -file_type = NETCDF_NCCF; -set_attr_init = "19820101"; -set_attr_valid = "19820701"; -set_attr_name = "TMP"; -set_attr_level = "Z2"; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 1.0; - vld_thresh = 1.0; - - field = [ - { - name = "fcst"; - level = "(MET_ENS_MEMBER_ID,6,*,*)"; - } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -76,38 +44,11 @@ ens = { ens_member_ids = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"]; control_id = "0"; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -118,12 +59,25 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; +// +// Override the NetCDF CFS variable names and times +// +file_type = NETCDF_NCCF; +set_attr_init = "19820101"; +set_attr_valid = "19820701"; +set_attr_name = "TMP"; +set_attr_level = "Z2"; + // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 1.0; + vld_thresh = 1.0; + field = [ { name = "fcst"; @@ -278,6 +232,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = STAT; @@ -297,22 +252,16 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; mean = TRUE; - stdev = TRUE; - minus = FALSE; - plus = FALSE; - min = TRUE; - max = TRUE; - range = FALSE; - vld_count = TRUE; - frequency = FALSE; - nep = FALSE; - nmep = FALSE; + raw = TRUE; rank = TRUE; + pit = TRUE; + vld_count = TRUE; weight = FALSE; } diff --git a/internal/test_unit/xml/unit_climatology_1.0deg.xml b/internal/test_unit/xml/unit_climatology_1.0deg.xml index a357b5c8b1..a07d47ff6e 100644 --- a/internal/test_unit/xml/unit_climatology_1.0deg.xml +++ b/internal/test_unit/xml/unit_climatology_1.0deg.xml @@ -269,7 +269,6 @@ &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_NCEP_1.0DEG_20120410_120000V_prc.txt &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_NCEP_1.0DEG_20120410_120000V_pjc.txt &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_NCEP_1.0DEG_20120410_120000V_eclv.txt - &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_NCEP_1.0DEG_20120410_120000V_ens.nc &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_NCEP_1.0DEG_20120410_120000V_orank.nc @@ -299,7 +298,6 @@ &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_ONE_CDF_BIN_20120410_120000V.stat &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_ONE_CDF_BIN_20120410_120000V_ecnt.txt - &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_ONE_CDF_BIN_20120410_120000V_ens.nc diff --git a/internal/test_unit/xml/unit_ensemble_stat.xml b/internal/test_unit/xml/unit_ensemble_stat.xml index 98a97a4779..6ee7fd6153 100644 --- a/internal/test_unit/xml/unit_ensemble_stat.xml +++ b/internal/test_unit/xml/unit_ensemble_stat.xml @@ -52,7 +52,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_CMD_LINE_20120410_120000V_phist.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_CMD_LINE_20120410_120000V_orank.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_CMD_LINE_20120410_120000V_ssvar.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_CMD_LINE_20120410_120000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_CMD_LINE_20120410_120000V_orank.nc @@ -88,7 +87,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_phist.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_orank.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_ssvar.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_orank.nc @@ -119,7 +117,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_20120410_120000V.stat &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_20120410_120000V_orank.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_20120410_120000V_ens.nc @@ -147,7 +144,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_CTRL_20120410_120000V.stat &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_CTRL_20120410_120000V_orank.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_CTRL_20120410_120000V_ens.nc @@ -175,7 +171,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_CENSOR_20120410_120000V.stat &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_CENSOR_20120410_120000V_orank.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_CENSOR_20120410_120000V_ens.nc @@ -210,7 +205,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SKIP_CONST_20120410_120000V_phist.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SKIP_CONST_20120410_120000V_orank.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SKIP_CONST_20120410_120000V_ssvar.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SKIP_CONST_20120410_120000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SKIP_CONST_20120410_120000V_orank.nc @@ -246,7 +240,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_OBSERR_20120410_120000V_phist.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_OBSERR_20120410_120000V_orank.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_OBSERR_20120410_120000V_ssvar.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_OBSERR_20120410_120000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_OBSERR_20120410_120000V_orank.nc @@ -268,7 +261,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_NC_NO_CTRL_19820701_000000V.stat - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_NC_NO_CTRL_19820701_000000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_NC_NO_CTRL_19820701_000000V_orank.nc @@ -291,7 +283,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_NC_WITH_CTRL_19820701_000000V.stat - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_NC_WITH_CTRL_19820701_000000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_NC_WITH_CTRL_19820701_000000V_orank.nc @@ -313,7 +304,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_GRIB_NO_CTRL_20160608_060000V.stat - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_GRIB_NO_CTRL_20160608_060000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_GRIB_NO_CTRL_20160608_060000V_orank.nc @@ -336,7 +326,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_GRIB_WITH_CTRL_20160608_060000V.stat - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_GRIB_WITH_CTRL_20160608_060000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_GRIB_WITH_CTRL_20160608_060000V_orank.nc diff --git a/internal/test_unit/xml/unit_grid_weight.xml b/internal/test_unit/xml/unit_grid_weight.xml index f355401441..85005feec1 100644 --- a/internal/test_unit/xml/unit_grid_weight.xml +++ b/internal/test_unit/xml/unit_grid_weight.xml @@ -96,7 +96,7 @@ &OUTPUT_DIR;/grid_weight/ensemble_stat_NO_WEIGHT_20120410_120000V.stat - &OUTPUT_DIR;/grid_weight/ensemble_stat_NO_WEIGHT_20120410_120000V_ens.nc + &OUTPUT_DIR;/grid_weight/ensemble_stat_NO_WEIGHT_20120410_120000V_orank.nc @@ -121,7 +121,7 @@ &OUTPUT_DIR;/grid_weight/ensemble_stat_COS_LAT_WEIGHT_20120410_120000V.stat - &OUTPUT_DIR;/grid_weight/ensemble_stat_COS_LAT_WEIGHT_20120410_120000V_ens.nc + &OUTPUT_DIR;/grid_weight/ensemble_stat_COS_LAT_WEIGHT_20120410_120000V_orank.nc @@ -146,7 +146,7 @@ &OUTPUT_DIR;/grid_weight/ensemble_stat_AREA_WEIGHT_20120410_120000V.stat - &OUTPUT_DIR;/grid_weight/ensemble_stat_AREA_WEIGHT_20120410_120000V_ens.nc + &OUTPUT_DIR;/grid_weight/ensemble_stat_AREA_WEIGHT_20120410_120000V_orank.nc diff --git a/internal/test_unit/xml/unit_met_test_scripts.xml b/internal/test_unit/xml/unit_met_test_scripts.xml index 9d0176c561..a92610f795 100644 --- a/internal/test_unit/xml/unit_met_test_scripts.xml +++ b/internal/test_unit/xml/unit_met_test_scripts.xml @@ -474,7 +474,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_20100101_120000V_prc.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_20100101_120000V_eclv.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_20100101_120000V.stat - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_20100101_120000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_20100101_120000V_orank.nc diff --git a/internal/test_unit/xml/unit_python.xml b/internal/test_unit/xml/unit_python.xml index e0f2cfe781..94dfac5e68 100644 --- a/internal/test_unit/xml/unit_python.xml +++ b/internal/test_unit/xml/unit_python.xml @@ -361,7 +361,7 @@ &OUTPUT_DIR;/python/ensemble_stat_PYTHON_20050807_120000V.stat - &OUTPUT_DIR;/python/ensemble_stat_PYTHON_20050807_120000V_ens.nc + &OUTPUT_DIR;/python/ensemble_stat_PYTHON_20050807_120000V_orank.nc @@ -562,7 +562,6 @@ &OUTPUT_DIR;/python/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_phist.txt &OUTPUT_DIR;/python/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_orank.txt &OUTPUT_DIR;/python/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_ssvar.txt - &OUTPUT_DIR;/python/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_ens.nc &OUTPUT_DIR;/python/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_orank.nc diff --git a/internal/test_unit/xml/unit_quality_filter.xml b/internal/test_unit/xml/unit_quality_filter.xml index cbf086e4d5..560f1d8fab 100644 --- a/internal/test_unit/xml/unit_quality_filter.xml +++ b/internal/test_unit/xml/unit_quality_filter.xml @@ -61,7 +61,6 @@ &OUTPUT_DIR;/quality_filter/ensemble_stat_QTY_INC_EXC_MADIS_VGS_20120409_120000V_ecnt.txt &OUTPUT_DIR;/quality_filter/ensemble_stat_QTY_INC_EXC_MADIS_VGS_20120409_120000V_rhist.txt &OUTPUT_DIR;/quality_filter/ensemble_stat_QTY_INC_EXC_MADIS_VGS_20120409_120000V_orank.txt - &OUTPUT_DIR;/quality_filter/ensemble_stat_QTY_INC_EXC_MADIS_VGS_20120409_120000V_ens.nc diff --git a/scripts/config/EnsembleStatConfig b/scripts/config/EnsembleStatConfig index 2dde84f7bb..d973d2f113 100644 --- a/scripts/config/EnsembleStatConfig +++ b/scripts/config/EnsembleStatConfig @@ -37,51 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 1.0; - vld_thresh = 1.0; - - field = [ - { - name = "APCP"; - level = [ "A24" ]; - cat_thresh = [ >0.0, >=10.0 ]; - }, - { - name = "REFC"; - level = [ "L0" ]; - cat_thresh = [ >=35.0 ]; - GRIB1_ptv = 129; - }, - { - name = "UGRD"; - level = [ "Z10" ]; - cat_thresh = [ >=5.0 ]; - }, - { - name = "VGRD"; - level = [ "Z10" ]; - cat_thresh = [ >=5.0 ]; - }, - { - name = "WIND"; - level = [ "Z10" ]; - cat_thresh = [ >=5.0 ]; - } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -89,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -131,12 +59,15 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 1.0; + vld_thresh = 1.0; message_type = [ "ADPSFC" ]; field = [ @@ -296,6 +227,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = BOTH; @@ -315,22 +247,16 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; mean = TRUE; - stdev = TRUE; - minus = TRUE; - plus = TRUE; - min = TRUE; - max = TRUE; - range = TRUE; - vld_count = TRUE; - frequency = TRUE; - nep = TRUE; - nmep = TRUE; + raw = TRUE; rank = TRUE; + pit = TRUE; + vld_count = TRUE; weight = FALSE; } diff --git a/src/basic/vx_config/config_constants.h b/src/basic/vx_config/config_constants.h index e4b4d4d75a..5cb03579d4 100644 --- a/src/basic/vx_config/config_constants.h +++ b/src/basic/vx_config/config_constants.h @@ -731,29 +731,17 @@ static const char conf_key_wvlt_plot[] = "wvlt_plot"; // Ensemble-Stat specific parameter key names // -static const char conf_key_ens[] = "ens"; -static const char conf_key_ens_field[] = "ens.field"; -static const char conf_key_ens_ens_thresh[] = "ens.ens_thresh"; -static const char conf_key_ens_vld_thresh[] = "ens.vld_thresh"; +static const char conf_key_fcst_ens_thresh[] = "fcst.ens_thresh"; +static const char conf_key_fcst_vld_thresh[] = "fcst.vld_thresh"; static const char conf_key_nc_var_str[] = "nc_var_str"; static const char conf_key_nbrhd_prob[] = "nbrhd_prob"; static const char conf_key_nmep_smooth[] = "nmep_smooth"; static const char conf_key_skip_const[] = "skip_const"; static const char conf_key_rng_type[] = "rng.type"; static const char conf_key_rng_seed[] = "rng.seed"; -static const char conf_key_ensemble_flag[] = "ensemble_flag"; -static const char conf_key_mean_flag[] = "mean"; -static const char conf_key_stdev_flag[] = "stdev"; -static const char conf_key_minus_flag[] = "minus"; -static const char conf_key_plus_flag[] = "plus"; -static const char conf_key_min_flag[] = "min"; -static const char conf_key_max_flag[] = "max"; -static const char conf_key_range_flag[] = "range"; -static const char conf_key_vld_count_flag[] = "vld_count"; -static const char conf_key_frequency_flag[] = "frequency"; -static const char conf_key_nep_flag[] = "nep"; -static const char conf_key_nmep_flag[] = "nmep"; +static const char conf_key_nc_orank_flag[] = "nc_orank_flag"; static const char conf_key_rank_flag[] = "rank"; +static const char conf_key_pit_flag[] = "pit"; static const char conf_key_ssvar_bin[] = "ens_ssvar_bin_size"; static const char conf_key_phist_bin[] = "ens_phist_bin_size"; static const char conf_key_prob_cat_thresh[] = "prob_cat_thresh"; @@ -768,7 +756,23 @@ static const char conf_key_inst_bias_offset[] = "inst_bias_offset"; // Gen-Ens-Prod specific parameter key names // -static const char conf_key_normalize[] = "normalize"; +static const char conf_key_ens[] = "ens"; +static const char conf_key_ens_field[] = "ens.field"; +static const char conf_key_ens_ens_thresh[] = "ens.ens_thresh"; +static const char conf_key_ens_vld_thresh[] = "ens.vld_thresh"; +static const char conf_key_normalize[] = "normalize"; +static const char conf_key_ensemble_flag[] = "ensemble_flag"; +static const char conf_key_mean_flag[] = "mean"; +static const char conf_key_stdev_flag[] = "stdev"; +static const char conf_key_minus_flag[] = "minus"; +static const char conf_key_plus_flag[] = "plus"; +static const char conf_key_min_flag[] = "min"; +static const char conf_key_max_flag[] = "max"; +static const char conf_key_range_flag[] = "range"; +static const char conf_key_vld_count_flag[] = "vld_count"; +static const char conf_key_frequency_flag[] = "frequency"; +static const char conf_key_nep_flag[] = "nep"; +static const char conf_key_nmep_flag[] = "nmep"; // Distribution options static const char conf_val_normal[] = "NORMAL"; diff --git a/src/basic/vx_util/data_plane.cc b/src/basic/vx_util/data_plane.cc index 618627dd63..bde7f982bc 100644 --- a/src/basic/vx_util/data_plane.cc +++ b/src/basic/vx_util/data_plane.cc @@ -69,6 +69,51 @@ DataPlane & DataPlane::operator=(const DataPlane &d) { /////////////////////////////////////////////////////////////////////////////// +DataPlane & DataPlane::operator+=(const DataPlane &d) { + const char *method_name = "DataPlane::operator+=(const DataPlane &) -> "; + + // Check for matching dimensions + if(Nx != d.Nx || Ny != d.Ny) { + mlog << Error << "\n" << method_name + << "the dimensions do not match: (" + << Nx << ", " << Ny << ") != (" + << d.Nx << ", " << d.Ny << ")\n\n"; + exit(1); + } + + // Increment values, checking for bad data + double v; + for(int i=0; i & buf(); @@ -187,6 +189,8 @@ class DataPlaneArray { ~DataPlaneArray(); DataPlaneArray(const DataPlaneArray &); DataPlaneArray & operator=(const DataPlaneArray &); + DataPlaneArray & operator+=(const DataPlaneArray &); + DataPlaneArray & operator/=(const double); void clear(); diff --git a/src/libcode/vx_statistics/met_stats.cc b/src/libcode/vx_statistics/met_stats.cc index cd1443fac6..15c69df188 100644 --- a/src/libcode/vx_statistics/met_stats.cc +++ b/src/libcode/vx_statistics/met_stats.cc @@ -915,50 +915,69 @@ void CNTInfo::compute_ci() { cv_chi2_u = chi2_cdf_inv(1.0 - (alpha[i]/2.0), n-1); // - // Compute confidence interval for forecast mean using VIF + // Check for bad data // - v = fbar.vif*fstdev.v*fstdev.v; - fbar.v_ncl[i] = fbar.v + cv_normal_l*sqrt(v)/sqrt((double) n); - fbar.v_ncu[i] = fbar.v + cv_normal_u*sqrt(v)/sqrt((double) n); - - // - // Compute confidence interval for forecast standard deviation, - // assuming normality of the forecast values - // - v = (n-1)*fstdev.v*fstdev.v/cv_chi2_u; - if(v < 0) fstdev.v_ncl[i] = bad_data_double; - else fstdev.v_ncl[i] = sqrt(v); - - v = (n-1)*fstdev.v*fstdev.v/cv_chi2_l; - if(v < 0) fstdev.v_ncu[i] = bad_data_double; - else fstdev.v_ncu[i] = sqrt(v); + if(is_bad_data(fstdev.v)) { + fbar.v_ncl[i] = fbar.v_ncu[i] = bad_data_double; + fstdev.v_ncl[i] = fstdev.v_ncu[i] = bad_data_double; + } + else { - // - // Compute confidence interval for observation mean using VIF - // - v = obar.vif*ostdev.v*ostdev.v; - obar.v_ncl[i] = obar.v + cv_normal_l*sqrt(v)/sqrt((double) n); - obar.v_ncu[i] = obar.v + cv_normal_u*sqrt(v)/sqrt((double) n); + // + // Compute confidence interval for forecast mean using VIF + // + v = fbar.vif*fstdev.v*fstdev.v; + fbar.v_ncl[i] = fbar.v + cv_normal_l*sqrt(v)/sqrt((double) n); + fbar.v_ncu[i] = fbar.v + cv_normal_u*sqrt(v)/sqrt((double) n); + + // + // Compute confidence interval for forecast standard deviation, + // assuming normality of the forecast values + // + v = (n-1)*fstdev.v*fstdev.v/cv_chi2_u; + if(v < 0) fstdev.v_ncl[i] = bad_data_double; + else fstdev.v_ncl[i] = sqrt(v); + + v = (n-1)*fstdev.v*fstdev.v/cv_chi2_l; + if(v < 0) fstdev.v_ncu[i] = bad_data_double; + else fstdev.v_ncu[i] = sqrt(v); + } // - // Compute confidence interval for observation standard deviation - // assuming normality of the observation values + // Check for bad data // - v = (n-1)*ostdev.v*ostdev.v/cv_chi2_u; - if(v < 0) ostdev.v_ncl[i] = bad_data_double; - else ostdev.v_ncl[i] = sqrt(v); + if(is_bad_data(ostdev.v)) { + obar.v_ncl[i] = obar.v_ncu[i] = bad_data_double; + ostdev.v_ncl[i] = ostdev.v_ncu[i] = bad_data_double; + } + else { - v = (n-1)*ostdev.v*ostdev.v/cv_chi2_l; - if(v < 0) ostdev.v_ncu[i] = bad_data_double; - else ostdev.v_ncu[i] = sqrt(v); + // + // Compute confidence interval for observation mean using VIF + // + v = obar.vif*ostdev.v*ostdev.v; + obar.v_ncl[i] = obar.v + cv_normal_l*sqrt(v)/sqrt((double) n); + obar.v_ncu[i] = obar.v + cv_normal_u*sqrt(v)/sqrt((double) n); + + // + // Compute confidence interval for observation standard deviation + // assuming normality of the observation values + // + v = (n-1)*ostdev.v*ostdev.v/cv_chi2_u; + if(v < 0) ostdev.v_ncl[i] = bad_data_double; + else ostdev.v_ncl[i] = sqrt(v); + + v = (n-1)*ostdev.v*ostdev.v/cv_chi2_l; + if(v < 0) ostdev.v_ncu[i] = bad_data_double; + else ostdev.v_ncu[i] = sqrt(v); + } // // Compute confidence interval for the pearson correlation coefficient // if(is_bad_data(pr_corr.v) || n <= 3 || is_eq(pr_corr.v, 1.0) || is_eq(pr_corr.v, -1.0)) { - pr_corr.v_ncl[i] = bad_data_double; - pr_corr.v_ncu[i] = bad_data_double; + pr_corr.v_ncl[i] = pr_corr.v_ncu[i] = bad_data_double; } else { v = 0.5*log((1 + pr_corr.v)/(1 - pr_corr.v)); @@ -973,8 +992,7 @@ void CNTInfo::compute_ci() { // if(is_bad_data(anom_corr.v) || n <= 3 || is_eq(anom_corr.v, 1.0) || is_eq(anom_corr.v, -1.0)) { - anom_corr.v_ncl[i] = bad_data_double; - anom_corr.v_ncu[i] = bad_data_double; + anom_corr.v_ncl[i] = anom_corr.v_ncu[i] = bad_data_double; } else { v = 0.5*log((1 + anom_corr.v)/(1 - anom_corr.v)); @@ -985,22 +1003,32 @@ void CNTInfo::compute_ci() { } // - // Compute confidence interval for mean error using VIF - // - v = me.vif*estdev.v*estdev.v; - me.v_ncl[i] = me.v + cv_normal_l*sqrt(v)/sqrt((double) n); - me.v_ncu[i] = me.v + cv_normal_u*sqrt(v)/sqrt((double) n); - + // Check for bad data // - // Compute confidence interval for the error standard deviation - // - v = (n-1)*estdev.v*estdev.v/cv_chi2_u; - if(v < 0) estdev.v_ncl[i] = bad_data_double; - else estdev.v_ncl[i] = sqrt(v); + if(is_bad_data(estdev.v)) { + me.v_ncl[i] = me.v_ncu[i] = bad_data_double; + estdev.v_ncl[i] = estdev.v_ncu[i] = bad_data_double; + } + else { - v = (n-1)*estdev.v*estdev.v/cv_chi2_l; - if(v < 0) estdev.v_ncu[i] = bad_data_double; - else estdev.v_ncu[i] = sqrt(v); + // + // Compute confidence interval for mean error using VIF + // + v = me.vif*estdev.v*estdev.v; + me.v_ncl[i] = me.v + cv_normal_l*sqrt(v)/sqrt((double) n); + me.v_ncu[i] = me.v + cv_normal_u*sqrt(v)/sqrt((double) n); + + // + // Compute confidence interval for the error standard deviation + // + v = (n-1)*estdev.v*estdev.v/cv_chi2_u; + if(v < 0) estdev.v_ncl[i] = bad_data_double; + else estdev.v_ncl[i] = sqrt(v); + + v = (n-1)*estdev.v*estdev.v/cv_chi2_l; + if(v < 0) estdev.v_ncu[i] = bad_data_double; + else estdev.v_ncu[i] = sqrt(v); + } } // end for i diff --git a/src/tools/core/ensemble_stat/ensemble_stat.cc b/src/tools/core/ensemble_stat/ensemble_stat.cc index e437bc0ca3..6d3309289e 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -66,7 +66,8 @@ // 034 01/14/21 McCabe MET #1695 All members in one file. // 035 02/15/22 Halley Gotway MET #1583 Add HiRA option. // 036 02/20/22 Halley Gotway MET #1259 Write probabilistic statistics. -// 037 07/06/22 Howard Soh METplus-Internal #19 Rename main to met_main +// 037 07/06/22 Howard Soh METplus-Internal #19 Rename main to met_main. +// 038 09/06/22 Halley Gotway MET #1908 Remove ensemble processing logic. // //////////////////////////////////////////////////////////////////////// @@ -105,7 +106,6 @@ using namespace std; static void process_command_line (int, char **); static void process_grid (const Grid &); static void process_n_vld (); -static void process_ensemble (); static void process_vx (); static bool get_data_plane (const char *, GrdFileType, VarInfo *, DataPlane &, bool do_regrid); @@ -113,9 +113,8 @@ static bool get_data_plane_array (const char *, GrdFileType, VarInfo *, DataPlaneArray &, bool do_regrid); static void process_point_vx (); -static void process_point_climo (); static void process_point_obs (int); -static int process_point_ens (int, int &); +static bool process_point_ens (int, int, DataPlaneArray &); static void process_point_scores (); static void process_grid_vx (); @@ -133,11 +132,6 @@ static void do_rps (const EnsembleStatVxOpt &, const SingleThresh &, const PairDataEnsemble *); -static void clear_counts(); -static void track_counts(EnsVarInfo *, const DataPlane &, bool); - -static ConcatString get_ens_mn_var_name(int); - static void setup_nc_file (unixtime, const char *); static void setup_txt_files (); static void setup_table (AsciiTable &); @@ -151,14 +145,6 @@ static void do_pct_cat_thresh(const EnsembleStatVxOpt &, const PairDataEnsemble static void do_pct_cdp_thresh(const EnsembleStatVxOpt &, const PairDataEnsemble &); static void write_pct_info(const EnsembleStatVxOpt &, const PCTInfo *, int, bool); -static void write_ens_nc(EnsVarInfo *, int, DataPlane &); -static void write_ens_var_float(EnsVarInfo *, float *, const DataPlane &, - const char *, const char *); -static void write_ens_var_int(EnsVarInfo *, int *, const DataPlane &, - const char *, const char *); -static void write_ens_data_plane(EnsVarInfo *, const DataPlane &, const DataPlane &, - const char *, const char *); - static void write_orank_nc(PairDataEnsemble &, DataPlane &, int, int, int); static void write_orank_var_float(int, int, int, float *, DataPlane &, const char *, const char *); @@ -195,11 +181,8 @@ int met_main(int argc, char *argv[]) { // Check for valid ensemble data process_n_vld(); - // Process the ensemble fields - process_ensemble(); - - // Only perform verification if requested - if(vx_flag) process_vx(); + // Perform verification + process_vx(); // Close the text files and deallocate memory clean_up(); @@ -316,22 +299,32 @@ void process_command_line(int argc, char **argv) { exit(1); } - // Copy ensemble file list to forecast file list - fcst_file_list = ens_file_list; - // Append the control member, if specified if(ctrl_file.nonempty()) { - if(ens_file_list.has(ctrl_file) && n_ens_files != 1) { + if(n_ens_files == 1 && !ens_file_list.has(ctrl_file)) { + mlog << Error << "\nprocess_command_line() -> " + << "when reading all ensemble members from the same file, " + << "the control member must be in that file as well: " + << ctrl_file << "\n\n"; + exit(1); + } + else if(n_ens_files > 1 && ens_file_list.has(ctrl_file)) { mlog << Error << "\nprocess_command_line() -> " << "the ensemble control file should not appear in the list " - << "of ensemble member files:\n" << ctrl_file << "\n\n"; + << "of ensemble member files: " << ctrl_file << "\n\n"; exit(1); } - // Add control member file to end of the forecast file list - fcst_file_list.add(ctrl_file.c_str()); - ctrl_file_index = fcst_file_list.n()-1; + // Store control member file information + if(n_ens_files == 1) { + ctrl_file_index = 0; + } + else { + ens_file_list.add(ctrl_file.c_str()); + n_ens_files++; + ctrl_file_index = ens_file_list.n()-1; + } } // Check that the end_ut >= beg_ut @@ -363,7 +356,7 @@ void process_command_line(int argc, char **argv) { conf_info.read_config(default_config_file, config_file); // Get the ensemble file type from config, if present - etype = parse_conf_file_type(conf_info.conf.lookup_dictionary(conf_key_ens)); + etype = parse_conf_file_type(conf_info.conf.lookup_dictionary(conf_key_fcst)); // Read the first input ensemble file if(!(ens_mtddf = mtddf_factory.new_met_2d_data_file(ens_file_list[0].c_str(), etype))) { @@ -379,6 +372,14 @@ void process_command_line(int argc, char **argv) { // Use a variable index from var_name instead of GRIB code bool use_var_id = false; + // Observation files are required + if(!grid_obs_flag && !point_obs_flag) { + mlog << Error << "\nprocess_command_line() -> " + << "the \"-grid_obs\" or \"-point_obs\" command line option " + << "must be used at least once.\n\n"; + exit(1); + } + // Determine the input observation file type if(point_obs_flag) { otype = FileType_Gb1; @@ -407,19 +408,15 @@ void process_command_line(int argc, char **argv) { } // Process the configuration - conf_info.process_config(etype, otype, grid_obs_flag, point_obs_flag, use_var_id, &ens_file_list, &fcst_file_list, ctrl_file.nonempty()); + conf_info.process_config(etype, otype, grid_obs_flag, point_obs_flag, + use_var_id, &ens_file_list, ctrl_file.nonempty()); + + // Set output_nc_flag + out_nc_flag = (grid_obs_flag && !conf_info.nc_info.all_false()); // Set the model name shc.set_model(conf_info.model.c_str()); - // Allocate arrays to store threshold counts - thresh_cnt_na = new NumArray [conf_info.get_max_n_ens_thresh()]; - thresh_nbrhd_cnt_na = new NumArray * [conf_info.get_max_n_ens_thresh()]; - - for(i=0; i " - << "can't open input forecast file: " - << fcst_file_list[i] << "\n\n"; - fcst_file_vld.add(0); - } - else { - fcst_file_vld.add(1); - } - } - - // Set flag to indicate whether verification is to be performed - if((point_obs_flag || grid_obs_flag) && - (conf_info.get_n_vx() > 0) && - (conf_info.output_flag[i_ecnt] != STATOutputType_None || - conf_info.output_flag[i_rhist] != STATOutputType_None || - conf_info.output_flag[i_phist] != STATOutputType_None || - conf_info.output_flag[i_ssvar] != STATOutputType_None || - conf_info.output_flag[i_relp] != STATOutputType_None || - conf_info.output_flag[i_orank] != STATOutputType_None || - conf_info.output_flag[i_pct] != STATOutputType_None || - conf_info.output_flag[i_pstd] != STATOutputType_None || - conf_info.output_flag[i_pjc] != STATOutputType_None || - conf_info.output_flag[i_prc] != STATOutputType_None || - conf_info.output_flag[i_eclv] != STATOutputType_None)) vx_flag = true; - else vx_flag = false; - - // Process ensemble mean information - ens_mean_flag = false; - bool need_ens_mean = ( - conf_info.output_flag[i_ecnt] != STATOutputType_None || - conf_info.output_flag[i_orank] != STATOutputType_None || - conf_info.output_flag[i_ssvar] != STATOutputType_None); - // User-specified ensemble mean file - if(ens_mean_user.nonempty()) { - - if(!need_ens_mean) { - mlog << Warning << "\nprocess_command_line() -> " - << "ignoring input -ens_mean file because no ensemble " - << "mean is needed.\n\n"; - } - else if(!file_exists(ens_mean_user.c_str())) { + if(ens_mean_file.nonempty()) { + if(!file_exists(ens_mean_file.c_str())) { mlog << Warning << "\nprocess_command_line() -> " << "can't open input ensemble mean file: " - << ens_mean_user << "\n\n"; - ens_mean_user = ""; - } - else if(!vx_flag) { - mlog << Warning << "\nprocess_command_line() -> " - << "ignoring input -ens_mean file because no verification " - << "has been requested\n\n"; - } - else { - ens_mean_flag = true; - } - } - else if(need_ens_mean) { - - ens_mean_flag = true; - - if(!conf_info.nc_info.do_mean) { - mlog << Warning << "\nprocess_command_line() -> " - << "enabling NetCDF ensemble mean computation to be used " - << "in verification.\n\n"; - conf_info.nc_info.do_mean = true; + << ens_mean_file << "\n\n"; + ens_mean_file = ""; } } + // User-specified ensemble control file if(conf_info.control_id.nonempty() && ctrl_file.empty()) { mlog << Warning << "\nprocess_command_line() -> " << "control_id is set in the config file but " @@ -557,18 +492,7 @@ void process_grid(const Grid &fcst_grid) { // Parse regridding logic RegridInfo ri; - if(conf_info.ens_input.size() > 0) { - ri = conf_info.ens_input[0]->get_var_info()->regrid(); - } - else if(conf_info.get_n_vx() > 0) { - ri = conf_info.vx_opt[0].vx_pd.fcst_info->get_var_info()->regrid(); - } - else { - mlog << Error << "\nprocess_grid() -> " - << "at least one ensemble field or verification field must " - << "be provided!\n\n"; - exit(1); - } + ri = conf_info.vx_opt[0].vx_pd.fcst_info->get_var_info()->regrid(); // Read gridded observation data, if necessary if(ri.field == FieldType_Obs) { @@ -625,82 +549,27 @@ void process_n_vld() { DataPlane dp; DataPlaneArray dpa; VarInfo * var_info; - ConcatString ens_file, fcst_file; + ConcatString fcst_file; vector::const_iterator var_it; // Initialize - n_ens_vld.clear(); n_vx_vld.clear(); - // Loop through the ensemble fields to be processed - if(conf_info.ens_input.size() > 0) { - var_it = conf_info.ens_input.begin(); - n_ens_inputs = (*var_it)->inputs_n(); - } - else { - n_ens_inputs = 0; - } - - for(i_var=0; var_it != conf_info.ens_input.end(); var_it++, i_var++) { - - // Loop through the ensemble inputs - for(i_ens=n_vld=0; i_ens < n_ens_inputs; i_ens++) { - - // Get file and VarInfo to process - ens_file = (*var_it)->get_file(i_ens); - var_info = (*var_it)->get_var_info(i_ens); - - // Check for valid file - if(!ens_file_vld[(*var_it)->get_file_index(i_ens)]) continue; - - // Check for valid data - if(!get_data_plane(ens_file.c_str(), etype, - var_info, dp, false)) { - mlog << Warning << "\nprocess_n_vld() -> " - << "ensemble field \"" - << var_info->magic_str() - << "\" not found in file \"" << ens_file - << "\"\n\n"; - } - else { - - // Increment the valid counter - n_vld++; - } - } // end for i_ens - - // Check for enough valid data - if((double) n_vld/n_ens_inputs < conf_info.vld_ens_thresh) { - mlog << Error << "\nprocess_n_vld() -> " - << n_vld << " of " << n_ens_inputs - << " (" << (double)n_vld/n_ens_inputs << ")" - << " fields found for \"" << (*var_it)->get_var_info()->magic_str() - << "\" does not meet the threshold specified by \"" - << conf_key_ens_ens_thresh << "\" (" << conf_info.vld_ens_thresh - << ") in the configuration file.\n\n"; - exit(1); - } - - // Store the valid data count - n_ens_vld.add(n_vld); - - } // end for i_var - // Loop through the verification fields to be processed for(i_var=0; i_varinputs_n(); // Loop through the forecast inputs - for(i_ens=n_vld=0; i_ens < n_ens_inputs; i_ens++) { + for(i_ens=n_vld=0; i_ensget_file(i_ens); var_info = conf_info.vx_opt[i_var].vx_pd.fcst_info->get_var_info(i_ens); j = conf_info.vx_opt[i_var].vx_pd.fcst_info->get_file_index(i_ens); // Check for valid file - if(!fcst_file_vld[j]) continue; + if(!ens_file_vld[j]) continue; // Check for valid data fields. // Call data_plane_array to handle multiple levels. @@ -727,11 +596,11 @@ void process_n_vld() { if((double) n_vld/n_ens_inputs < conf_info.vld_ens_thresh) { mlog << Error << "\nprocess_n_vld() -> " << n_vld << " of " << n_ens_inputs - << " (" << (double)n_vld/n_ens_inputs << ")" + << " (" << (double) n_vld/n_ens_inputs << ")" << " forecast fields found for \"" << conf_info.vx_opt[i_var].vx_pd.fcst_info->get_var_info()->magic_str() << "\" does not meet the threshold specified by \"" - << conf_key_ens_ens_thresh << "\" (" << conf_info.vld_ens_thresh + << conf_key_fcst_ens_thresh << "\" (" << conf_info.vld_ens_thresh << ") in the configuration file.\n\n"; exit(1); } @@ -855,138 +724,23 @@ bool get_data_plane_array(const char *infile, GrdFileType ftype, //////////////////////////////////////////////////////////////////////// -void process_ensemble() { - int i_var, i_ens, j; - bool reset; - DataPlane ens_dp, ctrl_dp; - unixtime max_init_ut = bad_data_ll; - VarInfo * var_info; - VarInfo * ctrl_info; - ConcatString ens_file; - - vector::const_iterator var_it = conf_info.ens_input.begin(); - - // Loop through each of the ensemble fields to be processed - for(i_var=0; var_it != conf_info.ens_input.end(); var_it++, i_var++) { - - var_info = (*var_it)->get_var_info(); - - mlog << Debug(2) << "\n" << sep_str << "\n\n" - << "Processing ensemble field: " - << (*var_it)->raw_magic_str << "\n"; - - // Loop through each of the input forecast files/variables - for(i_ens=0,reset=true; i_ens < (*var_it)->inputs_n(); i_ens++) { - - j = (*var_it)->get_file_index(i_ens); - - // Skip bad data files - if(!ens_file_vld[j]) { continue; } - - // get file and VarInfo to process - ens_file = (*var_it)->get_file(i_ens); - var_info = (*var_it)->get_var_info(i_ens); - - mlog << Debug(3) << "\n" - << "Reading field: " - << var_info->magic_str() << "\n"; - - // Read the current field - if(!get_data_plane(ens_file.c_str(), etype, - var_info, ens_dp, true)) { continue; } - - // Create a NetCDF file to store the ensemble output - if(nc_out == (NcFile *) 0) { - setup_nc_file(ens_dp.valid(), "_ens.nc"); - } - - // Reset the running sums and counts - if(reset) { - clear_counts(); - reset = false; - - // Read ensemble control member data, if provided - if(ctrl_file.nonempty()) { - ctrl_info = (*var_it)->get_ctrl(i_ens); - - mlog << Debug(3) << "\n" - << "Reading control field: " - << ctrl_info->magic_str() << "\n"; - - // Error out if missing - if (!get_data_plane(ctrl_file.c_str(), etype, - ctrl_info, ctrl_dp, true)) { - mlog << Error << "\nprocess_ensemble() -> " - << "control member ensemble field \"" - << ctrl_info->magic_str() - << "\" not found in file \"" << ctrl_file << "\"\n\n"; - exit(1); - } - - // Apply current data to the running sums and counts - track_counts(*var_it, ctrl_dp, true); - } - } - - // Apply current data to the running sums and counts - track_counts(*var_it, ens_dp, false); - - // Keep track of the maximum initialization time - if(is_bad_data(max_init_ut) || ens_dp.init() > max_init_ut) { - max_init_ut = ens_dp.init(); - } - - } // end for i_ens - - // Write out the ensemble information to a NetCDF file - ens_dp.set_init(max_init_ut); - write_ens_nc(*var_it, i_var, ens_dp); - - // Store the ensemble mean output file - ens_mean_file = out_nc_file_list[out_nc_file_list.n() - 1]; - - } // end for var_it - - // Close the output NetCDF file - if(nc_out) { - delete nc_out; - nc_out = (NcFile *) 0; - } - - return; -} - -//////////////////////////////////////////////////////////////////////// - void process_vx() { - if(conf_info.get_n_vx() > 0) { + // Process masks Grids and Polylines in the config file + conf_info.process_masks(grid); - if(point_obs_file_list.n() == 0 && - grid_obs_file_list.n() == 0) { - mlog << Error << "\nprocess_vx() -> " - << "when \"fcst.field\" is non-empty, you must use " - << "\"-point_obs\" and/or \"-grid_obs\" to specify the " - << "verifying observations.\n\n"; - exit(1); - } + // Determine the index of the control member in list of data values + int ctrl_data_index = (is_bad_data(ctrl_file_index) ? + bad_data_int : ens_file_vld.sum()-1); - // Process masks Grids and Polylines in the config file - conf_info.process_masks(grid); + // Setup the PairDataEnsemble objects + conf_info.set_vx_pd(n_vx_vld, ctrl_data_index); - // Determine the index of the control member in list of data values - int ctrl_data_index = (is_bad_data(ctrl_file_index) ? - bad_data_int : fcst_file_vld.sum()-1); + // Process the point observations + if(point_obs_flag) process_point_vx(); - // Setup the PairDataEnsemble objects - conf_info.set_vx_pd(n_vx_vld, ctrl_data_index); - - // Process the point observations - if(point_obs_flag) process_point_vx(); - - // Process the gridded observations - if(grid_obs_flag) process_grid_vx(); - } + // Process the gridded observations + if(grid_obs_flag) process_grid_vx(); return; } @@ -994,19 +748,22 @@ void process_vx() { //////////////////////////////////////////////////////////////////////// void process_point_vx() { - int i, i_file, n_miss; + int i, j, i_file, n_miss; unixtime beg_ut, end_ut; + DataPlaneArray fcst_dpa, emn_dpa; + DataPlaneArray cmn_dpa, csd_dpa; - // Set observation time window for each verification task + // Loop through each of the fields to be verified for(i=0; iget_var_info()->magic_str() << ".\n"; + + // Store climatology information + conf_info.vx_opt[i].vx_pd.set_climo_mn_dpa(cmn_dpa); + conf_info.vx_opt[i].vx_pd.set_climo_sd_dpa(csd_dpa); + } // Process each point observation NetCDF file - for(i=0; iinputs_n(); i++) { + // Loop through each of the fields to be verified + for(i=0; iget_file_index(i); + // Initialize + emn_dpa.clear(); - // If the current forecast file is valid, process it - if(!fcst_file_vld[i_file]) { - n_miss++; - continue; - } - else { - process_point_ens(i, n_miss); - } + // Loop through the ensemble inputs + for(j=0, n_miss=0; jinputs_n(); j++) { - } // end for i + i_file = conf_info.vx_opt[i].vx_pd.fcst_info->get_file_index(j); - // Process the ensemble mean, if necessary - if(ens_mean_flag) process_point_ens(-1, n_miss); + // If the current forecast file is valid, process it + if(!ens_file_vld[i_file]) { + n_miss++; + continue; + } + else if(!process_point_ens(i, j, fcst_dpa)) { + n_miss++; + continue; + } - // Compute the scores and write them out - process_point_scores(); + // Store ensemble member data + conf_info.vx_opt[i].vx_pd.set_fcst_dpa(fcst_dpa); - return; -} + // Compute ensemble values for this member + conf_info.vx_opt[i].vx_pd.add_ens(j-n_miss, false, grid); -//////////////////////////////////////////////////////////////////////// + // Running sum for the ensemble mean + if(emn_dpa.n_planes() == 0) emn_dpa = fcst_dpa; + else emn_dpa += fcst_dpa; -void process_point_climo() { - int i; - DataPlaneArray cmn_dpa, csd_dpa; + } // end for j - // Loop through each of the fields to be verified and extract - // the climatology fields for verification - for(i=0; iget_var_info(); + + // Read the gridded data from the ensemble mean file + if(!get_data_plane_array(ens_mean_file.c_str(), info->file_type(), info, + emn_dpa, true)) { + mlog << Error << "\nprocess_point_vx() -> " + << "trouble reading the ensemble mean field \"" + << info->magic_str() << "\" from file \"" + << ens_mean_file << "\"\n\n"; + exit(1); + } + + // Dump out the number of levels found + mlog << Debug(2) << "For " << info->magic_str() + << " found " << emn_dpa.n_planes() << " forecast levels.\n"; + + } + // Otherwise, compute the ensemble mean from the members + else { + + mlog << Debug(2) << "Computing the ensemble mean from the members.\n"; + + int n = conf_info.vx_opt[i].vx_pd.fcst_info->inputs_n() - n_miss; + + if(n <= 0) { + mlog << Error << "\nprocess_point_vx() -> " + << "all inputs are missing!\n\n"; + exit(1); + } + + // Convert running sums to a mean + emn_dpa /= (double) n; + } + + // Store ensemble mean data + conf_info.vx_opt[i].vx_pd.set_fcst_dpa(emn_dpa); + + // Compute ensemble mean values + conf_info.vx_opt[i].vx_pd.add_ens(-1, true, grid); } // end for i + // Compute the scores and write them out + process_point_scores(); + return; } @@ -1258,78 +1063,29 @@ void process_point_obs(int i_nc) { //////////////////////////////////////////////////////////////////////// -int process_point_ens(int i_ens, int &n_miss) { - int i; - DataPlaneArray fcst_dpa; - NumArray fcst_lvl_na; - VarInfo *info = (VarInfo *) 0; - VarInfoNcMet ens_mean_info; - - ConcatString ens_file; - bool is_ens_mean = (-1 == i_ens); - const char *file_type = (is_ens_mean ? "mean" : "ensemble"); +bool process_point_ens(int i_vx, int i_ens, DataPlaneArray &fcst_dpa) { - // get file index from first verification for logging - int i_file = conf_info.vx_opt[0].vx_pd.fcst_info->get_file_index(i_ens); + // Initialize + fcst_dpa.clear(); - // Determine the correct file to process - if(!is_ens_mean) ens_file = ConcatString(fcst_file_list[i_file]); - else ens_file = (ens_mean_user.empty() ? - ens_mean_file : ens_mean_user); + // Get file based on current vx and ensemble index + ConcatString ens_file = conf_info.vx_opt[i_vx].vx_pd.fcst_info->get_file(i_ens); mlog << Debug(2) << "\n" << sep_str << "\n\n" - << "Processing " << file_type << " file: " << ens_file + << "Processing ensemble member file: " << ens_file << (i_ens == ctrl_file_index ? " (control)\n" : "\n"); - // Loop through each of the fields to be verified and extract - // the forecast fields for verification - for(i=0; iget_var_info(i_ens); - } - - // If not processing mean, get file based on current vx and ensemble index - if(!is_ens_mean) ens_file = conf_info.vx_opt[i].vx_pd.fcst_info->get_file(i_ens); - - // Read the gridded data from the input forecast file - if(!get_data_plane_array(ens_file.c_str(), info->file_type(), info, - fcst_dpa, true)) { - - // Error out if unable to read the ensemble mean - if(is_ens_mean) { - mlog << Error << "\nprocess_point_ens() -> " - << "trouble reading the ensemble mean field \"" - << info->magic_str() << "\" from file \"" - << ens_file << "\"\n\n"; - exit(1); - } - - n_miss++; - continue; - } - - // Dump out the number of levels found - mlog << Debug(2) << "For " << info->magic_str() - << " found " << fcst_dpa.n_planes() << " forecast levels.\n"; + VarInfo *info = conf_info.vx_opt[i_vx].vx_pd.fcst_info->get_var_info(i_ens); - // Store information for the raw forecast fields - conf_info.vx_opt[i].vx_pd.set_fcst_dpa(fcst_dpa); + // Read the gridded data from the input forecast file + bool status = get_data_plane_array(ens_file.c_str(), info->file_type(), info, + fcst_dpa, true); - // Compute forecast values for this ensemble member - conf_info.vx_opt[i].vx_pd.add_ens(i_ens-n_miss, is_ens_mean, grid); + // Dump out the number of levels found + mlog << Debug(2) << "For " << info->magic_str() + << " found " << fcst_dpa.n_planes() << " forecast levels.\n"; - } // end for i - - return(0); + return(status); } //////////////////////////////////////////////////////////////////////// @@ -1340,7 +1096,8 @@ void process_point_scores() { ConcatString cs; int i, j, k, l; - mlog << Debug(2) << "\n" << sep_str << "\n\n"; + mlog << Debug(2) << "\n" << sep_str << "\n\n" + << "Verifying against point observations.\n"; // Create output text files as requested in the config file setup_txt_files(); @@ -1457,7 +1214,8 @@ void process_grid_vx() { VarInfo * var_info; ConcatString fcst_file; - mlog << Debug(2) << "\n" << sep_str << "\n\n"; + mlog << Debug(2) << "\n" << sep_str << "\n\n" + << "Verifying against gridded analyses.\n"; // Set the obtype column shc.set_obtype(conf_info.obtype.c_str()); @@ -1470,6 +1228,9 @@ void process_grid_vx() { // Loop through each of the fields to be verified for(i=0; iget_file(j); // If the current ensemble file is valid, read the field - if(fcst_file_vld[i_file]) { + if(ens_file_vld[i_file]) { found = get_data_plane(fcst_file.c_str(), etype, - var_info, - fcst_dp[j], true); + var_info, fcst_dp[j], true); } else { found = false; } + // Running sum for the ensemble mean + if(found) { + if(emn_dp.is_empty()) emn_dp = fcst_dp[j]; + else emn_dp += fcst_dp[j]; + } // Count the number of missing files - if(!found) { + else { n_miss++; continue; } } // end for j + // Read the ensemble mean from a file + if(ens_mean_file.nonempty()) { + + mlog << Debug(2) << "Processing ensemble mean file: " + << ens_mean_file << "\n"; + + VarInfo *info = conf_info.vx_opt[i].vx_pd.fcst_info->get_var_info(); + + // Read the gridded data from the mean file + found = get_data_plane(ens_mean_file.c_str(), FileType_None, + info, emn_dp, true); + + if(!found) { + mlog << Error << "\nprocess_grid_vx() -> " + << "trouble reading ensemble mean field \"" + << info->magic_str() << "\" from file \"" + << ens_mean_file << "\"\n\n"; + exit(1); + } + } + // Otherwise, compute the ensemble mean from the members + else { + + mlog << Debug(2) << "Computing the ensemble mean from the members.\n"; + + int n = conf_info.vx_opt[i].vx_pd.fcst_info->inputs_n() - n_miss; + + if(n <= 0) { + mlog << Error << "\nprocess_grid_vx() -> " + << "all inputs are missing!\n\n"; + exit(1); + } + + // Convert running sums to a mean + emn_dp /= (double) n; + } + // Read climatology data cmn_dp = read_climo_data_plane( conf_info.conf.lookup_array(conf_key_climo_mean_field, false), @@ -1584,9 +1386,9 @@ void process_grid_vx() { // If requested in the config file, create a NetCDF file to store // the verification matched pairs - if(conf_info.nc_info.do_orank && - nc_out == (NcFile *) 0) + if(out_nc_flag && nc_out == (NcFile *) 0) { setup_nc_file(fcst_dp[j].valid(), "_orank.nc"); + } // Read the observation file for(j=0, n_miss=0; jget_var_info(); - } - - // Read the gridded data from the mean file - found = get_data_plane(mn_file.c_str(), FileType_None, - info, emn_dp, true); - - if(!found) { - mlog << Error << "\nprocess_grid_vx() -> " - << "trouble reading ensemble mean field \"" - << info->magic_str() << "\" from file \"" - << mn_file << "\"\n\n"; - exit(1); - } - } - // Loop through and apply each of the smoothing operations for(j=0; jcat_ta.n(); - SingleThresh *thr_buf = ens_info->cat_ta.buf(); - - // Increment counts for each grid point - for(i=0; i= max_na.buf()[i] || is_bad_data(max_na.buf()[i])) max_na.buf()[i] = v; - - // Standard deviation sum, sum of squares, and count, excluding control member - if(!is_ctrl) { - stdev_sum_na.buf()[i] += v; - stdev_ssq_na.buf()[i] += v*v; - stdev_cnt_na.buf()[i] += 1; - } - - // Event frequency - for(j=0; j 0 - if(conf_info.nc_info.do_nmep) { - DataPlane frac_dp; - - // Loop over thresholds - for(i=0; i 0) thresh_nbrhd_cnt_na[i][j].inc(k, 1); - } // end for k - - } // end for j - } // end for i - } // end if do_nmep - - return; -} - -//////////////////////////////////////////////////////////////////////// - -ConcatString get_ens_mn_var_name(int i_vx) { - ConcatString cs; - - cs << conf_info.vx_opt[i_vx].vx_pd.fcst_info->get_var_info()->name_attr() << "_" - << conf_info.vx_opt[i_vx].vx_pd.fcst_info->get_var_info()->level_attr() - << "_ENS_MEAN"; - cs.replace(",", "_", false); - cs.replace("*", "all", false); - mlog << Debug(4) << "Generated mean field: " << cs << "\n"; - - return(cs); -} - -//////////////////////////////////////////////////////////////////////// - void setup_nc_file(unixtime valid_ut, const char *suffix) { - ConcatString out_nc_file; // Create output NetCDF file name build_outfile_name(ens_valid_ut, suffix, out_nc_file); @@ -2118,9 +1770,6 @@ void setup_nc_file(unixtime valid_ut, const char *suffix) { conf_info.grid_weight_flag, wgt_dp); } - // Append to the list of output files - out_nc_file_list.add(out_nc_file); - return; } @@ -2799,347 +2448,6 @@ void write_pct_info(const EnsembleStatVxOpt &vx_opt, //////////////////////////////////////////////////////////////////////// -void write_ens_nc(EnsVarInfo * ens_info, int i_var, DataPlane &ens_dp) { - int i, j, k, l; - double t, v; - char type_str[max_str_len]; - DataPlane prob_dp, nbrhd_dp; - - // Allocate memory for storing ensemble data - float * ens_mean = new float [nxy]; - float * ens_stdev = new float [nxy]; - float * ens_minus = new float [nxy]; - float * ens_plus = new float [nxy]; - float * ens_min = new float [nxy]; - float * ens_max = new float [nxy]; - float * ens_range = new float [nxy]; - int * ens_vld = new int [nxy]; - - // Store the threshold for the ratio of valid data points - t = conf_info.vld_data_thresh; - - // Store the data - for(i=0; icat_ta.n(); i++) { - - // Initialize - prob_dp.erase(); - - // Compute the ensemble relative frequency - for(j=0; jcat_ta[i].get_abbr_str().contents().c_str()); - write_ens_data_plane(ens_info, prob_dp, ens_dp, type_str, - "Ensemble Relative Frequency"); - } - - // Write the neighborhood ensemble probability - if(conf_info.nc_info.do_nep) { - GaussianInfo info; - - // Loop over the neighborhoods - for(j=0; jcat_ta[i].get_abbr_str().contents().c_str(), - interpmthd_to_string(InterpMthd_Nbrhd).c_str(), - conf_info.nbrhd_prob.width[j]*conf_info.nbrhd_prob.width[j]); - write_ens_data_plane(ens_info, nbrhd_dp, ens_dp, type_str, - "Neighborhood Ensemble Probability"); - } // end for j - } // end if do_nep - } // end for i - } // end if - - // Add the neighborhood maximum ensemble probabilities, if requested - if(conf_info.nc_info.do_nmep) { - - prob_dp.set_size(grid.nx(), grid.ny()); - - // Loop through each threshold - for(i=0; icat_ta.n(); i++) { - - // Loop through each neigbhorhood size - for(j=0; jcat_ta[i].get_abbr_str().contents().c_str(), - interpmthd_to_string(InterpMthd_Nbrhd).c_str(), - conf_info.nbrhd_prob.width[j]*conf_info.nbrhd_prob.width[j], - conf_info.nmep_smooth.method[k].c_str(), - conf_info.nmep_smooth.width[k]*conf_info.nmep_smooth.width[k]); - write_ens_data_plane(ens_info, nbrhd_dp, ens_dp, type_str, - "Neighborhood Maximum Ensemble Probability"); - } // end for k - } // end for j - } // end for i - } // end if do_nep - - // Deallocate and clean up - if(ens_mean) { delete [] ens_mean; ens_mean = (float *) 0; } - if(ens_stdev) { delete [] ens_stdev; ens_stdev = (float *) 0; } - if(ens_minus) { delete [] ens_minus; ens_minus = (float *) 0; } - if(ens_plus) { delete [] ens_plus; ens_plus = (float *) 0; } - if(ens_min) { delete [] ens_min; ens_min = (float *) 0; } - if(ens_max) { delete [] ens_max; ens_max = (float *) 0; } - if(ens_range) { delete [] ens_range; ens_range = (float *) 0; } - if(ens_vld) { delete [] ens_vld; ens_vld = (int *) 0; } - - return; -} - -//////////////////////////////////////////////////////////////////////// - -void write_ens_var_float(EnsVarInfo * ens_info, float *ens_data, const DataPlane &dp, - const char *type_str, - const char *long_name_str) { - NcVar ens_var; - ConcatString ens_var_name, var_str, name_str, cs; - - // Append nc_pairs_var_str config file entry - cs = ens_info->nc_var_str; - if(cs.length() > 0) var_str << "_" << cs; - - // Construct the variable name - ens_var_name << cs_erase - << ens_info->get_var_info()->name_attr() << "_" - << ens_info->get_var_info()->level_attr() - << var_str << "_" << type_str; - - // Skip variable names that have already been written - if(nc_ens_var_sa.has(ens_var_name)) return; - - // Otherwise, add to the list of previously defined variables - nc_ens_var_sa.add(ens_var_name); - ens_var = add_var(nc_out, (string)ens_var_name, ncFloat, lat_dim, lon_dim); - - // - // Construct the variable name attribute - // For the ensemble mean, just use the variable name. - // For all other fields, append the field type. - // - if(strcmp(type_str, "ENS_MEAN") == 0) { - name_str << cs_erase - << ens_info->get_var_info()->name_attr(); - } - else { - name_str << cs_erase - << ens_info->get_var_info()->name_attr() << "_" - << type_str; - } - - // Add the variable attributes - add_var_att_local(ens_info->get_var_info(), &ens_var, false, dp, - name_str.c_str(), long_name_str); - - // Write the data - if(!put_nc_data_with_dims(&ens_var, &ens_data[0], grid.ny(), grid.nx())) { - mlog << Error << "\nwrite_ens_var_float() -> " - << "error in ens_var->put for the " << ens_var_name - << " field.\n\n"; - exit(1); - } - - return; -} - -//////////////////////////////////////////////////////////////////////// - -void write_ens_var_int(EnsVarInfo * ens_info, int *ens_data, const DataPlane &dp, - const char *type_str, - const char *long_name_str) { - NcVar ens_var; - ConcatString ens_var_name, var_str, name_str, cs; - - // Append nc_pairs_var_str config file entry - cs = ens_info->nc_var_str; - if(cs.length() > 0) var_str << "_" << cs; - - // Construct the variable name - ens_var_name << cs_erase - << ens_info->get_var_info()->name_attr() << "_" - << ens_info->get_var_info()->level_attr() - << var_str << "_" << type_str; - - // Skip variable names that have already been written - if(nc_ens_var_sa.has(ens_var_name)) return; - - // Otherwise, add to the list of previously defined variables - nc_ens_var_sa.add(ens_var_name); - - int deflate_level = compress_level; - if (deflate_level < 0) deflate_level = conf_info.get_compression_level(); - ens_var = add_var(nc_out, (string)ens_var_name, ncInt, lat_dim, lon_dim, deflate_level); - - // Construct the variable name attribute - name_str << cs_erase - << ens_info->get_var_info()->name_attr() << "_" - << type_str; - - // Add the variable attributes - add_var_att_local(ens_info->get_var_info(), &ens_var, true, dp, - name_str.c_str(), long_name_str); - - // Write the data - if(!put_nc_data_with_dims(&ens_var, &ens_data[0], grid.ny(), grid.nx())) { - mlog << Error << "\nwrite_ens_var_int() -> " - << "error in ens_var->put for the " << ens_var_name - << " field.\n\n"; - exit(1); - } - - return; -} - -//////////////////////////////////////////////////////////////////////// - -void write_ens_data_plane(EnsVarInfo * ens_info, const DataPlane &ens_dp, const DataPlane &dp, - const char *type_str, const char *long_name_str) { - - // Allocate memory for this data - float *ens_data = new float [nxy]; - - // Store the data in an array of floats - for(int i=0; i::const_iterator it = ens_input.begin(); // Initialize values model.clear(); obtype.clear(); vld_ens_thresh = bad_data_double; vld_data_thresh = bad_data_double; - nbrhd_prob.clear(); - nmep_smooth.clear(); msg_typ_group_map.clear(); msg_typ_sfc.clear(); mask_area_map.clear(); @@ -90,20 +87,9 @@ void EnsembleStatConfInfo::clear() { // Deallocate memory if(vx_opt) { delete [] vx_opt; vx_opt = (EnsembleStatVxOpt *) 0; } - for(; it != ens_input.end(); it++) { - - if(*it) { delete *it; } - - } - ens_input.clear(); - // Reset counts - n_ens_var = 0; - n_nbrhd = 0; - max_n_ens_thresh = 0; - - n_vx = 0; - max_hira_size = 0; + n_vx = 0; + max_hira_size = 0; return; } @@ -132,17 +118,14 @@ void EnsembleStatConfInfo::process_config(GrdFileType etype, bool grid_vx, bool point_vx, bool use_var_id, StringArray * ens_files, - StringArray * fcst_files, bool use_ctrl) { int i, j, n_ens_files; VarInfoFactory info_factory; mapoutput_map; - Dictionary *edict = (Dictionary *) 0; Dictionary *fdict = (Dictionary *) 0; Dictionary *odict = (Dictionary *) 0; - Dictionary i_edict, i_fdict, i_odict; + Dictionary i_fdict, i_odict; InterpMthd mthd; - VarInfo * next_var; // Dump the contents of the config file if(mlog.verbosity_level() >= 5) conf.dump(cout); @@ -193,9 +176,6 @@ void EnsembleStatConfInfo::process_config(GrdFileType etype, msg_typ_sfc = msg_typ_group_map[(string)surface_msg_typ_group_str]; } - // Conf: ensemble_flag - parse_nc_info(); - // Conf: ens_member_ids ens_member_ids = parse_conf_ens_member_ids(&conf); @@ -208,9 +188,8 @@ void EnsembleStatConfInfo::process_config(GrdFileType etype, // Only a single file should be provided if using ens_member_ids if(ens_files->n() > 1) { mlog << Error << "\nEnsembleStatConfInfo::process_config() -> " - << "The \"" << conf_key_ens_member_ids << "\" " - << "must be empty if more than " - << "one file is provided.\n\n"; + << "the \"" << conf_key_ens_member_ids << "\" " + << "must be empty if more than one file is provided.\n\n"; exit(1); } @@ -234,291 +213,93 @@ void EnsembleStatConfInfo::process_config(GrdFileType etype, // If no ensemble member IDs were provided, add an empty string if(ens_member_ids.n() == 0) ens_member_ids.add(""); - // Conf: ens.field - edict = conf.lookup_array(conf_key_ens_field); - - // Determine the number of ensemble fields to be processed - n_ens_var = parse_conf_n_vx(edict); - - // Print a warning if the ensemble dictionary is not empty - if(n_ens_var != 0) { + // Conf: ens, print warning if present + if(conf.lookup_dictionary(conf_key_ens, false, false)) { mlog << Warning << "\nEnsembleStatConfInfo::process_config() -> " - << "Ensemble post-processing should be moved to the " - << "Gen-Ens-Prod tool, which replaces the logic of the " - << "\"ens\" dictionary. Support for the \"ens\" dictionary " - << "will be deprecated and removed." << "\n\n"; + << "support for ensemble product generation with the \"ens\" " + << "dictionary has moved to the Gen-Ens-Prod tool." << "\n\n"; } - - // Parse the ensemble field information - for(i=0,max_n_ens_thresh=0; iraw_magic_str = raw_magic_str(i_edict, etype); - - // Loop over ensemble member IDs to substitute - for(j=0; jset_dict(i_edict); - - // Dump the contents of the current VarInfo - if(mlog.verbosity_level() >= 5) { - mlog << Debug(5) - << "Parsed ensemble field number " << i+1 - << " (" << j+1 << "):\n"; - next_var->dump(cout); - } - InputInfo input_info; - input_info.var_info = next_var; - input_info.file_index = 0; - input_info.file_list = ens_files; - ens_info->add_input(input_info); - - // Add InputInfo to ens info list for each ensemble file provided - // set var_info to NULL to note first VarInfo should be used - for(int k=1; kadd_input(input_info); - } // end for k - } // end for j - - // Get field info for control member if set - if(!control_id.empty()) { - - // Set environment variable for ens member ID - setenv(met_ens_member_id, control_id.c_str(), 1); - - // Allocate new VarInfo object - next_var = info_factory.new_var_info(etype); - - // Set the current dictionary - next_var->set_dict(i_edict); - - ens_info->set_ctrl(next_var); - } - - // Conf: ens_nc_var_str - ens_info->nc_var_str = parse_conf_string(&i_edict, conf_key_nc_var_str, false); - - // Conf: ens_nc_pairs - // Only parse thresholds if probabilities are requested - if(nc_info.do_freq || nc_info.do_nep || nc_info.do_nmep) { - - // Conf: cat_thresh - ens_info->cat_ta = i_edict.lookup_thresh_array(conf_key_cat_thresh); - - // Dump the contents of the current thresholds - if(mlog.verbosity_level() >= 5) { - mlog << Debug(5) - << "Parsed thresholds for ensemble field number " << i+1 << ":\n"; - ens_info->cat_ta.dump(cout); - } - - // Keep track of the maximum number of thresholds - if(ens_info->cat_ta.n() > max_n_ens_thresh) { - max_n_ens_thresh = ens_info->cat_ta.n(); - } - } - - ens_input.push_back(ens_info); - } // end for i - - // Unset MET_ENS_MEMBER_ID that was previously set - unsetenv(met_ens_member_id); - - // Conf: ens.ens_thresh - vld_ens_thresh = conf.lookup_double(conf_key_ens_ens_thresh); + // Conf: fcst.ens_thresh + vld_ens_thresh = conf.lookup_double(conf_key_fcst_ens_thresh); // Check that the valid ensemble threshold is between 0 and 1. if(vld_ens_thresh < 0.0 || vld_ens_thresh > 1.0) { mlog << Error << "\nEnsembleStatConfInfo::process_config() -> " - << "The \"" << conf_key_ens_ens_thresh << "\" parameter (" + << "The \"" << conf_key_fcst_ens_thresh << "\" parameter (" << vld_ens_thresh << ") must be set between 0 and 1.\n\n"; exit(1); } - // Conf: ens.vld_thresh - vld_data_thresh = conf.lookup_double(conf_key_ens_vld_thresh); + // Conf: fcst.vld_thresh + vld_data_thresh = conf.lookup_double(conf_key_fcst_vld_thresh); // Check that the valid data threshold is between 0 and 1. if(vld_data_thresh < 0.0 || vld_data_thresh > 1.0) { mlog << Error << "\nEnsembleStatConfInfo::process_config() -> " - << "The \"" << conf_key_ens_vld_thresh << "\" parameter (" + << "The \"" << conf_key_fcst_vld_thresh << "\" parameter (" << vld_data_thresh << ") must be set between 0 and 1.\n\n"; exit(1); } - // Conf: nbrhd_prob - nbrhd_prob = parse_conf_nbrhd(&conf, conf_key_nbrhd_prob); - n_nbrhd = nbrhd_prob.width.n(); - - // Conf: nmep_smooth - nmep_smooth = parse_conf_interp(&conf, conf_key_nmep_smooth); - - // Loop through the neighborhood probability smoothing options - for(i=0; i " - << "Neighborhood probability smoothing methods DW_MEAN, " - << "LS_FIT, and BILIN are not supported for \"" - << conf_key_nmep_smooth << "\".\n\n"; - exit(1); - } - - // Check for valid neighborhood probability interpolation widths - if(nmep_smooth.width[i] < 1 || nmep_smooth.width[i]%2 == 0) { - mlog << Error << "\nEnsembleStatConfInfo::process_config() -> " - << "Neighborhood probability smoothing widths must be set " - << "to odd values greater than or equal to 1 (" - << nmep_smooth.width[i] << ") for \"" - << conf_key_nmep_smooth << "\".\n\n"; - exit(1); - } - } // end for i - // Conf: fcst.field and obs.field fdict = conf.lookup_array(conf_key_fcst_field); odict = conf.lookup_array(conf_key_obs_field); - // Determine the number of fields to be verified - n_vx = parse_conf_n_vx(fdict); + // Determine the number of fields (name/level) to be verified + int n_fvx = parse_conf_n_vx(fdict); + int n_ovx = parse_conf_n_vx(odict); // Check for a valid number of verification tasks - if(parse_conf_n_vx(odict) != n_vx) { + if(n_fvx == 0 || n_fvx != n_ovx) { mlog << Error << "\nEnsembleStatConfInfo::process_config() -> " - << "The number of verification tasks in \"" - << conf_key_obs_field - << "\" must match the number in \"" - << conf_key_fcst_field << "\".\n\n"; + << "The number of \"" << conf_key_obs_field << "\" entries (" + << n_ovx << ") must be greater than zero and match " + << "the number of \"" << conf_key_fcst_field << "\" entries (" + << n_fvx << ").\n\n"; exit(1); } - if(n_vx > 0) { - - // Allocate memory for the verification task options - vx_opt = new EnsembleStatVxOpt [n_vx]; - - // Check climatology fields - check_climo_n_vx(&conf, n_vx); + // Allocate memory for the verification task options + n_vx = n_fvx; + vx_opt = new EnsembleStatVxOpt [n_vx]; - // Check to make sure the observation file type is defined - if(otype == FileType_None) { - mlog << Error << "\nEnsembleStatConfInfo::process_config() -> " - << "When \"fcst.field\" is non-empty, you must use " - << "\"-point_obs\" and/or \"-grid_obs\" to specify the " - << "verifying observations.\n\n"; - exit(1); - } + // Check climatology fields + check_climo_n_vx(&conf, n_vx); - // Parse settings for each verification task - for(i=0,max_hira_size=0; isize()); - } + // Track the maximum HiRA size + for(j=0; jsize()); } } - - // Summarize output flags across all verification tasks - process_flags(); } - return; -} - -//////////////////////////////////////////////////////////////////////// - -void EnsembleStatConfInfo::parse_nc_info() { - const DictionaryEntry * e = (const DictionaryEntry *) 0; - - e = conf.lookup(conf_key_ensemble_flag); - - if(!e) { - mlog << Error - << "\nEnsembleStatConfInfo::parse_nc_info() -> " - << "lookup failed for key \"" << conf_key_ensemble_flag - << "\"\n\n"; - exit(1); - } - - const ConfigObjectType type = e->type(); - - if(type == BooleanType) { - bool value = e->b_value(); - - if(!value) nc_info.set_all_false(); - - return; - } - - // It should be a dictionary - if(type != DictionaryType) { - mlog << Error - << "\nEnsembleStatConfInfo::parse_nc_info() -> " - << "bad type (" << configobjecttype_to_string(type) - << ") for key \"" << conf_key_ensemble_flag << "\"\n\n"; - exit(1); - } - - // Parse the various entries - Dictionary * d = e->dict_value(); - - nc_info.do_latlon = d->lookup_bool(conf_key_latlon_flag); - nc_info.do_mean = d->lookup_bool(conf_key_mean_flag); - nc_info.do_stdev = d->lookup_bool(conf_key_stdev_flag); - nc_info.do_minus = d->lookup_bool(conf_key_minus_flag); - nc_info.do_plus = d->lookup_bool(conf_key_plus_flag); - nc_info.do_min = d->lookup_bool(conf_key_min_flag); - nc_info.do_max = d->lookup_bool(conf_key_max_flag); - nc_info.do_range = d->lookup_bool(conf_key_range_flag); - nc_info.do_vld = d->lookup_bool(conf_key_vld_count_flag); - nc_info.do_freq = d->lookup_bool(conf_key_frequency_flag); - nc_info.do_nep = d->lookup_bool(conf_key_nep_flag); - nc_info.do_nmep = d->lookup_bool(conf_key_nmep_flag); - nc_info.do_orank = d->lookup_bool(conf_key_rank_flag); - nc_info.do_weight = d->lookup_bool(conf_key_weight); + // Summarize output flags across all verification tasks + process_flags(); return; } @@ -531,6 +312,7 @@ void EnsembleStatConfInfo::process_flags() { // Initialize for(i=0; iadd_input(input_info); // Add InputInfo to fcst info list for each ensemble file provided // set var_info to NULL to note first VarInfo should be used - int last_member_index = fcst_files->n() - (use_ctrl ? 1 : 0); + int last_member_index = ens_files->n() - (use_ctrl ? 1 : 0); for(j=1; jadd_input(input_info); } // end for j } // end for i @@ -875,8 +668,8 @@ void EnsembleStatVxOpt::process_config(GrdFileType ftype, Dictionary &fdict, next_var->set_dict(fdict); input_info.var_info = next_var; - input_info.file_index = fcst_files->n() - 1; - input_info.file_list = fcst_files; + input_info.file_index = ens_files->n() - 1; + input_info.file_list = ens_files; vx_pd.fcst_info->add_input(input_info); } @@ -974,6 +767,9 @@ void EnsembleStatVxOpt::process_config(GrdFileType ftype, Dictionary &fdict, // Conf: output_flag output_map = parse_conf_output_flag(&odict, txt_file_type, n_txt); + // Conf: nc_orank_flag + parse_nc_info(odict); + // Populate the output_flag array with map values for(i=0; i " + << "lookup failed for key \"" << conf_key_nc_orank_flag + << "\"\n\n"; + exit(1); + } + + const ConfigObjectType type = e->type(); + + if(type == BooleanType) { + bool value = e->b_value(); + + if(!value) nc_info.set_all_false(); + + return; + } + + // It should be a dictionary + if(type != DictionaryType) { + mlog << Error + << "\nEnsembleStatVxOpt::parse_nc_info() -> " + << "bad type (" << configobjecttype_to_string(type) + << ") for key \"" << conf_key_nc_orank_flag << "\"\n\n"; + exit(1); + } + + // Parse the various entries + Dictionary * d = e->dict_value(); + + nc_info.do_latlon = d->lookup_bool(conf_key_latlon_flag); + nc_info.do_mean = d->lookup_bool(conf_key_mean_flag); + nc_info.do_raw = d->lookup_bool(conf_key_raw_flag); + nc_info.do_rank = d->lookup_bool(conf_key_rank_flag); + nc_info.do_pit = d->lookup_bool(conf_key_pit_flag); + nc_info.do_vld = d->lookup_bool(conf_key_vld_count_flag); + nc_info.do_weight = d->lookup_bool(conf_key_weight); + + return; +} + +//////////////////////////////////////////////////////////////////////// + void EnsembleStatVxOpt::set_vx_pd(EnsembleStatConfInfo *conf_info, int ctrl_index) { int i, j, n; int n_msg_typ = msg_typ.n(); @@ -1316,10 +1160,9 @@ void EnsembleStatNcOutInfo::clear() { bool EnsembleStatNcOutInfo::all_false() const { - bool status = do_latlon || do_mean || do_stdev || do_minus || - do_plus || do_min || do_max || do_range || - do_vld || do_freq || do_nep || do_nmep || - do_orank || do_weight; + bool status = do_latlon || do_mean || do_raw || + do_rank || do_pit || do_vld || + do_weight; return(!status); } @@ -1330,44 +1173,28 @@ void EnsembleStatNcOutInfo::set_all_false() { do_latlon = false; do_mean = false; - do_stdev = false; - do_minus = false; - do_plus = false; - do_min = false; - do_max = false; - do_range = false; + do_raw = false; + do_rank = false; + do_pit = false; do_vld = false; - do_freq = false; - do_nep = false; - do_nmep = false; - do_orank = false; do_weight = false; return; } - //////////////////////////////////////////////////////////////////////// void EnsembleStatNcOutInfo::set_all_true() { do_latlon = true; do_mean = true; - do_stdev = true; - do_minus = true; - do_plus = true; - do_min = true; - do_max = true; - do_range = true; + do_raw = true; + do_rank = true; + do_pit = true; do_vld = true; - do_freq = true; - do_nep = true; - do_nmep = true; - do_orank = true; do_weight = true; return; } //////////////////////////////////////////////////////////////////////// - diff --git a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h index e2d823a504..a011b89fe4 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h +++ b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h @@ -54,17 +54,10 @@ struct EnsembleStatNcOutInfo { bool do_latlon; bool do_mean; - bool do_stdev; - bool do_minus; - bool do_plus; - bool do_min; - bool do_max; - bool do_range; + bool do_raw; + bool do_rank; + bool do_pit; bool do_vld; - bool do_freq; - bool do_nep; - bool do_nmep; - bool do_orank; bool do_weight; ////////////////////////////////////////////////////////////////// @@ -143,6 +136,7 @@ class EnsembleStatVxOpt { // Output file options STATOutputType output_flag[n_txt]; // Flag for each output line type + EnsembleStatNcOutInfo nc_info; // Output NetCDF pairs file contents ////////////////////////////////////////////////////////////////// @@ -153,6 +147,7 @@ class EnsembleStatVxOpt { gsl_rng *, bool, bool, bool, StringArray, StringArray *, bool, ConcatString); + void parse_nc_info(Dictionary &); void set_vx_pd(EnsembleStatConfInfo *, int); void set_perc_thresh(const PairDataEnsemble *); @@ -196,10 +191,6 @@ class EnsembleStatConfInfo { void init_from_scratch(); - // Ensemble processing - int n_ens_var; // Number of ensemble fields to be processed - int max_n_ens_thresh; // Maximum number of ensemble thresholds - // Ensemble verification int n_vx; // Number of ensemble fields to be verified int max_hira_size; // Maximum size of a HiRA neighborhoods @@ -218,14 +209,9 @@ class EnsembleStatConfInfo { ConcatString model; // Model name ConcatString obtype; // Observation type - vector ens_input; // Vector of EnsVarInfo pointers (allocated) StringArray ens_member_ids; // Array of ensemble member ID strings ConcatString control_id; // Control ID - NbrhdInfo nbrhd_prob; // Neighborhood probability definition - int n_nbrhd; // Number of neighborhood sizes - InterpInfo nmep_smooth; // Neighborhood maximum smoothing information - EnsembleStatVxOpt * vx_opt; // Array of vx task options [n_vx] (allocated) double vld_ens_thresh; // Required ratio of valid input files @@ -249,8 +235,7 @@ class EnsembleStatConfInfo { ConcatString version; // Config file version STATOutputType output_flag[n_txt]; // Summary of output_flag options - - EnsembleStatNcOutInfo nc_info; // Output NetCDF file contents + EnsembleStatNcOutInfo nc_info; // Summary of output NetCDF file contents ////////////////////////////////////////////////////////////////// @@ -258,16 +243,13 @@ class EnsembleStatConfInfo { void read_config (const ConcatString , const ConcatString); void process_config(GrdFileType, GrdFileType, bool, bool, bool, - StringArray *, StringArray *, bool); + StringArray *, bool); void process_flags (); - void parse_nc_info (); void process_masks (const Grid &); void set_vx_pd (const IntArray &, int); // Dump out the counts - int get_n_ens_var() const; - int get_n_nbrhd() const; - int get_n_vx() const; + int get_n_vx() const; // Compute the maximum number of output lines possible based // on the contents of the configuration file @@ -275,7 +257,6 @@ class EnsembleStatConfInfo { int n_stat_row() const; // Maximum across all verification tasks - int get_max_n_ens_thresh() const; int get_max_hira_size() const; int get_max_n_prob_cat_thresh() const; int get_max_n_prob_pct_thresh() const; @@ -286,10 +267,7 @@ class EnsembleStatConfInfo { //////////////////////////////////////////////////////////////////////// -inline int EnsembleStatConfInfo::get_n_ens_var() const { return(n_ens_var); } -inline int EnsembleStatConfInfo::get_n_nbrhd() const { return(n_nbrhd); } inline int EnsembleStatConfInfo::get_n_vx() const { return(n_vx); } -inline int EnsembleStatConfInfo::get_max_n_ens_thresh() const { return(max_n_ens_thresh); } inline int EnsembleStatConfInfo::get_max_hira_size() const { return(max_hira_size); } inline int EnsembleStatConfInfo::get_compression_level() { return(conf.nc_compression()); } diff --git a/src/tools/other/ascii2nc/aeronet_handler.cc b/src/tools/other/ascii2nc/aeronet_handler.cc index 0c9bf2ad7a..7cdc07d7d0 100644 --- a/src/tools/other/ascii2nc/aeronet_handler.cc +++ b/src/tools/other/ascii2nc/aeronet_handler.cc @@ -47,7 +47,7 @@ const string lat_col2 = "Latitude"; // "Latitude(degrees)" const string lon_col2 = "Longitude"; // "Longitude(degrees)" const string elv_col2 = "Elevation"; // "Elevation(meters)" -const string AeronetHandler::HEADER_TYPE = ""; ///// +const string AeronetHandler::HEADER_TYPE = ""; const int AeronetHandler::AOT_GRIB_CODE = 129; // Version 2 @@ -68,8 +68,6 @@ const string WAVELENGTHS_INPUT_AOD_NAME = "Exact_Wavelengths_for_Input_AOD"; static int format_version; -const float AERONET_MISSING_VALUE = -999.; - double angstrom_power_interplation(double value_1, double value_2, double level_1, double level_2, double target_level); @@ -416,7 +414,6 @@ bool AeronetHandler::_readObservations(LineDataFile &ascii_file) var_id = header_var_index[k]; var_name = header_var_names[k]; dheight = header_heights[k]; - //if (is_eq(atof(data_line[k]), AERONET_MISSING_VALUE)) continue; if (strcmp(var_name.c_str(), AOD_NAME.c_str()) == 0) { if (is_eq(dheight, 550)) has_aod_at_550 = true; else if (is_eq(dheight, 440)) aod_at_440 = atof(data_line[k]); @@ -768,9 +765,13 @@ string AeronetHandler::make_var_name_from_header(string hdr_field) { return var_name; } +//////////////////////////////////////////////////////////////////////// + double angstrom_power_interplation(double value_1, double value_2, double level_1, double level_2, double target_level) { double angstrom_log = -log10(value_1/value_2)/log10(level_1/level_2); double angstrom_value = value_2 * pow((target_level/level_2),-angstrom_log); return angstrom_value; } + +//////////////////////////////////////////////////////////////////////// diff --git a/src/tools/other/ascii2nc/airnow_handler.cc b/src/tools/other/ascii2nc/airnow_handler.cc index 2eb467ee8c..fbc655f9dd 100644 --- a/src/tools/other/ascii2nc/airnow_handler.cc +++ b/src/tools/other/ascii2nc/airnow_handler.cc @@ -84,8 +84,6 @@ const string hdr_hourlyaqobs_co_units = "CO_Unit"; const string hdr_hourlyaqobs_so2 = "SO2"; const string hdr_hourlyaqobs_so2_units = "SO2_Unit"; -const float AIRNOW_MISSING_VALUE = -999.; - string remove_quotes(string &s); bool doubleOrMissing(const string &s, double &value); vector parseHourlyAqobsLine(const string &asciiLine, bool &ok); @@ -309,7 +307,7 @@ bool AirnowHandler::_parseObservationLineStandard(DataLine &data_line, col = _extractColumn(data_line, elevPtr); elev = atof(col.c_str()); } else { - elev = AIRNOW_MISSING_VALUE; + elev = bad_data_double; } } string varName; @@ -317,8 +315,6 @@ bool AirnowHandler::_parseObservationLineStandard(DataLine &data_line, double value; int aqiValue; int aqiCategory; - //double height_m = AIRNOW_MISSING_VALUE; // maybe change - // go with this for now, can easily replace with previous line double height_m = elev; if (format_version == AIRNOW_FORMAT_VERSION_DAILYV2) { @@ -333,7 +329,7 @@ bool AirnowHandler::_parseObservationLineStandard(DataLine &data_line, // for now only the single variable is written as an observation _addObservations(Observation(header_type, stationId, valid_time, lat, lon, elev, na_str, 0, - AIRNOW_MISSING_VALUE, height_m, + bad_data_double, height_m, value, varName)); } else if (format_version == AIRNOW_FORMAT_VERSION_HOURLY) { varName = _extractColumn(data_line, varnamePtr); @@ -342,7 +338,7 @@ bool AirnowHandler::_parseObservationLineStandard(DataLine &data_line, value = atof(col.c_str()); _addObservations(Observation(header_type, stationId, valid_time, lat, lon, elev, na_str, 0, - AIRNOW_MISSING_VALUE, height_m, + bad_data_double, height_m, value, varName)); } return true; @@ -422,7 +418,7 @@ bool AirnowHandler::_parseObservationLineAqobs(const string &data_line, if (elevPtr >= 0) { elev = atof(tokens[elevPtr].c_str()); } else { - elev = 0.0; // or maybe -99 missing + elev = 0.0; } _addHourlyAqobsObs(tokens, header_type, stationId, valid_time, lat, lon, elev, @@ -493,8 +489,6 @@ void AirnowHandler::_addHourlyAqobsObs(const vector &data_line, const st int aqi; double value; string units; - // double height_m = AIRNOW_MISSING_VALUE; // maybe change - // go with this, can easily switch to previous line double height_m = elev; status = atoi(data_line[measuredPtr].c_str()); @@ -505,7 +499,7 @@ void AirnowHandler::_addHourlyAqobsObs(const vector &data_line, const st // for now only the single variable is written as an observation _addObservations(Observation(header_type, stationId, valid_time, lat, lon, elev, na_str, 0, - AIRNOW_MISSING_VALUE, height_m, + bad_data_double, height_m, value, varname)); } } @@ -522,15 +516,13 @@ void AirnowHandler::_addHourlyAqobsObs(const vector &data_line, const st string col; double value; string units; - // double height_m = AIRNOW_MISSING_VALUE; // maybe change - // go with this, can easily switch to previous line double height_m = elev; if (doubleOrMissing(data_line[valuePtr], value)) { units = data_line[unitPtr]; // ignored for now _addObservations(Observation(header_type, stationId, valid_time, lat, lon, elev, na_str, 0, - AIRNOW_MISSING_VALUE, height_m, + bad_data_double, height_m, value, varname)); } } @@ -923,7 +915,7 @@ string remove_quotes(string &s) bool doubleOrMissing(const string &s, double &value) { if (s.empty()) { - value = AIRNOW_MISSING_VALUE; + value = bad_data_double; return false; } else { value = atof(s.c_str()); @@ -964,3 +956,5 @@ vector parseHourlyAqobsLine(const string &asciiLine, bool &ok) } return tokens; } + +////////////////////////////////////////////////////////////////////////