From 8a5518857e4ba8c931a821ad78f33a1e9c53e2ba Mon Sep 17 00:00:00 2001 From: davidalbo Date: Fri, 17 Nov 2023 13:12:48 -0700 Subject: [PATCH] Feature 2706 mvmode obs fcst input size (#2742) Co-authored-by: Tracy Hertneky <39317287+hertneky@users.noreply.github.com> Co-authored-by: John Halley Gotway --- data/config/MODEMultivarConfig_default | 6 +- docs/Users_Guide/mode.rst | 13 +- .../config/MODEConfig_multivar_fake_data | 5 +- ...Config_multivar_fake_data_with_intensities | 4 +- src/basic/vx_config/config_constants.h | 3 +- src/basic/vx_config/config_file.cc | 8 + src/basic/vx_config/config_file.h | 2 + src/libcode/vx_shapedata/engine.cc | 93 +- src/libcode/vx_shapedata/engine.h | 5 + src/libcode/vx_shapedata/mode_conf_info.cc | 889 +++++++++++----- src/libcode/vx_shapedata/mode_conf_info.h | 90 +- src/libcode/vx_shapedata/mode_data_type.h | 50 + src/libcode/vx_shapedata/mode_field_info.cc | 4 +- src/libcode/vx_statistics/apply_mask.cc | 9 +- src/tools/core/mode/mode.cc | 2 +- src/tools/core/mode/mode_exec.cc | 946 ++++++++++++++---- src/tools/core/mode/mode_exec.h | 52 +- src/tools/core/mode/mode_frontend.cc | 540 ++++++---- src/tools/core/mode/mode_frontend.h | 61 +- src/tools/core/mode/multivar_data.cc | 208 ++-- src/tools/core/mode/multivar_data.h | 103 +- src/tools/core/mode/multivar_frontend.cc | 548 +++++----- 22 files changed, 2412 insertions(+), 1229 deletions(-) create mode 100644 src/libcode/vx_shapedata/mode_data_type.h diff --git a/data/config/MODEMultivarConfig_default b/data/config/MODEMultivarConfig_default index 76207fd018..89268e0574 100644 --- a/data/config/MODEMultivarConfig_default +++ b/data/config/MODEMultivarConfig_default @@ -54,9 +54,11 @@ quilt = FALSE; multivar_logic = "#1 && #2 && #3"; // -// MODE Multivar intensity computation flag +// MODE Multivar intensity comparison settings // -multivar_intensity_flag = [FALSE, TRUE, TRUE]; +multivar_intensity_compare_fcst = [ 2, 3 ]; +multivar_intensity_compare_obs = [ 2, 3 ]; + // // Forecast and observation fields to be verified diff --git a/docs/Users_Guide/mode.rst b/docs/Users_Guide/mode.rst index 9da477d24f..5a6503f0f5 100644 --- a/docs/Users_Guide/mode.rst +++ b/docs/Users_Guide/mode.rst @@ -112,11 +112,11 @@ Traditionally, MODE defines objects by smoothing and thresholding data from a si As described in :numref:`MODE-configuration-file`, the **field** entry in the forecast and observation dictionaries define the input data to be processed. If **field** is defined as a dictionary, the traditional method for running MODE is invoked, where objects are defined using a single input field. If **field** is defined as an array of dictionaries, each specifying a different input field, then the multi-variate MODE logic is invoked and requires the **multivar_logic** configuration entry to be set. Traditional MODE is run once for each input field to define objects for that field. Note that the object definition criteria can be defined separately for each field array entry. The objects from each input field are combined into forecast and observation data *super* objects -The **multivar_logic** and **multivar_intensity_flag** configuration entries, described in :numref:`MODE-configuration-file`, define the boolean logic for combining objects from multiple fields into *super* objects, and then optionally computing intensities for individual input fields when the input is masked to non-missing only inside the *super* objects. If the **multivar_logic** configuration option iset, there must be the same number of fields defined in an array of dictionaries for fcst and for obs as indicated in the **multivar_logic**. Note that the multi-variate MODE forecast and observation input fields and combination logic do not need to -match. If a particular **multivar_intensity_flag** value is TRUE the corresponding pair of fields (fcst and obs) are masked to non-missing inside the fcst and obs super objects, and traditional mode is run on that pair of masked inputs producing uniquely named outputs. If it is FALSE, mode is not run for that pair of inputs. +The **multivar_logic** configuration entry, described in :numref:`MODE-configuration-file`, defines the boolean logic for combining objects from multiple fields into *super* objects. It can be defined once to apply to both the forecast and observation dictionaries if the field array lengths are the same, or defined separately within each dictionary. If defined separately within each dictionary, the field array lengths do not need to be the same for the forecast and observations. Note that the multi-variate MODE forecast and observation input fields and combination logic do not need to match. -If all **multivar_intensity_flag** values are FALSE, the forecast and observation *super* objects are written to NetCDF, text, and postscript output files in the standard mode output format, but with no intensity information. +The **multivar_intensity_compare_fcst** and **multivar_intensity_compare_obs** configuration entries, described in :numref:`MODE-configuration-file`, define the field array indexes for which to optionally compare intensities for individual input fields when the input is masked to non-missing only inside the *super* objects and are required to be the same length. For example, if **multivar_intensity_compare_fcst = [ 1, 2 ];** and **multivar_intensity_compare_obs = [ 2, 3 ];**, then index 1 (2) of the forecast field array will be compared with index 2 (3) of the observation field array. If an intensity comparision is requested, the corresponding pair of fields (fcst and obs) are masked to non-missing inside the fcst and obs super objects, and traditional mode is run on that pair of masked inputs producing uniquely named outputs. If **multivar_intensity_compare_fcst** and **multivar_intensity_compare_obs** are empty, the forecast and observation *super* objects are written to NetCDF, text, and postscript output files in the standard mode output format, but with no intensity information. +When regridding to the FCST or OBS field (e.g. to_grid = FCST), the first field of the field array is used from the forecast and observation field dictionaries, respectively. All regridding is then done to that grid. Other regrid options described in :ref:`regrid` can also be used as normal. Practical Information ===================== @@ -243,15 +243,16 @@ _____________________ The **multivar_logic** entry appears only in the **MODEMultivarConfig_default** file. This option applies to running multi-variate MODE by setting **field** to an array of dictionaries to define multiple input fields. Objects are defined separately for each input field based on the configuration settings specified for each field array entry. The **multivar_logic** entry is a string which defines how objects for each field are combined into a final *super* object. The objects for each field are referred to as '#N' where N is the N-th field array entry. The '&&' and '||' strings define intersection and union logic, respectively. For example, "#1 && #2" is the intersection of the objects from the first and second fields. "(#1 && #2) || #3" is the union of that intersection with the objects from the third field. -The **multivar_logic** entry is parsed separately from the **fcst** and **obs** dictionaries and can be defined differently in each. +The **multivar_logic** entry is parsed separately from the **fcst** and **obs** dictionaries and can be defined differently in each. It does not require the same number of fields in the forecast and observation arrays. _____________________ .. code-block:: none - multivar_intensity_flag = [FALSE, TRUE, TRUE]; + multivar_intensity_compare_fcst = [1,2]; + multivar_intensity_compare_obs = [2,3]; -The **multivar_intensity_flag** entry appears only in the **MODEMultivarConfig_default** file. This option is paired with the **multivar_logic** entry, and can take on a value of TRUE or FALSE for each **field**. In the multivar case, super objects are created using the **multivar_logic** settings. For each input for which **multivar_intensity_flag** is TRUE, the input is masked to be non-missing only within the super objects, and traditional mode is run on that masked input. For each input for which **multivar_intensity_flag** is FALSE, the input is skipped over. If all the multivar_intensity_flag values are FALSE, traditional mode output is created for the super objects, but with no intensity information. +The **multivar_intensity_compare_fcst** and **multivar_intensity_compare_obs** entries appear only in the **MODEMultivarConfig_default** file. These entries define an index in the field arrays to be compared for forecast and observation intensities and must be the same length. For example, in the above example, forecast field 1 will be compared to observation field 2 for computing intensity attribute statistics. If the **multivar_intensity_compare_fcst** and **multivar_intensity_compare_obs** are empty, traditional mode output is created for the super objects, but with no intensity information. _____________________ diff --git a/internal/test_unit/config/MODEConfig_multivar_fake_data b/internal/test_unit/config/MODEConfig_multivar_fake_data index fa46e066b2..734ff39dd8 100644 --- a/internal/test_unit/config/MODEConfig_multivar_fake_data +++ b/internal/test_unit/config/MODEConfig_multivar_fake_data @@ -54,9 +54,10 @@ quilt = FALSE; multivar_logic = "#1 && #2 && #3"; // -// MODE Multivar intensity logic +// MODE Multivar intensity comparisons // -multivar_intensity_flag = [FALSE, FALSE, FALSE]; +multivar_intensity_compare_fcst = [ ]; +multivar_intensity_compare_obs = [ ]; // // Forecast and observation fields to be verified diff --git a/internal/test_unit/config/MODEConfig_multivar_fake_data_with_intensities b/internal/test_unit/config/MODEConfig_multivar_fake_data_with_intensities index 7230ecf817..85fc18c937 100644 --- a/internal/test_unit/config/MODEConfig_multivar_fake_data_with_intensities +++ b/internal/test_unit/config/MODEConfig_multivar_fake_data_with_intensities @@ -56,7 +56,9 @@ multivar_logic = "#1 && #2 && #3"; // // MODE Multivar intensity logic // -multivar_intensity_flag = [TRUE, TRUE, TRUE]; +multivar_intensity_compare_fcst = [ 1, 2, 3 ]; +multivar_intensity_compare_obs = [ 1, 2, 3 ]; + // // Forecast and observation fields to be verified diff --git a/src/basic/vx_config/config_constants.h b/src/basic/vx_config/config_constants.h index 045c696f02..48ca1beccf 100644 --- a/src/basic/vx_config/config_constants.h +++ b/src/basic/vx_config/config_constants.h @@ -908,7 +908,8 @@ static const char conf_key_shift_right[] = "shift_right"; static const char conf_key_multivar_logic [] = "multivar_logic"; static const char conf_key_multivar_name [] = "multivar_name"; static const char conf_key_multivar_level [] = "multivar_level"; -static const char conf_key_multivar_intensity_flag [] = "multivar_intensity_flag"; +static const char conf_key_fcst_multivar_compare_index [] = "multivar_intensity_compare_fcst"; +static const char conf_key_obs_multivar_compare_index [] = "multivar_intensity_compare_obs"; // // MTD specific parameter key names diff --git a/src/basic/vx_config/config_file.cc b/src/basic/vx_config/config_file.cc index daee7b2cd6..67c8af8959 100644 --- a/src/basic/vx_config/config_file.cc +++ b/src/basic/vx_config/config_file.cc @@ -188,6 +188,14 @@ return; //////////////////////////////////////////////////////////////////////// +void MetConfig::debug_dump(int depth) const +{ + dump(cout, depth); +} + +//////////////////////////////////////////////////////////////////////// + + void MetConfig::dump(ostream & out, int depth) const { diff --git a/src/basic/vx_config/config_file.h b/src/basic/vx_config/config_file.h index 9cc0292c22..9fff9a35f8 100644 --- a/src/basic/vx_config/config_file.h +++ b/src/basic/vx_config/config_file.h @@ -58,6 +58,8 @@ class MetConfig : public Dictionary { void dump(std::ostream &, int = 0) const; + void debug_dump(int = 0) const; + // // set stuff // diff --git a/src/libcode/vx_shapedata/engine.cc b/src/libcode/vx_shapedata/engine.cc index 0bfab73929..e81c2d21bc 100644 --- a/src/libcode/vx_shapedata/engine.cc +++ b/src/libcode/vx_shapedata/engine.cc @@ -190,6 +190,8 @@ void ModeFuzzyEngine::init_from_scratch() { clear_features(); + data_type = ModeDataType_Traditional; + return; } @@ -245,21 +247,26 @@ void ModeFuzzyEngine::clear_colors() { void ModeFuzzyEngine::set(const ShapeData &fcst_wd, const ShapeData &obs_wd) { + if (data_type == ModeDataType_MvMode_Fcst) { + set_fcst(fcst_wd); + } else if (data_type == ModeDataType_MvMode_Obs) { + set_obs(obs_wd); + } else { + ConcatString path; - ConcatString path; - - clear_features(); - clear_colors(); - ctable.clear(); + clear_features(); + clear_colors(); + ctable.clear(); - collection.clear(); + collection.clear(); - set_fcst(fcst_wd); - set_obs(obs_wd); + set_fcst(fcst_wd); + set_obs(obs_wd); - path = replace_path(conf_info.object_pi.color_table.c_str()); + path = replace_path(conf_info.object_pi.color_table.c_str()); - ctable.read(path.c_str()); + ctable.read(path.c_str()); + } return; @@ -271,21 +278,26 @@ void ModeFuzzyEngine::set(const ShapeData &fcst_wd, const ShapeData &obs_wd) void ModeFuzzyEngine::set_no_conv(const ShapeData &fcst_wd, const ShapeData &obs_wd) { + if (data_type == ModeDataType_MvMode_Fcst) { + set_fcst_no_conv(fcst_wd); + } else if (data_type == ModeDataType_MvMode_Obs) { + set_obs_no_conv ( obs_wd); + } else { + ConcatString path; - ConcatString path; + clear_features(); + clear_colors(); + ctable.clear(); - clear_features(); - clear_colors(); - ctable.clear(); + collection.clear(); - collection.clear(); + set_fcst_no_conv (fcst_wd); + set_obs_no_conv ( obs_wd); - set_fcst_no_conv (fcst_wd); - set_obs_no_conv ( obs_wd); + path = replace_path(conf_info.object_pi.color_table.c_str()); - path = replace_path(conf_info.object_pi.color_table.c_str()); - - ctable.read(path.c_str()); + ctable.read(path.c_str()); + } return; @@ -297,21 +309,27 @@ void ModeFuzzyEngine::set_only_split(const ShapeData &fcst_wd, const ShapeData & { - ConcatString path; - - clear_features(); - clear_colors(); - ctable.clear(); + if (data_type == ModeDataType_MvMode_Fcst) { + set_fcst_only_split (fcst_wd); + } else if (data_type == ModeDataType_MvMode_Obs) { + set_obs_only_split ( obs_wd); + } else { + ConcatString path; - collection.clear(); + clear_features(); + clear_colors(); + ctable.clear(); - set_fcst_only_split (fcst_wd); - set_obs_only_split ( obs_wd); + collection.clear(); - path = replace_path(conf_info.object_pi.color_table.c_str()); + set_fcst_only_split (fcst_wd); + set_obs_only_split ( obs_wd); - ctable.read(path.c_str()); + path = replace_path(conf_info.object_pi.color_table.c_str()); + ctable.read(path.c_str()); + } + return; } @@ -1579,7 +1597,7 @@ void ModeFuzzyEngine::do_fcst_merge_thresh(const ShapeData &merge_data) { /////////////////////////////////////////////////////////////////////// void ModeFuzzyEngine::do_obs_merge_thresh(const ShapeData &merge_data) { - const char *method_name = "ModeFuzzyEngine::do_fcst_merge_thresh() -> "; + const char *method_name = "ModeFuzzyEngine::do_obs_merge_thresh() -> "; int j, mid, oid; int n_obs_merge; ShapeData obs_merge_split; @@ -1643,7 +1661,6 @@ void ModeFuzzyEngine::do_obs_merge_thresh(const ShapeData &merge_data) { // Calculate the composite object sets // for(mid=1; mid<=n_obs_merge; mid++) { - // Ignore merge objects containing a single simple object if(mrg_to_obj_map[mid].size() <= 1) continue; @@ -2482,6 +2499,14 @@ void ModeFuzzyEngine::do_cluster_features() { /////////////////////////////////////////////////////////////////////// +void ModeFuzzyEngine::set_data_type(ModeDataType type) +{ + data_type = type; + conf_info.set_data_type(type); +} + +/////////////////////////////////////////////////////////////////////// + int ModeFuzzyEngine::get_info_index(int pair_n) const { int i; @@ -3939,7 +3964,7 @@ void calc_fcst_clus_ch_mask(const ModeFuzzyEngine &eng, ShapeData &mask) { Box bb; if(eng.need_fcst_clus_split) { - mlog << Error << "\ncalc_fcst_clus_ch_mask -> " + mlog << Error << "\ncalc_fcst_clus_ch_mask() -> " << "should not be called with need_fcst_clus_split set to true\n\n"; exit(1); @@ -4002,7 +4027,7 @@ void calc_obs_clus_ch_mask(const ModeFuzzyEngine &eng, ShapeData &mask) { Box bb; if(eng.need_obs_clus_split) { - mlog << Error << "\ncalc_obs_clus_ch_mask -> " + mlog << Error << "\ncalc_obs_clus_ch_mask() -> " << "should not be called with need_obs_clus_split set to true\n\n"; exit(1); } diff --git a/src/libcode/vx_shapedata/engine.h b/src/libcode/vx_shapedata/engine.h index c975a06691..8bc5995dfb 100644 --- a/src/libcode/vx_shapedata/engine.h +++ b/src/libcode/vx_shapedata/engine.h @@ -14,6 +14,7 @@ /////////////////////////////////////////////////////////////////////////////// #include "mode_conf_info.h" +#include "mode_data_type.h" #include "interest.h" #include "set.h" @@ -284,6 +285,8 @@ class ModeFuzzyEngine { void do_cluster_features(); + void set_data_type(ModeDataType type); + // // Configuration information // @@ -368,8 +371,10 @@ class ModeFuzzyEngine { int get_matched_obs(int) const; int get_unmatched_obs(int) const; + SetCollection collection; + ModeDataType data_type; }; /////////////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_shapedata/mode_conf_info.cc b/src/libcode/vx_shapedata/mode_conf_info.cc index aea85582c0..a2ebee3c5b 100644 --- a/src/libcode/vx_shapedata/mode_conf_info.cc +++ b/src/libcode/vx_shapedata/mode_conf_info.cc @@ -57,9 +57,11 @@ void ModeConfInfo::init_from_scratch() { - N_fields = 0; + N_fields_f = 0; + N_fields_o = 0; - Field_Index = 0; + Field_Index_f = 0; + Field_Index_o = 0; fcst_array = 0; obs_array = 0; @@ -90,10 +92,11 @@ void ModeConfInfo::clear() grid_res = bad_data_double; - Field_Index = 0; + Field_Index_f = 0; + Field_Index_o = 0; fcst_multivar_logic.clear(); - obs_multivar_logic.clear(); + obs_multivar_logic.clear(); match_flag = MatchType_None; @@ -159,7 +162,12 @@ void ModeConfInfo::clear() Fcst = 0; Obs = 0; - N_fields = 0; + // so traditional mode will have the right value + data_type = ModeDataType_Traditional; + + // N_fields = 0; + N_fields_f = 0; + N_fields_o = 0; return; @@ -192,16 +200,11 @@ void ModeConfInfo::read_config(const char * default_file_name, const char * user //////////////////////////////////////////////////////////////////////// -void ModeConfInfo::process_config(GrdFileType ftype, GrdFileType otype) +void ModeConfInfo::process_config(GrdFileType ftype, GrdFileType otype, + ModeDataType dt) { - -int j, k, n; -// VarInfoFactory info_factory; -Dictionary * fcst_dict = (Dictionary *) 0; -Dictionary * obs_dict = (Dictionary *) 0; -Dictionary * dict = (Dictionary *) 0; -PlotInfo plot_info; + Dictionary * dict = (Dictionary *) 0; // Dump the contents of the config file @@ -211,6 +214,8 @@ PlotInfo plot_info; clear(); + set_data_type(dt); + // Conf: version version = parse_conf_version(&conf); @@ -235,135 +240,6 @@ PlotInfo plot_info; quilt = conf.lookup_bool(conf_key_quilt); - // Conf: fcst and obs - - fcst_dict = conf.lookup_dictionary(conf_key_fcst); - obs_dict = conf.lookup_dictionary(conf_key_obs); - - read_fields (fcst_array, fcst_dict, ftype, 'F'); // the order is important here - read_fields ( obs_array, obs_dict, otype, 'O'); // the order is important here - - Fcst = fcst_array; // + 0 - Obs = obs_array; // + 0 - - // Dump the contents of the VarInfo objects - - if(mlog.verbosity_level() >= 5) { - for (j=0; jdump(cout); - mlog << Debug(5) - << "Parsed observation field:\n"; - obs_array[j].var_info->dump(cout); - } // for j - } - - // No support for wind direction - - for (j=0; jis_wind_direction() || obs_array[j].var_info->is_wind_direction()) { - mlog << Error << "\nModeConfInfo::process_config() -> " - << "the wind direction field may not be verified " - << "using MODE.\n\n"; - exit(1); - } - } - - for (j=0; j " - << "fcst and obs convolution radius arrays need to be the same size\n\n"; - - exit ( 1 ); - - } - - } - - // Check that fcst_conv_radius and obs_conv_radius are non-negative - - for (j=0; j " - << "fcst_conv_radius (" << fcst_array[j].conv_radius_array[k] - << ") and obs_conv_radius (" << obs_array[j].conv_radius_array[k] - << ") must be non-negative\n\n"; - - exit(1); - - } - - } // for k - - } // for j - - - for (j=0; j " - << "fcst and obs convolution threshold arrays need to be the same size\n\n"; - - exit ( 1 ); - - } - - } - - for (j=0; j " - << "fcst conv thresh and fcst merge thresh arrays need to be the same size\n\n"; - - exit ( 1 ); - - } - - - if ( obs_array[j].need_merge_thresh() && (obs_array[j].merge_thresh_array.n_elements() != obs_array[j].conv_thresh_array.n_elements()) ) { - - mlog << Error << "\nModeConfInfo::process_config() -> " - << "obs conv thresh and obs merge thresh arrays need to be the same size\n\n"; - - exit ( 1 ); - - } - - } // for j - - for (j=0; j " - << "When matching is disabled (match_flag = " - << matchtype_to_string(match_flag) - << ") but merging is requested (fcst_merge_flag = " - << mergetype_to_string(fcst_array[j].merge_flag) - << ", obs_merge_flag = " - << mergetype_to_string(obs_array[j].merge_flag) - << ") any merging information will be discarded.\n\n"; - } - - } - // Conf: max_centroid_dist max_centroid_dist = conf.lookup_double(conf_key_max_centroid_dist); @@ -414,7 +271,6 @@ PlotInfo plot_info; mask_poly_flag = int_to_fieldtype(conf.lookup_int(conf_key_mask_poly_flag)); // Conf: weight - dict = conf.lookup_dictionary(conf_key_weight); // Parse the weights @@ -513,14 +369,6 @@ PlotInfo plot_info; met_data_dir = replace_path(conf.lookup_string(conf_key_met_data_dir).c_str()); - // Conf: fcst_raw_plot - - fcst_array->raw_pi = parse_conf_plot_info(conf.lookup_dictionary(conf_key_fcst_raw_plot)); - - // Conf: obs_raw_plot - - obs_array->raw_pi = parse_conf_plot_info(conf.lookup_dictionary(conf_key_obs_raw_plot)); - // Conf: object_plot object_pi = parse_conf_plot_info(conf.lookup_dictionary(conf_key_object_plot)); @@ -549,14 +397,274 @@ PlotInfo plot_info; output_prefix = conf.lookup_string(conf_key_output_prefix); + if (data_type == ModeDataType_MvMode_Fcst) { + + process_config_fcst(ftype); + + } else if (data_type == ModeDataType_MvMode_Obs) { + + process_config_obs(otype); + + } else { + + process_config_both(ftype, otype); + } +} + +//////////////////////////////////////////////////////////////////////// + + +void ModeConfInfo::process_config_both(GrdFileType ftype, GrdFileType otype) +{ + int j, k, n; + + + Dictionary * fcst_dict = (Dictionary *) 0; + Dictionary * obs_dict = (Dictionary *) 0; + + // Conf: fcst and obs + + fcst_dict = conf.lookup_dictionary(conf_key_fcst); + obs_dict = conf.lookup_dictionary(conf_key_obs); + // Conf: shift_right - shift_right = fcst_dict->lookup_int(conf_key_shift_right); + shift_right = fcst_dict->lookup_int(conf_key_shift_right); + + + read_fields (fcst_array, fcst_dict, ftype, 'F'); // the order is important here + read_fields ( obs_array, obs_dict, otype, 'O'); // the order is important here + Fcst = fcst_array; // + 0 + Obs = obs_array; // + 0 + + // Dump the contents of the VarInfo objects + + if(mlog.verbosity_level() >= 5) { + for (j=0; jdump(cout); + } + for (j=0; jdump(cout); + } // for j + } + + for (j=0; j " + << "fcst and obs convolution radius arrays need to be the same size for traditional mode\n\n"; + exit ( 1 ); + } + if ( fcst_array[j].conv_thresh_array.n_elements() != obs_array[j].conv_thresh_array.n_elements() ) { + + mlog << Error << "\nModeConfInfo::process_config_both() -> " + << "fcst and obs convolution threshold arrays need to be the same size\n\n"; + exit ( 1 ); + } + } + } + + // Conf: fcst_raw_plot + + fcst_array->raw_pi = parse_conf_plot_info(conf.lookup_dictionary(conf_key_fcst_raw_plot)); + + // Conf: obs_raw_plot + + obs_array->raw_pi = parse_conf_plot_info(conf.lookup_dictionary(conf_key_obs_raw_plot)); + + return; + +} + +//////////////////////////////////////////////////////////////////////// + + +void ModeConfInfo::process_config_fcst(GrdFileType ftype) +{ + int j, k, n; + + Dictionary * fcst_dict = (Dictionary *) 0; + + fcst_dict = conf.lookup_dictionary(conf_key_fcst); + shift_right = fcst_dict->lookup_int(conf_key_shift_right); + + read_fields (fcst_array, fcst_dict, ftype, 'F'); // the order is important here + Fcst = fcst_array; // + 0 + + + // Dump the contents of the VarInfo objects + + if(mlog.verbosity_level() >= 5) { + for (j=0; jdump(cout); + } // for j + } + + for (j=0; jraw_pi = parse_conf_plot_info(conf.lookup_dictionary(conf_key_fcst_raw_plot)); + + return; + +} + +//////////////////////////////////////////////////////////////////////// + + +void ModeConfInfo::process_config_obs(GrdFileType otype) +{ + int j, k, n; + + Dictionary * obs_dict = (Dictionary *) 0; + + obs_dict = conf.lookup_dictionary(conf_key_obs); + shift_right = obs_dict->lookup_int(conf_key_shift_right); + + read_fields ( obs_array, obs_dict, otype, 'O'); // the order is important here + Obs = obs_array; // + 0 + + + // Dump the contents of the VarInfo objects + + if(mlog.verbosity_level() >= 5) { + for (j=0; jdump(cout); + } // for j + } + + for (j=0; jraw_pi = parse_conf_plot_info(conf.lookup_dictionary(conf_key_obs_raw_plot)); return; } +//////////////////////////////////////////////////////////////////////// + + +void ModeConfInfo::evaluate_fcst_settings(int j) +{ + // No support for wind direction + if(fcst_array[j].var_info->is_wind_direction()) { + mlog << Error << "\nModeConfInfo::evaluate_fcst_settings(" << j << ") -> " + << "the wind direction field may not be verified " + << "using MODE.\n\n"; + exit(1); + } + + // Check that fcst_conv_radius values are non-negative + int n = fcst_array[j].conv_radius_array.n_elements(); + + for (int k=0; k " + << "fcst_conv_radius (" << fcst_array[j].conv_radius_array[k] + << ") must be non-negative\n\n"; + + exit(1); + + } + + } // for k + + if ( fcst_array[j].conv_radius_array.n_elements() == 1 ) fcst_array[j].conv_radius = fcst_array[j].conv_radius_array[0]; + if ( fcst_array[j].conv_thresh_array.n_elements() == 1 ) fcst_array[j].conv_thresh = fcst_array[j].conv_thresh_array[0]; + if ( fcst_array[j].need_merge_thresh() && (fcst_array[j].merge_thresh_array.n_elements() != fcst_array[j].conv_thresh_array.n_elements()) ) { + + mlog << Error << "\nModeConfInfo::evaluate_fcst_settings(" << j << ") -> " + << "fcst conv thresh and fcst merge thresh arrays need to be the same size\n\n"; + + exit ( 1 ); + } + + if ( fcst_array[j].merge_thresh_array.n_elements() == 1 ) fcst_array[j].merge_thresh = fcst_array[j].merge_thresh_array[0]; + + if(match_flag == MatchType_None && fcst_array[j].merge_flag != MergeType_None) { + mlog << Warning << "\nModeConfInfo::evaluate_fcst_settings(" << j << ") -> " + << "When matching is disabled (match_flag = " + << matchtype_to_string(match_flag) + << ") but merging is requested (fcst_merge_flag = " + << mergetype_to_string(fcst_array[j].merge_flag) + << ") any merging information will be discarded.\n\n"; + } +} + + +//////////////////////////////////////////////////////////////////////// + + +void ModeConfInfo::evaluate_obs_settings(int j) +{ + // No support for wind direction + if(obs_array[j].var_info->is_wind_direction()) { + mlog << Error << "\nModeConfInfo::evaluate_obs_settings(" << j << ") -> " + << "the wind direction field may not be verified " + << "using MODE.\n\n"; + exit(1); + } + + // Check that obs_conv_radius values are non-negative + int n = obs_array[j].conv_radius_array.n_elements(); + for (int k=0; k " + << "obs_conv_radius (" << obs_array[j].conv_radius_array[k] + << ") must be non-negative\n\n"; + + exit(1); + } + } // for k + + if ( obs_array[j].conv_radius_array.n_elements() == 1 ) obs_array[j].conv_radius = obs_array[j].conv_radius_array[0]; + if ( obs_array[j].conv_thresh_array.n_elements() == 1 ) obs_array[j].conv_thresh = obs_array[j].conv_thresh_array[0]; + + if ( obs_array[j].need_merge_thresh() && (obs_array[j].merge_thresh_array.n_elements() != obs_array[j].conv_thresh_array.n_elements()) ) { + + mlog << Error << "\nModeConfInfo::evaluate_obs_settings(" << j << ") -> " + << "obs conv thresh and obs merge thresh arrays need to be the same size\n\n"; + + exit ( 1 ); + + } + + if ( obs_array[j].merge_thresh_array.n_elements() == 1 ) obs_array[j].merge_thresh = obs_array[j].merge_thresh_array[0]; + + // Check that match_flag is set between 0 and 3 + if(match_flag == MatchType_None && obs_array[j].merge_flag != MergeType_None) { + mlog << Warning << "\nModeConfInfo::evaluate_obs_settings(" << j << ") -> " + << "When matching is disabled (match_flag = " + << matchtype_to_string(match_flag) + << ") but merging is requested (obs_merge_flag = " + << mergetype_to_string(obs_array[j].merge_flag) + << ") any merging information will be discarded.\n\n"; + } +} //////////////////////////////////////////////////////////////////////// @@ -587,16 +695,22 @@ if ( field->is_array() ) { const DictionaryEntry * e = 0; const Dictionary & D = *field; - if ( (N_fields > 0) && (N != N_fields) ) { - - mlog << Error - << "\nModeConfInfo::read_field_dict() -> fcst and obs dictionaries have different number of entries\n\n"; - - exit ( 1 ); + if (data_type == ModeDataType_Traditional) { + // traditional mode, extra test + if ( (N_fields_f > 0) && (N != N_fields_f) ) { + mlog << Error + << "\nModeConfInfo::read_fields() -> fcst and obs dictionaries have different number of entries in traditional mode" + << ", not allowed\n\n"; + exit ( 1 ); + } + } + + if (_fo == 'F') { + N_fields_f = N; + } else { + N_fields_o = N; } - N_fields = N; - for (j=0; jis_array() ) { if ( (e->type() != DictionaryType) && (e->type() != ArrayType) ) { mlog << Error - << "\nModeConfInfo::read_field_dict() -> field entry # " << (j + 1) << " is not a dictionary!\n\n"; + << "\nModeConfInfo::read_fields() -> field entry # " << (j + 1) << " is not a dictionary!\n\n"; exit ( 1 ); @@ -633,7 +747,8 @@ if ( field->is_array() ) { // nope, traditional mode // -N_fields = N; +N_fields_f = N; +N_fields_o = N; info_array[0].set(false, 0, dict, &conf, type, _fo); // @@ -688,8 +803,41 @@ return ( pwl_if ); void ModeConfInfo::set_field_index(int k) { + if (data_type == ModeDataType_MvMode_Obs) { + if ( (k < 0) || (k >= N_fields_o) ) { + mlog << Error + << "\nModeConfInfo::set_field_index(int) -> range check error\n\n"; + exit ( 1 ); + } + Field_Index_o = k; + Field_Index_f = -1; + Obs = obs_array + k; + } + else if (data_type == ModeDataType_MvMode_Fcst) { + if ( (k < 0) || (k >= N_fields_f) ) { + mlog << Error + << "\nModeConfInfo::set_field_index(int) -> range check error\n\n"; + exit ( 1 ); + } + Field_Index_f = k; + Field_Index_o = -1; + Fcst = fcst_array + k; + } else { + // set obs and fcst index values the same + set_field_index(k, k); + } + return; +} + -if ( (k < 0) || (k >= N_fields) ) { +//////////////////////////////////////////////////////////////////////// + + +void ModeConfInfo::set_field_index(int f_index, int o_index) + +{ +if ( (f_index < 0) || (f_index >= N_fields_f) || (o_index < 0) || + (o_index >= N_fields_o)) { mlog << Error << "\nModeConfInfo::set_field_index(int) -> range check error\n\n"; @@ -698,11 +846,15 @@ if ( (k < 0) || (k >= N_fields) ) { } -Field_Index = k; - -Fcst = fcst_array + k; - Obs = obs_array + k; +Field_Index_f = f_index; +Field_Index_o = o_index; +if (data_type != ModeDataType_MvMode_Fcst) { + Obs = obs_array + o_index; +} +if (data_type != ModeDataType_MvMode_Obs) { + Fcst = fcst_array + f_index; +} return; } @@ -762,9 +914,59 @@ void ModeConfInfo::set_perc_thresh(const DataPlane &f_dp, &(Obs->merge_thresh_array)); return; - } +//////////////////////////////////////////////////////////////////////// + +void ModeConfInfo::set_perc_thresh(const DataPlane &dp) +{ + // + // Compute percentiles for forecast or observation thresholds. + // + Mode_Field_Info *F; + + if (data_type == ModeDataType_MvMode_Obs) { + F = Obs; + } else if (data_type == ModeDataType_MvMode_Fcst) { + F = Fcst; + } else { + mlog << Warning + << "\nModeConfInfo::set_perc_thresh() -> " + << "Logic error wrong method called expect obs only or fcst only, got " + << sprintModeDataType(data_type) << "\n'n"; + return; + } + if( !(F->conv_thresh_array.need_perc() ) && + !(F->merge_thresh_array.need_perc() ) ) { + return; + } + + // + // Sort the input array + // + NumArray sort; + int nxy = dp.nx() * dp.ny(); + + sort.extend(nxy); + + for(int i=0; iconv_thresh_array.set_perc(&sort, &sort, (NumArray *) 0, + &(F->conv_thresh_array), + &(F->conv_thresh_array)); + F->merge_thresh_array.set_perc(&sort, &sort, (NumArray *) 0, + &(F->merge_thresh_array), + &(F->merge_thresh_array)); + return; + +} //////////////////////////////////////////////////////////////////////// @@ -837,31 +1039,29 @@ return; //////////////////////////////////////////////////////////////////////// - void ModeConfInfo::set_conv_radius_by_index(int k) { - - // - // we already know that the fcst and obs radius arrays have - // the same number of elements - // - -if ( (k < 0) || (k >= Fcst->conv_radius_array.n_elements()) ) { - - mlog << Error - << "\nModeConfInfo::set_conv_radius_by_index(int) -> " - << "range check error\n\n"; - - exit ( 1 ); - -} - -Fcst->conv_radius = Fcst->conv_radius_array[k]; -Obs->conv_radius = Obs->conv_radius_array[k]; - -return; - + if (data_type != ModeDataType_MvMode_Obs) { + if ( (k < 0) || (k >= Fcst->conv_radius_array.n_elements()) ) { + mlog << Error + << "\nModeConfInfo::set_conv_radius_by_index(int) -> " + << "range check error\n\n"; + exit ( 1 ); + } + Fcst->conv_radius = Fcst->conv_radius_array[k]; + } + if (data_type != ModeDataType_MvMode_Fcst) { + if ( (k < 0) || (k >= Obs->conv_radius_array.n_elements()) ) { + + mlog << Error + << "\nModeConfInfo::set_conv_radius_by_index(int) -> " + << "range check error\n\n"; + exit ( 1 ); + } + Obs->conv_radius = Obs->conv_radius_array[k]; + } + return; } @@ -870,72 +1070,116 @@ return; void ModeConfInfo::set_conv_thresh(SingleThresh s) { -Fcst->conv_thresh = s; -Obs->conv_thresh = s; + if (data_type != ModeDataType_MvMode_Obs) { + Fcst->conv_thresh = s; + } + if (data_type != ModeDataType_MvMode_Fcst) { + Obs->conv_thresh = s; + } } //////////////////////////////////////////////////////////////////////// void ModeConfInfo::set_conv_radius(int r) { -Fcst->conv_radius = r; -Obs->conv_radius = r; + if (data_type != ModeDataType_MvMode_Obs) { + Fcst->conv_radius = r; + } + if (data_type != ModeDataType_MvMode_Fcst) { + Obs->conv_radius = r; + } } //////////////////////////////////////////////////////////////////////// - void ModeConfInfo::set_conv_thresh_by_index(int k) { + if (data_type != ModeDataType_MvMode_Fcst) { + if ( (k < 0) || (k >= Obs->conv_thresh_array.n_elements()) ) { + mlog << Error + << "\nModeConfInfo::set_conv_thresh_by_index(int) -> " + << "range check error\n\n"; + exit ( 1 ); + } + Obs->conv_thresh = Obs->conv_thresh_array[k]; + } + if (data_type != ModeDataType_MvMode_Obs) { + if ( (k < 0) || (k >= Fcst->conv_thresh_array.n_elements()) ) { + + mlog << Error + << "\nModeConfInfo::set_conv_thresh_by_index(int) -> " + << "range check error\n\n"; + exit ( 1 ); + } + Fcst->conv_thresh = Fcst->conv_thresh_array[k]; + } + return; +} - // - // we already know that the fcst and obs threshold arrays have - // the same number of elements - // -if ( (k < 0) || (k >= Fcst->conv_thresh_array.n_elements()) ) { +//////////////////////////////////////////////////////////////////////// - mlog << Error - << "\nModeConfInfo::set_conv_thresh_by_index(int) -> " - << "range check error\n\n"; +void ModeConfInfo::set_merge_thresh_by_index(int k) +{ + if (data_type != ModeDataType_MvMode_Fcst) { + if ( Obs->need_merge_thresh () ) set_obs_merge_thresh_by_index (k); + } + if (data_type != ModeDataType_MvMode_Obs) { + if ( Fcst->need_merge_thresh () ) set_fcst_merge_thresh_by_index (k); + } +} - exit ( 1 ); +//////////////////////////////////////////////////////////////////////// -} -Fcst->conv_thresh = Fcst->conv_thresh_array[k]; - Obs->conv_thresh = Obs->conv_thresh_array[k]; +void ModeConfInfo::set_fcst_merge_thresh_by_index(int k) -return; +{ + if (data_type == ModeDataType_MvMode_Obs) + { + mlog << Error + << "\nModeConfInfo::set_fcst_merge_thresh_by_index(int) -> " + << "software is set for obs data not fcst\n\n"; + exit (1); + } + Fcst->set_merge_thresh_by_index(k); + return; } -//////////////////////////////////////////////////////////////////////// - -void ModeConfInfo::set_fcst_merge_thresh_by_index(int k) -{ - -Fcst->set_merge_thresh_by_index(k); +//////////////////////////////////////////////////////////////////////// -return; +void ModeConfInfo::set_conv_thresh_by_merge_index(int k) +{ + if (data_type != ModeDataType_MvMode_Fcst) { + if (Obs->need_merge_thresh()) set_obs_conv_thresh_by_merge_index (k); + } + if (data_type != ModeDataType_MvMode_Obs) { + if (Fcst->need_merge_thresh()) set_fcst_conv_thresh_by_merge_index (k); + } } - //////////////////////////////////////////////////////////////////////// void ModeConfInfo::set_fcst_conv_thresh_by_merge_index(int k) { + if (data_type == ModeDataType_MvMode_Obs) + { + mlog << Error + << "\nModeConfInfo::set_fcst_conv_thresh_by_merge_index(int) -> " + << "software is set for obs data not fcst\n\n"; + exit (1); + } + Fcst->set_conv_thresh_by_merge_index(k); -Fcst->set_conv_thresh_by_merge_index(k); - -return; + return; } @@ -946,10 +1190,15 @@ return; void ModeConfInfo::set_obs_conv_thresh_by_merge_index(int k) { - -Obs->set_conv_thresh_by_merge_index(k); - -return; + if (data_type == ModeDataType_MvMode_Fcst) + { + mlog << Error + << "\nModeConfInfo::set_obs_conv_thresh_by_merge_index(int) -> " + << "software is set for fcst data not obs\n\n"; + exit (1); + } + Obs->set_conv_thresh_by_merge_index(k); + return; } @@ -958,28 +1207,56 @@ return; void ModeConfInfo::set_fcst_merge_flag(MergeType t) { -Fcst->merge_flag = t; + if (data_type == ModeDataType_MvMode_Obs) + { + mlog << Error + << "\nModeConfInfo::set_fcst_merge_flag(int) -> " + << "software is set for obs data not fcst\n\n"; + exit (1); + } + Fcst->merge_flag = t; } //////////////////////////////////////////////////////////////////////// void ModeConfInfo::set_obs_merge_flag(MergeType t) { -Obs->merge_flag = t; + if (data_type == ModeDataType_MvMode_Fcst) + { + mlog << Error + << "\nModeConfInfo::set_obs_merge_flag(int) -> " + << "software is set for fcst data not obs\n\n"; + exit (1); + } + Obs->merge_flag = t; } //////////////////////////////////////////////////////////////////////// void ModeConfInfo::set_fcst_merge_thresh(SingleThresh s) { -Fcst->merge_thresh = s; + if (data_type == ModeDataType_MvMode_Obs) + { + mlog << Error + << "\nModeConfInfo::set_fcst_merge_thresh(int) -> " + << "software is set for obs data not fcst\n\n"; + exit (1); + } + Fcst->merge_thresh = s; } //////////////////////////////////////////////////////////////////////// void ModeConfInfo::set_obs_merge_thresh(SingleThresh s) { -Obs->merge_thresh = s; + if (data_type == ModeDataType_MvMode_Fcst) + { + mlog << Error + << "\nModeConfInfo::set_obs_merge_thresh(int) -> " + << "software is set for fcst data not obs\n\n"; + exit (1); + } + Obs->merge_thresh = s; } //////////////////////////////////////////////////////////////////////// @@ -988,13 +1265,25 @@ Obs->merge_thresh = s; void ModeConfInfo::set_obs_merge_thresh_by_index(int k) { + if (data_type == ModeDataType_MvMode_Fcst) + { + mlog << Error + << "\nModeConfInfo::set_obs_merge_thresh_by_index(int) -> " + << "software is set for fcst data not obs\n\n"; + exit (1); + } -Obs->set_merge_thresh_by_index(k); + Obs->set_merge_thresh_by_index(k); + return; +} -return; +//////////////////////////////////////////////////////////////////////// -} +void ModeConfInfo::set_data_type(ModeDataType type) +{ + data_type = type; +} //////////////////////////////////////////////////////////////////////// @@ -1062,11 +1351,20 @@ Dictionary * dict = (Dictionary *) 0; fcst_multivar_logic.clear(); obs_multivar_logic.clear(); +fcst_multivar_compare_index.clear(); +obs_multivar_compare_index.clear(); fcst_multivar_name = default_multivar_name; obs_multivar_name = default_multivar_name; fcst_multivar_level = na_str; obs_multivar_level = na_str; +// this has to be outside the fcst and obs dictionaries +if ( conf.lookup(conf_key_fcst_multivar_compare_index)) fcst_multivar_compare_index = conf.lookup_int_array(conf_key_fcst_multivar_compare_index); + +// this has to be outside the fcst and obs dictionaries +if ( conf.lookup(conf_key_obs_multivar_compare_index)) obs_multivar_compare_index = conf.lookup_int_array(conf_key_obs_multivar_compare_index); + + dict = conf.lookup_dictionary(conf_key_fcst); if ( dict->lookup(conf_key_multivar_logic) ) fcst_multivar_logic = dict->lookup_string(conf_key_multivar_logic); @@ -1079,8 +1377,6 @@ if ( dict->lookup(conf_key_multivar_logic) ) obs_multivar_logic = dict->lookup_s if ( dict->lookup(conf_key_multivar_name) ) obs_multivar_name = dict->lookup_string(conf_key_multivar_name); if ( dict->lookup(conf_key_multivar_level) ) obs_multivar_level = dict->lookup_string(conf_key_multivar_level); -multivar_intensity.clear(); -if ( dict->lookup(conf_key_multivar_intensity_flag)) multivar_intensity = dict->lookup_bool_array(conf_key_multivar_intensity_flag); return; } @@ -1097,37 +1393,39 @@ void ModeConfInfo::check_multivar_not_implemented() bool status = false; if (quilt) { mlog << Error - << "\nModeConfInfo::multivar_not_implemented:\n" + << "\nModeConfInfo::check_multivar_not_implemented():\n" << " quilting not yet implemented for multivar mode\n\n"; status = true; } - for (int i=0; iconv_thresh_array.n(); ++j) { + if (Fcst->conv_thresh_array[j].get_ptype() == perc_thresh_sample_obs) { + mlog << Warning + << "\nModeConfInfo::check_multivar_perc_thresh:\n" + << " Thresholding with 'SOP' in a forecast input not well defined for multivariate mode simple object creation\n" + << " 'SFP' will be used as a replacement\n\n"; + } + } + } else if (data_type == ModeDataType_MvMode_Obs) { + for (int j=0; j< Obs->conv_thresh_array.n(); ++j) { + if (Obs->conv_thresh_array[j].get_ptype() == perc_thresh_sample_fcst) { + mlog << Warning + << "\nModeConfInfo::check_multivar_perc_thresh:\n" + << " Thresholding with 'SFP' in an obs input not well defined for multivariate mode simple object creation\n" + << " 'SOP' will be used as a replacement\n\n"; + } + } + } + } + + if (isSimpleMerge) { + if (data_type == ModeDataType_MvMode_Fcst) { + for (int j=0; j< Fcst->merge_thresh_array.n(); ++j) { + if (Fcst->merge_thresh_array[j].get_ptype() == perc_thresh_sample_obs) { + mlog << Warning + << "\nModeConfInfo::check_multivar_perc_thresh:\n" + << " Thresholding with 'SOP' in a forecast input not well defined for multivariate mode simple object creation\n" + << " 'SFP' will be used as a replacement\n\n"; + } + } + } else if (data_type == ModeDataType_MvMode_Obs) { + for (int j=0; j< Obs->merge_thresh_array.n(); ++j) { + if (Obs->merge_thresh_array[j].get_ptype() == perc_thresh_sample_fcst) { + mlog << Warning + << "\nModeConfInfo::check_multivar_perc_thresh():\n" + << " Thresholding with 'SFP' in an obs input not well defined for multivariate mode simple object creation\n" + << " 'SOP' will be used as a replacement\n\n"; + } + } } } - return true; } //////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_shapedata/mode_conf_info.h b/src/libcode/vx_shapedata/mode_conf_info.h index 7d8aaf6f97..115112cd45 100644 --- a/src/libcode/vx_shapedata/mode_conf_info.h +++ b/src/libcode/vx_shapedata/mode_conf_info.h @@ -24,6 +24,7 @@ #include "vx_math.h" #include "mode_field_info.h" +#include "mode_data_type.h" //////////////////////////////////////////////////////////////////////// @@ -68,11 +69,10 @@ class ModeConfInfo { void init_from_scratch(); - int Field_Index; - - int N_fields; // = 1 for traditional MODE - // > 1 for multivar MODE - // should always be at least 1 + int Field_Index_f; // for traditional mode expect Field_index_f/_o to be the same + int Field_Index_o; + int N_fields_f; // for traditional mode expect N_fields_f/_o to be the same + int N_fields_o; public: @@ -82,15 +82,21 @@ class ModeConfInfo { void clear(); + // sets both obs and fcst field indices if traditional mode, or mvmode 'both' void set_field_index(int); - int field_index() const; + // must be multivar mode if the two indices are not the same + void set_field_index(int fcst_index, int obs_index); + + int field_index_f() const; + int field_index_o() const; bool is_multivar(); - ConcatString fcst_multivar_logic; - ConcatString obs_multivar_logic; - BoolArray multivar_intensity; + ConcatStringfcst_multivar_logic; + ConcatString obs_multivar_logic; + IntArray fcst_multivar_compare_index; + IntArray obs_multivar_compare_index; ConcatString fcst_multivar_name; ConcatString fcst_multivar_level; ConcatString obs_multivar_name; @@ -99,7 +105,8 @@ class ModeConfInfo { void get_multivar_programs(); void check_multivar_not_implemented(); - bool multivar_intensities_all_false() const; + + void check_multivar_perc_thresh(bool isSimple, bool isSimpleMerge) const; ///////////////////////////////////////////////////////////////////// @@ -111,6 +118,12 @@ class ModeConfInfo { Mode_Field_Info * Obs; // points to current field, not allocated + // to allow single data (fcst or obs) or fcst/obs pairs, + // and to distinguish traditional mode from mvmode + + ModeDataType data_type; + + ///////////////////////////////////////////////////////////////////// @@ -121,7 +134,8 @@ class ModeConfInfo { MetConfig conf; // MODE configuration object void read_config (const char * default_filename, const char * user_filename); - void process_config (GrdFileType ftype, GrdFileType otype); + + void process_config (GrdFileType ftype, GrdFileType otype, ModeDataType dt=ModeDataType_Traditional); void read_fields (Mode_Field_Info * &, Dictionary * dict, GrdFileType, char _fo); @@ -218,11 +232,15 @@ class ModeConfInfo { // void set_perc_thresh(const DataPlane &, const DataPlane &); + void set_perc_thresh(const DataPlane &); void parse_nc_info (); + // might need addtional methods here for pass2 multivariate, if/when we allow more than 1 radius void set_conv_radius_by_index (int); + // might need addtional methods here for pass2 multivariate, if/when we allow more than 1 thresh void set_conv_thresh_by_index (int); + void set_conv_thresh(SingleThresh); void set_conv_radius(int); @@ -231,13 +249,16 @@ class ModeConfInfo { int n_runs() const; // # threshs times # radii - int n_fields() const; // should be 1 for traditional mode, > 1 for muiltivar + int n_fields_f() const; // should be 1 for traditional mode, >= 1 for muiltivar + int n_fields_o() const; // should be 1 for traditional mode, >= 1 for muiltivar int get_compression_level(); + void set_merge_thresh_by_index(int); void set_fcst_merge_thresh_by_index (int); void set_obs_merge_thresh_by_index (int); + void set_conv_thresh_by_merge_index(int); void set_fcst_conv_thresh_by_merge_index (int); void set_obs_conv_thresh_by_merge_index (int); @@ -246,23 +267,54 @@ class ModeConfInfo { void set_fcst_merge_thresh(SingleThresh); void set_obs_merge_thresh(SingleThresh); + void set_data_type(ModeDataType type); + +private: + + // some private methods + void process_config_both(GrdFileType ftype, GrdFileType otype); + void process_config_fcst(GrdFileType ftype); + void process_config_obs(GrdFileType otype); + void evaluate_fcst_settings(int); + void evaluate_obs_settings(int); + }; //////////////////////////////////////////////////////////////////////// -inline int ModeConfInfo::n_conv_radii() const { return ( Fcst->conv_radius_array.n_elements() ); } // should be the same as - // obs_conv_radius_array.n_elements() - -inline int ModeConfInfo::n_conv_threshs() const { return ( Fcst->conv_thresh_array.n_elements() ); } // should be the same as - // obs_conv_thresh_array.n_elements() +inline int ModeConfInfo::n_conv_radii() const +{ + // this could break down if multivar mode relaxes + // its limitations on number of radii (obs and fcst could be different) + if (data_type == ModeDataType_MvMode_Obs) + { + return ( Obs->conv_radius_array.n_elements() ); + } else { + return ( Fcst->conv_radius_array.n_elements() ); + } +} + +inline int ModeConfInfo::n_conv_threshs() const +{ + // this could break down if multivar mode relaxes + // its limitations on number of thresh (obs and fcst could be different) + if (data_type == ModeDataType_MvMode_Obs) + { + return ( Obs->conv_thresh_array.n_elements() ); + } else { + return ( Fcst->conv_thresh_array.n_elements() ); + } +} inline int ModeConfInfo::get_compression_level() { return conf.nc_compression(); } -inline int ModeConfInfo::field_index() const { return Field_Index; } +inline int ModeConfInfo::field_index_f() const { return Field_Index_f; } +inline int ModeConfInfo::field_index_o() const { return Field_Index_o; } -inline int ModeConfInfo::n_fields() const { return N_fields; } +inline int ModeConfInfo::n_fields_f() const { return N_fields_f; } +inline int ModeConfInfo::n_fields_o() const { return N_fields_o; } //////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_shapedata/mode_data_type.h b/src/libcode/vx_shapedata/mode_data_type.h new file mode 100644 index 0000000000..92a2686af2 --- /dev/null +++ b/src/libcode/vx_shapedata/mode_data_type.h @@ -0,0 +1,50 @@ +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +// ** Copyright UCAR (c) 1992 - 2023 +// ** University Corporation for Atmospheric Research (UCAR) +// ** National Center for Atmospheric Research (NCAR) +// ** Research Applications Lab (RAL) +// ** P.O.Box 3000, Boulder, Colorado, 80307-3000, USA +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* + +/////////////////////////////////////////////////////////////////////////////// + + +#ifndef __MODE_DATA_TYPE_H__ +#define __MODE_DATA_TYPE_H__ + +#include +using std::string; + +/////////////////////////////////////////////////////////////////////////////// + + +enum ModeDataType +{ + ModeDataType_Traditional, // default + ModeDataType_MvMode_Obs, // mvmode, obs data only + ModeDataType_MvMode_Fcst, // mvmode, fcst data only + ModeDataType_MvMode_Both // mvmode, fcst and obs +}; + + +/////////////////////////////////////////////////////////////////////////////// + +inline string sprintModeDataType(ModeDataType type) +{ + switch (type) + { + case ModeDataType_MvMode_Obs: + return "MvMode_Obs"; + case ModeDataType_MvMode_Fcst: + return "MvMode_Fcst"; + case ModeDataType_MvMode_Both: + return "MvMode_Both"; + case ModeDataType_Traditional: + default: + return "TraditionalMode"; + } +} + +#endif + +/////////////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_shapedata/mode_field_info.cc b/src/libcode/vx_shapedata/mode_field_info.cc index 06311f5d47..8dd024e803 100644 --- a/src/libcode/vx_shapedata/mode_field_info.cc +++ b/src/libcode/vx_shapedata/mode_field_info.cc @@ -200,7 +200,7 @@ gft = type; if ( dict->lookup(conf_key_raw_thresh) ) { mlog << Error - << "\nMode_Field_Info::process_config() -> " + << "\nMode_Field_Info::set() -> " << "the \"" << conf_key_raw_thresh << "\" entry is deprecated in MET " << met_version << "! Use \"" << conf_key_censor_thresh << "\" and \"" << conf_key_censor_val << "\" instead.\n\n"; @@ -353,7 +353,7 @@ void Mode_Field_Info::set_merge_thresh_by_index (int k) if ( (k < 0) || (k >= merge_thresh_array.n_elements()) ) { - mlog << Error << "\nMode_Field_Info::set_fcst_merge_thresh_by_index(int) -> " + mlog << Error << "\nMode_Field_Info::set_merge_thresh_by_index(int) -> " << "range check error\n\n"; exit ( 1 ); diff --git a/src/libcode/vx_statistics/apply_mask.cc b/src/libcode/vx_statistics/apply_mask.cc index 2b0fbcfee3..c515baf4b3 100644 --- a/src/libcode/vx_statistics/apply_mask.cc +++ b/src/libcode/vx_statistics/apply_mask.cc @@ -50,6 +50,7 @@ Grid parse_vx_grid(const RegridInfo info, const Grid *fgrid, const Grid *ogrid) exit(1); } else { + mlog << Debug(2) << "Using the forecast grid as the verification grid\n"; vx_grid = *fgrid; } } @@ -59,19 +60,19 @@ Grid parse_vx_grid(const RegridInfo info, const Grid *fgrid, const Grid *ogrid) // Verify on the forecast grid if(info.field == FieldType_Fcst) { - mlog << Debug(3) - << "Use the forecast grid.\n"; + mlog << Debug(2) << "Using the forecast grid as the verification grid\n"; vx_grid = *fgrid; } // Verify on the observation grid else if(info.field == FieldType_Obs) { - mlog << Debug(3) - << "Use the observation grid.\n"; + mlog << Debug(2) << "Using the observation grid as the verification grid\n"; vx_grid = *ogrid; } // Parse a named grid, grid specification string, // or gridded data file else { + mlog << Debug(2) << "Using named grid as the verification grid. " + << "Name=" << info.name << "\n"; parse_grid_mask(info.name, vx_grid); } } diff --git a/src/tools/core/mode/mode.cc b/src/tools/core/mode/mode.cc index a9277a0884..b7277b0110 100644 --- a/src/tools/core/mode/mode.cc +++ b/src/tools/core/mode/mode.cc @@ -195,7 +195,7 @@ int met_main(int argc, char * argv []) // run the traditional version of mode ModeFrontEnd *frontend = new ModeFrontEnd; - status = frontend->run(Argv); + status = frontend->run_traditional(Argv); if ( frontend ) { delete frontend; frontend = 0; } } diff --git a/src/tools/core/mode/mode_exec.cc b/src/tools/core/mode/mode_exec.cc index f927b637be..82cb261b11 100644 --- a/src/tools/core/mode/mode_exec.cc +++ b/src/tools/core/mode/mode_exec.cc @@ -60,12 +60,12 @@ static void replaceAll(std::string& str, const std::string& from, const std::str /////////////////////////////////////////////////////////////////////// - -ModeExecutive::ModeExecutive() +ModeExecutive::ModeExecutive(Processing_t p) { init_from_scratch(); + ptype = p; } @@ -132,6 +132,8 @@ void ModeExecutive::clear() R_index = T_index = 0; + ptype = TRADITIONAL; + // // done // @@ -144,7 +146,7 @@ void ModeExecutive::clear() /////////////////////////////////////////////////////////////////////// -void ModeExecutive::init(int n_files, bool isMultivar) +void ModeExecutive::init_traditional(int n_files) { @@ -152,25 +154,68 @@ void ModeExecutive::init(int n_files, bool isMultivar) R_index = T_index = 0; - // Create the default config file name - if (isMultivar) { - default_config_file = replace_path(default_multivar_config_filename); - } else { - default_config_file = replace_path(default_config_filename); + conf_read(default_config_filename); + + // Get the forecast and observation file types from config, if present + ftype = parse_conf_file_type(engine.conf_info.conf.lookup_dictionary(conf_key_fcst)); + otype = parse_conf_file_type(engine.conf_info.conf.lookup_dictionary(conf_key_obs)); + + + // Read observation file + if(!(obs_mtddf = mtddf_factory.new_met_2d_data_file(obs_file.c_str(), otype))) { + mlog << Error << "\nTrouble reading observation file \"" + << obs_file << "\"\n\n"; + exit(1); } - // If the merge config file was not set, use the match config file - if(merge_config_file.length() == 0) - merge_config_file = match_config_file; + // Read forecast file + if(!(fcst_mtddf = mtddf_factory.new_met_2d_data_file(fcst_file.c_str(), ftype))) { + mlog << Error << "\nTrouble reading forecast file \"" + << fcst_file << "\"\n\n"; + exit(1); + } - // List the config files + // Store the input data file types + ftype = fcst_mtddf->file_type(); + otype = obs_mtddf->file_type(); + + // Process the configuration + engine.conf_info.process_config(ftype, otype); + int nf = engine.conf_info.n_fields_f(); // same as obs for traditional mode + if (nf != n_files) { + mlog << Error << "\nNumber of input files " << n_files << " Not equal to config number of fields " + << nf << "\n\n"; + exit(1); + } + + const int shift = engine.conf_info.shift_right; + + fcst_mtddf->set_shift_right(shift); + obs_mtddf->set_shift_right(shift); + + // List the input files mlog << Debug(1) - << "Default Config File: " << default_config_file << "\n" - << "Match Config File: " << match_config_file << "\n" - << "Merge Config File: " << merge_config_file << "\n"; + << "Forecast File: " << fcst_file << "\n" + << "Observation File: " << obs_file << "\n"; - // Read the config files - engine.conf_info.read_config(default_config_file.c_str(), match_config_file.c_str()); + engine.conf_info.nc_info.compress_level = engine.conf_info.get_compression_level(); + + return; + +} + +/////////////////////////////////////////////////////////////////////// + + +void ModeExecutive::init_multivar_verif_grid() + +{ + + Met2dDataFileFactory mtddf_factory; + + R_index = T_index = 0; + + conf_read(default_multivar_config_filename); // Get the forecast and observation file types from config, if present ftype = parse_conf_file_type(engine.conf_info.conf.lookup_dictionary(conf_key_fcst)); @@ -196,12 +241,7 @@ void ModeExecutive::init(int n_files, bool isMultivar) otype = obs_mtddf->file_type(); // Process the configuration - engine.conf_info.process_config(ftype, otype); - if (engine.conf_info.n_fields() != n_files) { - mlog << Error << "\nNumber of input files " << n_files << " Not equal to config number of fields " - << engine.conf_info.n_fields() << "\n\n"; - exit(1); - } + engine.conf_info.process_config(ftype, otype, ModeDataType_MvMode_Both); // check one again for multivar problems engine.conf_info.check_multivar_not_implemented(); @@ -224,27 +264,117 @@ void ModeExecutive::init(int n_files, bool isMultivar) /////////////////////////////////////////////////////////////////////// -void ModeExecutive::init_multivar(GrdFileType ftype, GrdFileType otype) +void ModeExecutive::init_multivar_simple(int n_files, ModeDataType dtype) { + Met2dDataFileFactory mtddf_factory; + R_index = T_index = 0; - // Create the default config file name - default_config_file = replace_path(default_multivar_config_filename); + conf_read(default_multivar_config_filename); - // If the merge config file was not set, use the match config file - if(merge_config_file.length() == 0) - merge_config_file = match_config_file; + // tell the engine which type of data it is + engine.set_data_type(dtype); - // List the config files - mlog << Debug(1) - << "Default Config File: " << default_config_file << "\n" - << "Match Config File: " << match_config_file << "\n" - << "Merge Config File: " << merge_config_file << "\n"; + // Get the forecast and observation file types from config, if present + ftype = parse_conf_file_type(engine.conf_info.conf.lookup_dictionary(conf_key_fcst)); + otype = parse_conf_file_type(engine.conf_info.conf.lookup_dictionary(conf_key_obs)); - // Read the config files - engine.conf_info.read_config(default_config_file.c_str(), match_config_file.c_str()); + + // Read observation file or forecast file + if (dtype == ModeDataType_MvMode_Obs) + { + if(!(obs_mtddf = mtddf_factory.new_met_2d_data_file(obs_file.c_str(), otype))) { + mlog << Error << "\nTrouble reading observation file \"" + << obs_file << "\"\n\n"; + exit(1); + + } + // Store the input data file types + otype = obs_mtddf->file_type(); + } + else if (dtype == ModeDataType_MvMode_Fcst) + { + // Read forecast file + if(!(fcst_mtddf = mtddf_factory.new_met_2d_data_file(fcst_file.c_str(), ftype))) { + mlog << Error << "\nTrouble reading forecast file \"" + << fcst_file << "\"\n\n"; + exit(1); + } + // Store the input data file types + ftype = fcst_mtddf->file_type(); + } + else { + mlog << Error << "\nModeExecutive::init_multivar_simple()->" + << "simple object creation requires obs or forecast mode, got " + << sprintModeDataType(dtype) << "\n\n"; + exit(1); + } + + // Process the configuration + engine.conf_info.process_config(ftype, otype, dtype); + int nf; + if (dtype == ModeDataType_MvMode_Obs) { + nf = engine.conf_info.n_fields_o(); + } else if (dtype == ModeDataType_MvMode_Fcst) { + nf = engine.conf_info.n_fields_f(); + } else { + mlog << Error << "\nModeExecutive::init_multivar_simple()->" + << "simple object creation requires obs or forecast mode, got " + << sprintModeDataType(dtype) << "\n\n"; + exit(1); + } + if (nf != n_files) { + mlog << Error << "\nModeExecutive::init_multivar_simple()->" + << "Number of input files " << n_files << " Not equal to config number of fields " + << nf << "\n\n"; + exit(1); + } + + // check one again for multivar problems + engine.conf_info.check_multivar_not_implemented(); + + const int shift = engine.conf_info.shift_right; + + if (dtype != ModeDataType_MvMode_Fcst) { + obs_mtddf->set_shift_right(shift); + } + + if (dtype != ModeDataType_MvMode_Obs) { + fcst_mtddf->set_shift_right(shift); + } + + if (dtype == ModeDataType_MvMode_Obs) { + mlog << Debug(1) + << "Observation File: " << obs_file << "\n"; + + } else if (dtype == ModeDataType_MvMode_Fcst) { + mlog << Debug(1) + << "Forecast File: " << fcst_file << "\n"; + } + else { + // List the input files + mlog << Debug(1) + << "Forecast File: " << fcst_file << "\n" + << "Observation File: " << obs_file << "\n"; + } + + engine.conf_info.nc_info.compress_level = engine.conf_info.get_compression_level(); + + return; + +} + +/////////////////////////////////////////////////////////////////////// + +void ModeExecutive::init_multivar_intensities(GrdFileType ftype, GrdFileType otype) + +{ + + R_index = T_index = 0; + + conf_read(default_multivar_config_filename); // Get the forecast and observation file types from config, if present GrdFileType l_ftype = parse_conf_file_type(engine.conf_info.conf.lookup_dictionary(conf_key_fcst)); @@ -255,7 +385,7 @@ void ModeExecutive::init_multivar(GrdFileType ftype, GrdFileType otype) l_otype = otype; // Process the configuration - engine.conf_info.process_config(l_ftype, l_otype); + engine.conf_info.process_config(l_ftype, l_otype, ModeDataType_MvMode_Both); // check one again for multivar problems engine.conf_info.check_multivar_not_implemented(); @@ -271,10 +401,19 @@ void ModeExecutive::init_multivar(GrdFileType ftype, GrdFileType otype) } + +/////////////////////////////////////////////////////////////////////// + +void ModeExecutive::check_multivar_perc_thresh_settings() +{ + engine.conf_info.check_multivar_perc_thresh(ptype == ModeExecutive::MULTIVAR_SIMPLE, + ptype == ModeExecutive::MULTIVAR_SIMPLE_MERGE); +} + /////////////////////////////////////////////////////////////////////// -void ModeExecutive::setup_fcst_obs_data() +void ModeExecutive::setup_fcst_obs_data_traditional() { @@ -288,7 +427,7 @@ void ModeExecutive::setup_fcst_obs_data() if ( !(fcst_mtddf->data_plane(*(engine.conf_info.Fcst->var_info), Fcst_sd.data)) ) { - mlog << Error << "\nsetup_fcst_obs_data() -> " + mlog << Error << "\nModeExecutive::setup_fcst_obs_data_traditional() -> " << "can't get forecast data \"" << engine.conf_info.Fcst->var_info->magic_str() << "\" from file \"" << fcst_file << "\"\n\n"; @@ -299,7 +438,7 @@ void ModeExecutive::setup_fcst_obs_data() if ( !(obs_mtddf->data_plane(*(engine.conf_info.Obs->var_info), Obs_sd.data)) ) { - mlog << Error << "\nsetup_fcst_obs_data() -> " + mlog << Error << "\nModeExecutive::setup_fcst_obs_data_traditional() -> " << "can't get observation data \"" << engine.conf_info.Obs->var_info->magic_str() << "\" from file \"" << obs_file << "\"\n\n"; @@ -347,7 +486,7 @@ void ModeExecutive::setup_fcst_obs_data() if(Fcst_sd.data.valid() != Obs_sd.data.valid()) { - mlog << Warning << "\nsetup_fcst_obs_data() -> " + mlog << Warning << "\nModeExecutive::setup_fcst_obs_data_traditional() -> " << "Forecast and observation valid times do not match " << unix_to_yyyymmdd_hhmmss(Fcst_sd.data.valid()) << " != " << unix_to_yyyymmdd_hhmmss(Obs_sd.data.valid()) << " for " @@ -355,68 +494,268 @@ void ModeExecutive::setup_fcst_obs_data() << engine.conf_info.Obs->var_info->magic_str() << ".\n\n"; } - // Print a warning if the accumulation intervals do not match + // Print a warning if the accumulation intervals do not match + + if(engine.conf_info.Fcst->var_info->level().type() == LevelType_Accum && + engine.conf_info.Obs->var_info->level().type() == LevelType_Accum && + Fcst_sd.data.accum() != Obs_sd.data.accum()) { + + mlog << Warning << "\nModeExecutive::setup_fcst_obs_data_traditional() -> " + << "Forecast and observation accumulation times do not match " + << sec_to_hhmmss(Fcst_sd.data.valid()) << " != " + << sec_to_hhmmss(Obs_sd.data.valid()) << " for " + << engine.conf_info.Fcst->var_info->magic_str() << " versus " + << engine.conf_info.Obs->var_info->magic_str() << ".\n\n"; + } + + mlog << Debug(1) + << "Forecast Field: " + << engine.conf_info.Fcst->var_info->name_attr() << " at " + << engine.conf_info.Fcst->var_info->level_attr() + << "\n" + << "Observation Field: " + << engine.conf_info.Obs->var_info->name_attr() << " at " + << engine.conf_info.Obs->var_info->level_attr() + << "\n"; + + // Mask out the missing data between fields + + if(engine.conf_info.mask_missing_flag == FieldType_Fcst || + engine.conf_info.mask_missing_flag == FieldType_Both) + mask_bad_data(Fcst_sd.data, Obs_sd.data); + + // Mask out the missing data between fields + + if(engine.conf_info.mask_missing_flag == FieldType_Obs || + engine.conf_info.mask_missing_flag == FieldType_Both) + mask_bad_data(Obs_sd.data, Fcst_sd.data); + + // Parse the grid and/or polyline masks from the configuration + + process_masks(Fcst_sd, Obs_sd); + + // Compute the min and max data values across both raw fields + + Fcst_sd.data.data_range(fmin, fmax); + Obs_sd.data.data_range(omin, omax); + if (!is_bad_data(fmin) && !is_bad_data(omin)) data_min = min(fmin, omin); + else if(!is_bad_data(fmin) && is_bad_data(omin)) data_min = fmin; + else if( is_bad_data(fmin) && !is_bad_data(omin)) data_min = omin; + + if (!is_bad_data(fmax) && !is_bad_data(omax)) data_max = max(fmax, omax); + else if(!is_bad_data(fmax) && is_bad_data(omax)) data_max = fmax; + else if( is_bad_data(fmax) && !is_bad_data(omax)) data_max = omax; + + // Process percentile thresholds + + engine.conf_info.set_perc_thresh(Fcst_sd.data, Obs_sd.data); + + // store the input data units + funits = engine.conf_info.Fcst->var_info->units(); + ounits = engine.conf_info.Obs->var_info->units(); + + // store the input data level + flevel = engine.conf_info.Fcst->var_info->level_name(); + olevel = engine.conf_info.Obs->var_info->level_name(); + + // + // done + // + + return; + +} + +/////////////////////////////////////////////////////////////////////// + + +void ModeExecutive::setup_verification_grid() + +{ + + // ShapeData fcst_sd, obs_sd; + double fmin, omin, fmax, omax; + + Fcst_sd.clear(); + Obs_sd.clear(); + + // Read the gridded data from the input forecast file + + if ( !(fcst_mtddf->data_plane(*(engine.conf_info.Fcst->var_info), Fcst_sd.data)) ) { + + mlog << Error << "\nModeExecutive::setup_verification_grid() -> " + << "can't get forecast data \"" + << engine.conf_info.Fcst->var_info->magic_str() + << "\" from file \"" << fcst_file << "\"\n\n"; + exit(1); + } + + // Read the gridded data from the input observation file + + if ( !(obs_mtddf->data_plane(*(engine.conf_info.Obs->var_info), Obs_sd.data)) ) { + + mlog << Error << "\nModeExecutive::setup_verification_grid() -> " + << "can't get observation data \"" + << engine.conf_info.Obs->var_info->magic_str() + << "\" from file \"" << obs_file << "\"\n\n"; + exit(1); + } + + // Determine the verification grid + + grid = parse_vx_grid(engine.conf_info.Fcst->var_info->regrid(), + &(fcst_mtddf->grid()), &(obs_mtddf->grid())); + + return; +} + +/////////////////////////////////////////////////////////////////////// + + +void ModeExecutive::setup_fcst_data(const Grid &verification_grid) + +{ + + // ShapeData fcst_sd, obs_sd; + double fmin, fmax; + + Fcst_sd.clear(); + + // Read the gridded data from the input forecast file + if ( !(fcst_mtddf->data_plane(*(engine.conf_info.Fcst->var_info), Fcst_sd.data)) ) { + + mlog << Error << "\nModeExecutive::setup_fcst_data() -> " + << "can't get forecast data \"" + << engine.conf_info.Fcst->var_info->magic_str() + << "\" from file \"" << fcst_file << "\"\n\n"; + exit(1); + } + + grid = verification_grid; + + // Store the grid + + engine.set_grid(&grid); + + // Regrid, if necessary + + if ( !(fcst_mtddf->grid() == grid) ) { + mlog << Debug(1) + << "Regridding forecast " << engine.conf_info.Fcst->var_info->magic_str() + << " to the verification grid.\n"; + Fcst_sd.data = met_regrid(Fcst_sd.data, fcst_mtddf->grid(), grid, + engine.conf_info.Fcst->var_info->regrid()); + } + + // Rescale probabilites from [0, 100] to [0, 1] + + if ( engine.conf_info.Fcst->var_info->p_flag() ) rescale_probability(Fcst_sd.data); + + mlog << Debug(1) + << "Forecast Field: " + << engine.conf_info.Fcst->var_info->name_attr() << " at " + << engine.conf_info.Fcst->var_info->level_attr() + << "\n"; + + // Parse the grid and/or polyline masks from the configuration + + process_fcst_masks(Fcst_sd); + + // Compute the min and max data values across both raw fields + + Fcst_sd.data.data_range(fmin, fmax); + data_min = fmin; + data_max = fmax; + + // Process percentile thresholds + + engine.conf_info.set_perc_thresh(Fcst_sd.data); + + // store the input data units + funits = engine.conf_info.Fcst->var_info->units(); + ounits = na_str; + + // store the input data level + flevel = engine.conf_info.Fcst->var_info->level_name(); + olevel = na_str; + + // + // done + // + + return; + +} + +/////////////////////////////////////////////////////////////////////// + + +void ModeExecutive::setup_obs_data(const Grid &verification_grid) + +{ + + // ShapeData fcst_sd, obs_sd; + double omin, omax; + + Obs_sd.clear(); + + // Read the gridded data from the input observation file + + if ( !(obs_mtddf->data_plane(*(engine.conf_info.Obs->var_info), Obs_sd.data)) ) { + + mlog << Error << "\nModeExecutive::setup_obs_data() -> " + << "can't get observation data \"" + << engine.conf_info.Obs->var_info->magic_str() + << "\" from file \"" << obs_file << "\"\n\n"; + exit(1); + } + + grid = verification_grid; - if(engine.conf_info.Fcst->var_info->level().type() == LevelType_Accum && - engine.conf_info.Obs->var_info->level().type() == LevelType_Accum && - Fcst_sd.data.accum() != Obs_sd.data.accum()) { + // Store the grid - mlog << Warning << "\nsetup_fcst_obs_data() -> " - << "Forecast and observation accumulation times do not match " - << sec_to_hhmmss(Fcst_sd.data.valid()) << " != " - << sec_to_hhmmss(Obs_sd.data.valid()) << " for " - << engine.conf_info.Fcst->var_info->magic_str() << " versus " - << engine.conf_info.Obs->var_info->magic_str() << ".\n\n"; + engine.set_grid(&grid); + + // Regrid, if necessary + + if ( !(obs_mtddf->grid() == grid) ) { + mlog << Debug(1) + << "Regridding observation " << engine.conf_info.Obs->var_info->magic_str() + << " to the verification grid.\n"; + Obs_sd.data = met_regrid(Obs_sd.data, obs_mtddf->grid(), grid, + engine.conf_info.Obs->var_info->regrid()); } + // Rescale probabilites from [0, 100] to [0, 1] + + if ( engine.conf_info.Obs->var_info->p_flag() ) rescale_probability(Obs_sd.data); + mlog << Debug(1) - << "Forecast Field: " - << engine.conf_info.Fcst->var_info->name_attr() << " at " - << engine.conf_info.Fcst->var_info->level_attr() - << "\n" << "Observation Field: " << engine.conf_info.Obs->var_info->name_attr() << " at " << engine.conf_info.Obs->var_info->level_attr() << "\n"; - // Mask out the missing data between fields - - if(engine.conf_info.mask_missing_flag == FieldType_Fcst || - engine.conf_info.mask_missing_flag == FieldType_Both) - mask_bad_data(Fcst_sd.data, Obs_sd.data); - - // Mask out the missing data between fields - - if(engine.conf_info.mask_missing_flag == FieldType_Obs || - engine.conf_info.mask_missing_flag == FieldType_Both) - mask_bad_data(Obs_sd.data, Fcst_sd.data); - // Parse the grid and/or polyline masks from the configuration - process_masks(Fcst_sd, Obs_sd); + process_obs_masks(Obs_sd); // Compute the min and max data values across both raw fields - Fcst_sd.data.data_range(fmin, fmax); Obs_sd.data.data_range(omin, omax); - if (!is_bad_data(fmin) && !is_bad_data(omin)) data_min = min(fmin, omin); - else if(!is_bad_data(fmin) && is_bad_data(omin)) data_min = fmin; - else if( is_bad_data(fmin) && !is_bad_data(omin)) data_min = omin; - - if (!is_bad_data(fmax) && !is_bad_data(omax)) data_max = max(fmax, omax); - else if(!is_bad_data(fmax) && is_bad_data(omax)) data_max = fmax; - else if( is_bad_data(fmax) && !is_bad_data(omax)) data_max = omax; + data_min = omin; + data_max = omax; // Process percentile thresholds - engine.conf_info.set_perc_thresh(Fcst_sd.data, Obs_sd.data); + engine.conf_info.set_perc_thresh(Obs_sd.data); // store the input data units - funits = engine.conf_info.Fcst->var_info->units(); + funits = na_str; ounits = engine.conf_info.Obs->var_info->units(); // store the input data level - flevel = engine.conf_info.Fcst->var_info->level_name(); + flevel = na_str; olevel = engine.conf_info.Obs->var_info->level_name(); // @@ -429,17 +768,17 @@ void ModeExecutive::setup_fcst_obs_data() /////////////////////////////////////////////////////////////////////// -void ModeExecutive::setup_fcst_obs_data(const MultiVarData &mvd) - +void ModeExecutive::setup_fcst_obs_data_multivar_intensities(const MultiVarData &mvdf, + const MultiVarData &mvdo) { - double fmin, omin, fmax, omax; + double fmin, fmax, omin, omax; bool simple = true; - Fcst_sd = *(mvd.fcst_shapedata_ptr(simple)); + Fcst_sd = *(mvdf.shapedata_ptr(simple)); Fcst_sd.debug_examine(); - Obs_sd = *(mvd.obs_shapedata_ptr(simple)); + Obs_sd = *(mvdo.shapedata_ptr(simple)); Obs_sd.debug_examine(); - grid = *(mvd._grid); + grid = *(mvdf._grid); // do not need to read any data, it is stored in the mvd input // the verification grid was created in the first pass, so we have that as well @@ -456,20 +795,20 @@ void ModeExecutive::setup_fcst_obs_data(const MultiVarData &mvd) // Print a warning if the valid times do not match if(Fcst_sd.data.valid() != Obs_sd.data.valid()) { - mlog << Warning << "\nsetup_fcst_obs_data() -> " - << "Forecast and observation valid times do not match " - << unix_to_yyyymmdd_hhmmss(Fcst_sd.data.valid()) << " != " - << unix_to_yyyymmdd_hhmmss(Obs_sd.data.valid()) << " for " - << engine.conf_info.Fcst->var_info->magic_str() << " versus " - << engine.conf_info.Obs->var_info->magic_str() << ".\n\n"; - } + mlog << Warning << "\nModeExecutive::setup_fcst_obs_data_multivar_intensities() -> " + << "Forecast and observation valid times do not match " + << unix_to_yyyymmdd_hhmmss(Fcst_sd.data.valid()) << " != " + << unix_to_yyyymmdd_hhmmss(Obs_sd.data.valid()) << " for " + << engine.conf_info.Fcst->var_info->magic_str() << " versus " + << engine.conf_info.Obs->var_info->magic_str() << ".\n\n"; + } // Print a warning if the accumulation intervals do not match if(engine.conf_info.Fcst->var_info->level().type() == LevelType_Accum && engine.conf_info.Obs->var_info->level().type() == LevelType_Accum && Fcst_sd.data.accum() != Obs_sd.data.accum()) { - mlog << Warning << "\nsetup_fcst_obs_data() -> " + mlog << Warning << "\nModeExecutive::setup_fcst_obs_data_multivar_intensities() -> " << "Forecast and observation accumulation times do not match " << sec_to_hhmmss(Fcst_sd.data.valid()) << " != " << sec_to_hhmmss(Obs_sd.data.valid()) << " for " @@ -481,20 +820,36 @@ void ModeExecutive::setup_fcst_obs_data(const MultiVarData &mvd) << "Forecast Field: " << engine.conf_info.Fcst->var_info->name_attr() << " at " << engine.conf_info.Fcst->var_info->level_attr() - << "\n" + << "\n"; + Fcst_sd.data.data_range(fmin, fmax); + funits = engine.conf_info.Fcst->var_info->units(); + flevel = engine.conf_info.Fcst->var_info->level_name(); + mlog << Debug(1) << "Observation Field: " << engine.conf_info.Obs->var_info->name_attr() << " at " << engine.conf_info.Obs->var_info->level_attr() << "\n"; + Obs_sd.data.data_range(omin, omax); + ounits = engine.conf_info.Obs->var_info->units(); + olevel = engine.conf_info.Obs->var_info->level_name(); + + // in case perc thresh was done, retrieve the values created in the + // first pass, which have been stored in mvdo and mvdf + engine.conf_info.Obs->conv_thresh_array = mvdo._merge->_convThreshArray; + engine.conf_info.Obs->merge_thresh_array = mvdo._merge->_mergeThreshArray; + engine.conf_info.Fcst->conv_thresh_array = mvdf._merge->_convThreshArray; + engine.conf_info.Fcst->merge_thresh_array = mvdf._merge->_mergeThreshArray; + + // This doesn't work with perc_thresh, it uses values restricted to within + // superobjects, which gives different thresholds, so we do the above instead. + //engine.conf_info.set_perc_thresh(Fcst_sd.data, Obs_sd.data); // masking of inputs not needed, as it was done in the first pass // and stored to Fcst_sd and Obs_sd - // Compute the min and max data values across both raw fields + // Compute the min and max data values across raw fields // do this in the 2nd pass as data has now been masked to within superobjects - Fcst_sd.data.data_range(fmin, fmax); - Obs_sd.data.data_range(omin, omax); if (!is_bad_data(fmin) && !is_bad_data(omin)) data_min = min(fmin, omin); else if(!is_bad_data(fmin) && is_bad_data(omin)) data_min = fmin; else if( is_bad_data(fmin) && !is_bad_data(omin)) data_min = omin; @@ -503,31 +858,17 @@ void ModeExecutive::setup_fcst_obs_data(const MultiVarData &mvd) else if(!is_bad_data(fmax) && is_bad_data(omax)) data_max = fmax; else if( is_bad_data(fmax) && !is_bad_data(omax)) data_max = omax; - // Process percentile thresholds - // do this in the second pass using masked Fcst_sd and Obs_sd - engine.conf_info.set_perc_thresh(Fcst_sd.data, Obs_sd.data); - - // store the input data units - funits = engine.conf_info.Fcst->var_info->units(); - ounits = engine.conf_info.Obs->var_info->units(); - - // store the input data level - flevel = engine.conf_info.Fcst->var_info->level_name(); - olevel = engine.conf_info.Obs->var_info->level_name(); - - // // done // return; } - /////////////////////////////////////////////////////////////////////// -void ModeExecutive::setup_fcst_obs_data(ShapeData &f_super, ShapeData &o_super, - const Grid &igrid) +void ModeExecutive::setup_fcst_obs_data_multivar_super(ShapeData &f_super, ShapeData &o_super, + const Grid &igrid) { double fmin, omin, fmax, omax; @@ -553,7 +894,7 @@ void ModeExecutive::setup_fcst_obs_data(ShapeData &f_super, ShapeData &o_super, // Print a warning if the valid times do not match if(Fcst_sd.data.valid() != Obs_sd.data.valid()) { - mlog << Warning << "\nsetup_fcst_obs_data() -> " + mlog << Warning << "\nModeExecutive::setup_fcst_obs_data_multivar_super() -> " << "Forecast and observation valid times do not match " << unix_to_yyyymmdd_hhmmss(Fcst_sd.data.valid()) << " != " << unix_to_yyyymmdd_hhmmss(Obs_sd.data.valid()) << " for " @@ -566,7 +907,7 @@ void ModeExecutive::setup_fcst_obs_data(ShapeData &f_super, ShapeData &o_super, engine.conf_info.Obs->var_info->level().type() == LevelType_Accum && Fcst_sd.data.accum() != Obs_sd.data.accum()) { - mlog << Warning << "\nsetup_fcst_obs_data() -> " + mlog << Warning << "\nModeExecutive::setup_fcst_obs_data_multivar_super() -> " << "Forecast and observation accumulation times do not match " << sec_to_hhmmss(Fcst_sd.data.valid()) << " != " << sec_to_hhmmss(Obs_sd.data.valid()) << " for " @@ -600,9 +941,9 @@ void ModeExecutive::setup_fcst_obs_data(ShapeData &f_super, ShapeData &o_super, else if(!is_bad_data(fmax) && is_bad_data(omax)) data_max = fmax; else if( is_bad_data(fmax) && !is_bad_data(omax)) data_max = omax; - // Process percentile thresholds + // Process percentile thresholds...Not applicable for this pass // do this in the second pass using masked Fcst_sd and Obs_sd - engine.conf_info.set_perc_thresh(Fcst_sd.data, Obs_sd.data); + // engine.conf_info.set_perc_thresh(Fcst_sd.data, Obs_sd.data); // // done @@ -616,73 +957,71 @@ void ModeExecutive::setup_fcst_obs_data(ShapeData &f_super, ShapeData &o_super, /////////////////////////////////////////////////////////////////////// -void ModeExecutive::do_conv_thresh(const int r_index, const int t_index, - bool isMultivarPass1Merge, - bool isMultivarPass2, - bool isMultivarSuper) - +void ModeExecutive::do_conv_thresh(const int r_index, const int t_index) { ModeConfInfo & conf = engine.conf_info; + // note that we are assuming the same r_index and t_index for both forecasts + // and obs, which might not be true if mvmode were to allow >1 index + // (currently it does not) + R_index = r_index; T_index = t_index; - if (isMultivarPass1Merge) { - - if (conf.Fcst->need_merge_thresh()) { - conf.set_fcst_conv_thresh_by_merge_index (T_index); - } - if (conf.Obs->need_merge_thresh()) { - conf.set_obs_conv_thresh_by_merge_index (T_index); - } - } else if (isMultivarSuper) { + if (ptype == MULTIVAR_SIMPLE_MERGE) { + conf.set_conv_thresh_by_merge_index(T_index); + } else if (ptype == MULTIVAR_SUPER) { SingleThresh s("ne-9999"); conf.set_conv_thresh(s); conf.set_conv_radius(0.0); } else { + // this could break down if obs and fcst have different arrays + // currently not allowed in multivar mode, should work correctly + // for traditional mode conf.set_conv_radius_by_index(R_index); conf.set_conv_thresh_by_index(T_index); } - if ( conf.Fcst->need_merge_thresh () ) conf.set_fcst_merge_thresh_by_index (T_index); - if ( conf.Obs->need_merge_thresh () ) conf.set_obs_merge_thresh_by_index (T_index); + conf.set_merge_thresh_by_index(T_index); // // Set up the engine with these raw fields // - mlog << Debug(2) - << "Identifying objects in the forecast and observation fields...\n"; + string what = "forecast and observation fields"; + if (ptype == MULTIVAR_SIMPLE || ptype == MULTIVAR_SIMPLE_MERGE) { + if (conf.data_type == ModeDataType_MvMode_Obs) { + what = "observation field"; + } else { + what = "forecast field"; + } + } + mlog << Debug(2) << "Identifying objects in the " << what << "...\n"; if ( r_index != local_r_index ) { // need to do convolution - if (isMultivarPass2) { - engine.set_only_split(Fcst_sd, Obs_sd); - } else if (isMultivarSuper) { + if (ptype == MULTIVAR_INTENSITY || ptype == MULTIVAR_SUPER) { engine.set_only_split(Fcst_sd, Obs_sd); - //engine.set_super(Fcst_sd, Obs_sd); - } else { + } else {// MULTIVAR_SIMPLE, MULTIVAR_SIMPLE_MERGE, TRADITIONAL engine.set(Fcst_sd, Obs_sd); } } else { // don't need to do convolution - if (isMultivarPass2) { - engine.set_only_split(Fcst_sd, Obs_sd); - } else if (isMultivarSuper) { + if (ptype == MULTIVAR_INTENSITY || ptype == MULTIVAR_SUPER) { engine.set_only_split(Fcst_sd, Obs_sd); - //engine.set_super(Fcst_sd, Obs_sd); - } else { + } else {// MULTIVAR_SIMPLE, MULTIVAR_SIMPLE_MERGE, TRADITIONAL engine.set_no_conv(Fcst_sd, Obs_sd); } } // // Compute the contingency table statistics for the fields, if needed + // (not needed for simple or merge, only one field) // - - if ( conf.ct_stats_flag ) compute_ct_stats(); - + if (ptype != MULTIVAR_SIMPLE && ptype != MULTIVAR_SIMPLE_MERGE) { + if ( conf.ct_stats_flag ) compute_ct_stats(); + } // // done @@ -735,10 +1074,10 @@ void ModeExecutive::do_merging() /////////////////////////////////////////////////////////////////////// -void ModeExecutive::do_merging(ShapeData &f_merge, ShapeData &o_merge, - bool isMultivarSuper) +void ModeExecutive::do_merging(ShapeData &f_merge, ShapeData &o_merge) + { - if (isMultivarSuper) { + if (ptype == MULTIVAR_SUPER) { // set the merge flag and merge_thresh appropriately ModeConfInfo & conf = engine.conf_info; SingleThresh s("ne-9999"); @@ -746,6 +1085,12 @@ void ModeExecutive::do_merging(ShapeData &f_merge, ShapeData &o_merge, conf.set_fcst_merge_thresh(s); conf.set_obs_merge_flag(MergeType_Thresh); conf.set_obs_merge_thresh(s); + } else { + if (ptype != MULTIVAR_INTENSITY) { + mlog << Error << "\nModeExecutive::do_merging(shapedata, shapedata) -> " + << "wrong method for processing type " << stype(ptype) << "\n\n"; + exit(1); + } } @@ -782,10 +1127,10 @@ void ModeExecutive::do_merging(ShapeData &f_merge, ShapeData &o_merge, /////////////////////////////////////////////////////////////////////// -void ModeExecutive::do_match_merge(ShapeData &f_merge, ShapeData &o_merge, bool isMultivarSuper) +void ModeExecutive::do_match_merge(ShapeData &f_merge, ShapeData &o_merge) { - do_merging(f_merge, o_merge, isMultivarSuper); + do_merging(f_merge, o_merge); // Do the matching of objects between fields @@ -870,6 +1215,95 @@ void ModeExecutive::process_masks(ShapeData & fcst_sd, ShapeData & obs_sd) /////////////////////////////////////////////////////////////////////// +void ModeExecutive::process_fcst_masks(ShapeData & fcst_sd) + +{ + + ShapeData grid_mask_sd, poly_mask_sd; + ConcatString name; + + mlog << Debug(3) << "Processing masking regions.\n"; + + // Parse the grid mask into a ShapeData object + if(engine.conf_info.mask_grid_flag != FieldType_None) { + mlog << Debug(3) + << "Processing grid mask: " + << engine.conf_info.mask_grid_name << "\n"; + parse_grid_mask(engine.conf_info.mask_grid_name, grid, + grid_mask_sd.data, name); + } + + // Parse the poly mask into a ShapeData object + if(engine.conf_info.mask_poly_flag != FieldType_None) { + mlog << Debug(3) + << "Processing poly mask: " + << engine.conf_info.mask_poly_name << "\n"; + parse_poly_mask(engine.conf_info.mask_poly_name, grid, + poly_mask_sd.data, name); + } + + // Apply the grid mask to the forecast field if requested + if(engine.conf_info.mask_grid_flag == FieldType_Fcst || + engine.conf_info.mask_grid_flag == FieldType_Both) { + apply_mask(fcst_sd, grid_mask_sd); + } + + // Apply the polyline mask to the forecast field if requested + if(engine.conf_info.mask_poly_flag == FieldType_Fcst || + engine.conf_info.mask_poly_flag == FieldType_Both) { + apply_mask(fcst_sd, poly_mask_sd); + } + + return; +} + +/////////////////////////////////////////////////////////////////////// + +void ModeExecutive::process_obs_masks(ShapeData & obs_sd) + +{ + + ShapeData grid_mask_sd, poly_mask_sd; + ConcatString name; + + mlog << Debug(2) + << "Processing masking regions.\n"; + + // Parse the grid mask into a ShapeData object + if(engine.conf_info.mask_grid_flag != FieldType_None) { + mlog << Debug(3) + << "Processing grid mask: " + << engine.conf_info.mask_grid_name << "\n"; + parse_grid_mask(engine.conf_info.mask_grid_name, grid, + grid_mask_sd.data, name); + } + + // Parse the poly mask into a ShapeData object + if(engine.conf_info.mask_poly_flag != FieldType_None) { + mlog << Debug(3) + << "Processing poly mask: " + << engine.conf_info.mask_poly_name << "\n"; + parse_poly_mask(engine.conf_info.mask_poly_name, grid, + poly_mask_sd.data, name); + } + + // Apply the grid mask to the observation field if requested + if(engine.conf_info.mask_grid_flag == FieldType_Obs || + engine.conf_info.mask_grid_flag == FieldType_Both) { + apply_mask(obs_sd, grid_mask_sd); + } + + // Apply the polyline mask to the observation field if requested + if(engine.conf_info.mask_poly_flag == FieldType_Obs || + engine.conf_info.mask_poly_flag == FieldType_Both) { + apply_mask(obs_sd, poly_mask_sd); + } + + return; +} + +/////////////////////////////////////////////////////////////////////// + void ModeExecutive::set_raw_to_full(float *fcst_raw_data, float *obs_raw_data, int nx, int ny, @@ -883,15 +1317,16 @@ void ModeExecutive::set_raw_to_full(float *fcst_raw_data, /////////////////////////////////////////////////////////////////////// -void ModeExecutive::process_output(bool isMultivar, bool isMultivarSuper, - const MultiVarData *mvd) +void ModeExecutive::process_output(const MultiVarData *mvdf, + const MultiVarData *mvdo) { + // store to class member so don't have to pass it around - isMultivarOutput = isMultivar; - isMultivarSuperOutput = isMultivarSuper; + isMultivarOutput = (ptype == MULTIVAR_INTENSITY); + isMultivarSuperOutput = (ptype == MULTIVAR_SUPER); - if (isMultivar) { + if (isMultivarOutput) { // get the magic strings, which will be used in file naming fcst_magic_string = engine.conf_info.Fcst->var_info->magic_str().c_str(); @@ -911,7 +1346,7 @@ void ModeExecutive::process_output(bool isMultivar, bool isMultivarSuper, replaceAll(fcst_magic_string, ")", ""); replaceAll(obs_magic_string, ")", ""); - } else if (isMultivarSuper) { + } else if (isMultivarSuperOutput) { // use the configured multivar name and level fcst_magic_string = engine.conf_info.fcst_multivar_name.string() + "_" + engine.conf_info.fcst_multivar_level.string(); @@ -931,15 +1366,30 @@ void ModeExecutive::process_output(bool isMultivar, bool isMultivarSuper, if ( engine.conf_info.ct_stats_flag ) write_ct_stats(); - if (isMultivar) { - if (mvd) { - set_raw_to_full(mvd->_simple->_fcst_raw_data, - mvd->_simple->_obs_raw_data, - mvd->_nx, mvd->_ny, - mvd->_data_min, mvd->_data_max); + + + if (isMultivarOutput) { + if (mvdf && mvdo) { + double fmin = mvdf->_data_min; + double fmax = mvdf->_data_max; + double omin = mvdo->_data_min; + double omax = mvdo->_data_max; + double data_min, data_max; + if (!is_bad_data(fmin) && !is_bad_data(omin)) data_min = min(fmin, omin); + else if(!is_bad_data(fmin) && is_bad_data(omin)) data_min = fmin; + else if( is_bad_data(fmin) && !is_bad_data(omin)) data_min = omin; + + if (!is_bad_data(fmax) && !is_bad_data(omax)) data_max = max(fmax, omax); + else if(!is_bad_data(fmax) && is_bad_data(omax)) data_max = fmax; + else if( is_bad_data(fmax) && !is_bad_data(omax)) data_max = omax; + + set_raw_to_full(mvdf->_simple->_raw_data, + mvdo->_simple->_raw_data, + mvdf->_nx, mvdf->_ny, + data_min, data_max); } else { - mlog << Error << "\nprocess_output() -> " - << "no multivar data when data is expected\n\n"; + mlog << Error << "\nModeExecutive::process_output() -> " + << "no multivar data when multivar data is expected\n\n"; exit(1); } } @@ -1151,7 +1601,7 @@ void ModeExecutive::write_obj_stats() out.open(stat_file.c_str()); if(!out) { - mlog << Error << "\nwrite_obj_stats() -> " + mlog << Error << "\nModeExecutive::write_obj_stats() -> " << "unable to open stats output file \"" << stat_file << "\"\n\n"; exit(1); @@ -1186,7 +1636,7 @@ void ModeExecutive::write_obj_stats() out.open(stat_file.c_str()); if(!out) { - mlog << Error << "\nwrite_obj_stats() -> " + mlog << Error << "\nModeExecutive::write_obj_stats() -> " << "unable to open stats output file \"" << stat_file << "\"\n\n"; exit(1); @@ -1218,7 +1668,7 @@ void ModeExecutive::write_obj_stats() out.open(stat_file.c_str()); if(!out) { - mlog << Error << "\nwrite_obj_stats() -> " + mlog << Error << "\nModeExecutive::write_obj_stats() -> " << "unable to open stats output file \"" << stat_file << "\"\n\n"; exit(1); @@ -1245,44 +1695,70 @@ void ModeExecutive::write_obj_stats() ////////////////////////////////////////////////////////////////////// - -MultiVarData *ModeExecutive::get_multivar_data() +MultiVarData *ModeExecutive::get_multivar_data(ModeDataType dtype) { bool simple=true; MultiVarData *mvd = new MultiVarData(); - fcst_magic_string = engine.conf_info.Fcst->var_info->magic_str().c_str(); - obs_magic_string = engine.conf_info.Obs->var_info->magic_str().c_str(); - - // replace forward slashes with underscores to prevent new directories - - replace(fcst_magic_string.begin(), fcst_magic_string.end(), '/', '_'); - replace(obs_magic_string.begin(), obs_magic_string.end(), '/', '_'); - - mvd->init(fcst_magic_string, obs_magic_string, grid, ftype, otype, - funits, ounits, flevel, olevel, data_min, data_max); - mvd->set_fcst_obj(engine.fcst_split, simple); - mvd->set_fcst_raw(engine.fcst_raw, simple); - mvd->set_obs_obj(engine.obs_split, simple); - mvd->set_obs_raw(engine.obs_raw, simple); - mvd->set_fcst_shapedata(Fcst_sd, simple); - mvd->set_obs_shapedata(Obs_sd, simple); - + switch (dtype) + { + case ModeDataType_MvMode_Obs: + obs_magic_string = engine.conf_info.Obs->var_info->magic_str().c_str(); + // replace forward slashes with underscores to prevent new directories + replace(obs_magic_string.begin(), obs_magic_string.end(), '/', '_'); + mvd->init(dtype, obs_magic_string, grid, otype, ounits, olevel, data_min, data_max); + mvd->set_obj(engine.obs_split, simple); + mvd->set_raw(engine.obs_raw, simple); + mvd->set_shapedata(Obs_sd, simple); + mvd->set_conv_thresh_array(engine.conf_info.Obs->conv_thresh_array, simple); + mvd->set_merge_thresh_array(engine.conf_info.Obs->merge_thresh_array, simple); + break; + case ModeDataType_MvMode_Fcst: + fcst_magic_string = engine.conf_info.Fcst->var_info->magic_str().c_str(); + // replace forward slashes with underscores to prevent new directories + replace(fcst_magic_string.begin(), fcst_magic_string.end(), '/', '_'); + mvd->init(dtype, fcst_magic_string, grid, ftype, funits, flevel, data_min, data_max); + mvd->set_obj(engine.fcst_split, simple); + mvd->set_raw(engine.fcst_raw, simple); + mvd->set_shapedata(Fcst_sd, simple); + mvd->set_conv_thresh_array(engine.conf_info.Fcst->conv_thresh_array, simple); + mvd->set_merge_thresh_array(engine.conf_info.Fcst->merge_thresh_array, simple); + break; + default: + mlog << Error << "\nModeExecutive::get_multivar_data() -> wrong data type " + << sprintModeDataType(dtype) << "\n\n"; + exit(1); + } return mvd; } /////////////////////////////////////////////////////////////////////// -void ModeExecutive::addMultivarMergePass1(MultiVarData *mvd) +void ModeExecutive::add_multivar_merge_data(MultiVarData *mvd, ModeDataType dtype) { bool simple = false; - mvd->set_fcst_obj(engine.fcst_split, simple); - mvd->set_fcst_raw(engine.fcst_raw, simple); - mvd->set_obs_obj(engine.obs_split, simple); - mvd->set_obs_raw(engine.obs_raw, simple); - mvd->set_fcst_shapedata(Fcst_sd, simple); - mvd->set_obs_shapedata(Obs_sd, simple); + switch (dtype) + { + case ModeDataType_MvMode_Obs: + mvd->set_obj(engine.obs_split, simple); + mvd->set_raw(engine.obs_raw, simple); + mvd->set_shapedata(Obs_sd, simple); + mvd->set_conv_thresh_array(engine.conf_info.Obs->conv_thresh_array, simple); + mvd->set_merge_thresh_array(engine.conf_info.Obs->merge_thresh_array, simple); + break; + case ModeDataType_MvMode_Fcst: + mvd->set_obj(engine.fcst_split, simple); + mvd->set_raw(engine.fcst_raw, simple); + mvd->set_shapedata(Fcst_sd, simple); + mvd->set_conv_thresh_array(engine.conf_info.Fcst->conv_thresh_array, simple); + mvd->set_merge_thresh_array(engine.conf_info.Fcst->merge_thresh_array, simple); + break; + default: + mlog << Error << "\nModeExecutive::add_multivar_merge_data() -> wrong data type " + << sprintModeDataType(dtype) << "\n\n"; + exit(1); + } } /////////////////////////////////////////////////////////////////////// @@ -1349,7 +1825,7 @@ void ModeExecutive::write_obj_netcdf(const ModeNcOutInfo & info) f_out = open_ncfile(out_file.c_str(), true); if(IS_INVALID_NC_P(f_out)) { - mlog << Error << "\nwrite_obj_netcdf() -> trouble opening output file " + mlog << Error << "\nModeExecutive::write_obj_netcdf() -> trouble opening output file " << out_file << "\n\n"; delete f_out; f_out = (NcFile *) 0; @@ -1430,8 +1906,7 @@ void ModeExecutive::write_obj_netcdf(const ModeNcOutInfo & info) if ( !put_nc_data(&fcst_radius_var, &engine.conf_info.Fcst->conv_radius) || !put_nc_data(&obs_radius_var, &engine.conf_info.Obs->conv_radius) ) { - mlog << Error - << "write_obj_netcdf() -> " + mlog << Error << "\nModeExecutive::write_obj_netcdf() -> " << "error writing fcst/obs convolution radii\n\n"; exit(1); @@ -1441,8 +1916,7 @@ void ModeExecutive::write_obj_netcdf(const ModeNcOutInfo & info) if ( ! put_nc_data(&fcst_thresh_var, fcst_thresh.c_str()) || ! put_nc_data(& obs_thresh_var, obs_thresh.c_str()) ) { - mlog << Error - << "write_obj_netcdf() -> " + mlog << Error << "\nModeExecutive::write_obj_netcdf() -> " << "error writing fcst/obs thresholds\n\n"; exit(1); @@ -1641,7 +2115,7 @@ void ModeExecutive::write_obj_netcdf(const ModeNcOutInfo & info) if( !put_nc_data_with_dims(&fcst_raw_var, &fcst_raw_data[0], grid.ny(), grid.nx()) || !put_nc_data_with_dims(&obs_raw_var, &obs_raw_data[0], grid.ny(), grid.nx()) ) { - mlog << Error << "\nwrite_obj_netcdf() -> " + mlog << Error << "\nModeExecutive::write_obj_netcdf() -> " << "error with the fcst_raw_var->put or obs_raw_var->put\n\n"; exit(1); } @@ -1653,7 +2127,7 @@ void ModeExecutive::write_obj_netcdf(const ModeNcOutInfo & info) if( !put_nc_data_with_dims(&fcst_obj_raw_var, &fcst_obj_raw_data[0], grid.ny(), grid.nx()) || !put_nc_data_with_dims(&obs_obj_raw_var, &obs_obj_raw_data[0], grid.ny(), grid.nx()) ) { - mlog << Error << "\nwrite_obj_netcdf() -> " + mlog << Error << "\nModeExecutive::write_obj_netcdf() -> " << "error with the fcst_obj_raw_var->put or obs_obj_raw_var->put\n\n"; exit(1); } @@ -1669,7 +2143,7 @@ void ModeExecutive::write_obj_netcdf(const ModeNcOutInfo & info) if( !put_nc_data_with_dims(&fcst_obj_var, &fcst_obj_data[0], grid.ny(), grid.nx()) || !put_nc_data_with_dims(&obs_obj_var, &obs_obj_data[0], grid.ny(), grid.nx()) ) { - mlog << Error << "\nwrite_obj_netcdf() -> " + mlog << Error << "\nModeExecutive::write_obj_netcdf() -> " << "error with the fcst_obj_var->put or obs_obj_var->put\n\n"; exit(1); } @@ -1685,7 +2159,7 @@ void ModeExecutive::write_obj_netcdf(const ModeNcOutInfo & info) if( !put_nc_data_with_dims(&fcst_clus_var, &fcst_clus_data[0], grid.ny(), grid.nx()) || !put_nc_data_with_dims(&obs_clus_var, &obs_clus_data[0], grid.ny(), grid.nx()) ) { - mlog << Error << "\nwrite_obj_netcdf() -> " + mlog << Error << "\nModeExecutive::write_obj_netcdf() -> " << "error with the fcst_clus_var->put or obs_clus_var->put\n\n"; exit(1); } @@ -1746,7 +2220,7 @@ void ModeExecutive::write_poly_netcdf(NcFile * f_out) !put_nc_data(&n_obs_simp_var, &engine.n_obs) || !put_nc_data(&n_clus_var, &engine.n_clus) ) { - mlog << Error << "\nwrite_obj_netcdf() -> " + mlog << Error << "\nModeExecutive::write_poly_netcdf() -> " << "error with the n_fcst_simp_var->put, " << "n_obs_simp_var->put, or n_clus_var->put\n\n"; exit(1); @@ -2005,7 +2479,7 @@ void ModeExecutive::write_poly_netcdf(NcFile *f_out, ObjPolyType poly_type) if( !put_nc_data_with_dims(&obj_poly_start_var, &poly_start[0], n_poly) || !put_nc_data_with_dims(&obj_poly_npts_var, &poly_npts[0], n_poly) ) { - mlog << Error << "\nwrite_poly_netcdf() -> " + mlog << Error << "\nModeExecutive::write_poly_netcdf() -> " << "error with " << start_var_name << "->put or " << npts_var_name << "->put\n\n"; exit(1); @@ -2017,7 +2491,7 @@ void ModeExecutive::write_poly_netcdf(NcFile *f_out, ObjPolyType poly_type) if( !put_nc_data_with_dims(&poly_lat_var, &poly_lat[0], n_pts) || !put_nc_data_with_dims(&poly_lon_var, &poly_lon[0], n_pts) ) { - mlog << Error << "\nwrite_poly_netcdf() -> " + mlog << Error << "\nModeExecutive::write_poly_netcdf() -> " << "error with " << lat_var_name << "->put or " << lon_var_name << "->put\n\n"; exit(1); @@ -2029,7 +2503,7 @@ void ModeExecutive::write_poly_netcdf(NcFile *f_out, ObjPolyType poly_type) if( !put_nc_data_with_dims(&poly_x_var, &poly_x[0], n_pts) || !put_nc_data_with_dims(&poly_y_var, &poly_y[0], n_pts) ) { - mlog << Error << "\nwrite_poly_netcdf() -> " + mlog << Error << "\nModeExecutive::write_poly_netcdf() -> " << "error with " << x_var_name << "->put or" << y_var_name << "->put\n\n"; exit(1); @@ -2072,7 +2546,7 @@ void ModeExecutive::write_ct_stats() out.open(stat_file.c_str()); if(!out) { - mlog << Error << "\nwrite_ct_stats() -> " + mlog << Error << "\nModeExecutive::write_ct_stats() -> " << "unable to open stats output file \"" << stat_file << "\"\n\n"; exit(1); @@ -2231,6 +2705,56 @@ void ModeExecutive::write_ct_stats() return; } +/////////////////////////////////////////////////////////////////////// + +void ModeExecutive::conf_read(const string &default_config_filename) +{ + + // Create the default config file name + default_config_file = replace_path(default_config_filename); + + // If the merge config file was not set, use the match config file + if(merge_config_file.length() == 0) + merge_config_file = match_config_file; + + // List the config files + mlog << Debug(3) + << "Default Config File: " << default_config_file << "\n" + << "Match Config File: " << match_config_file << "\n" + << "Merge Config File: " << merge_config_file << "\n"; + + // Read the config files + engine.conf_info.read_config(default_config_file.c_str(), match_config_file.c_str()); +} + +/////////////////////////////////////////////////////////////////////// + +string ModeExecutive::stype(Processing_t t) +{ + string s; + switch (t) { + case MULTIVAR_SIMPLE: + s = "Multivar Simple Objects"; + break; + case MULTIVAR_SIMPLE_MERGE: + s = "Multivar Simple Object Merge"; + break; + case MULTIVAR_INTENSITY: + s = "Multivar Intensity"; + break; + case MULTIVAR_SUPER: + s = "Multivar Superobjects"; + break; + case TRADITIONAL: + default: + s = "Traditional"; + break; + } + return s; +} + + + /////////////////////////////////////////////////////////////////////// @@ -2291,3 +2815,5 @@ void replaceAll(std::string& str, const std::string& from, const std::string& to start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' } } + + diff --git a/src/tools/core/mode/mode_exec.h b/src/tools/core/mode/mode_exec.h index 547792c1c6..34c8d7fb5e 100644 --- a/src/tools/core/mode/mode_exec.h +++ b/src/tools/core/mode/mode_exec.h @@ -39,6 +39,7 @@ #include "vx_plot_util.h" #include "mode_ps_file.h" +#include "mode_data_type.h" #include "multivar_data.h" //////////////////////////////////////////////////////////////////////// @@ -71,13 +72,19 @@ class ModeExecutive { public: - ModeExecutive(); + // the various mode algorithm settings + typedef enum {TRADITIONAL, MULTIVAR_SIMPLE, MULTIVAR_SIMPLE_MERGE, MULTIVAR_INTENSITY, MULTIVAR_SUPER} Processing_t; + + ModeExecutive(Processing_t p=TRADITIONAL); ~ModeExecutive(); void clear(); - void init(int n_files, bool isMultivar); - void init_multivar(GrdFileType ftype, GrdFileType otype); + void init_traditional(int n_files); + void init_multivar_verif_grid(); + void init_multivar_simple(int n_files, ModeDataType dtype); + void init_multivar_intensities(GrdFileType ftype, GrdFileType otype); + void check_multivar_perc_thresh_settings(); int n_conv_radii () const; @@ -86,7 +93,7 @@ class ModeExecutive { int n_runs() const; int R_index; // indices into the convolution radius and threshold arrays - int T_index; // for the current run + int T_index; // for the current run // // Input configuration files @@ -108,7 +115,10 @@ class ModeExecutive { TTContingencyTable cts[n_cts]; ModeFuzzyEngine engine; + + // verification grid Grid grid; + Box xy_bb; ConcatString out_dir; double data_min, data_max; @@ -122,23 +132,26 @@ class ModeExecutive { bool isMultivarOutput; bool isMultivarSuperOutput; + Processing_t ptype; + void clear_internal_r_index(); - void setup_fcst_obs_data(); - void setup_fcst_obs_data(const MultiVarData &mvd); - void setup_fcst_obs_data(ShapeData &f_super, ShapeData &o_super, - const Grid &igrid); - void do_conv_thresh(const int r_index, const int t_index, - bool isMultivarPass1Merge=false, - bool isMultivarPass2=false, - bool isMultivarSuper=false); + void setup_verification_grid(); + void setup_fcst_obs_data_traditional(); + void setup_fcst_data(const Grid &verification_grid); + void setup_obs_data(const Grid &verification_grid); + void setup_fcst_obs_data_multivar_intensities(const MultiVarData &mvdf, const MultiVarData &mvdo); + void setup_fcst_obs_data_multivar_super(ShapeData &f_super, ShapeData &o_super, const Grid &igrid); + void do_conv_thresh(const int r_index, const int t_index); void do_merging(); - void do_merging(ShapeData &f_merge, ShapeData &o_merge,bool isMultivarSuper=false); + void do_merging(ShapeData &f_merge, ShapeData &o_merge); void do_match_merge(); - void do_match_merge(ShapeData &f_merge, ShapeData &o_merge, bool isMultivarSuper=false); + void do_match_merge(ShapeData &f_merge, ShapeData &o_merge); void process_masks(ShapeData &, ShapeData &); - void process_output(bool isMultivar=false, bool isMultivarSuper=false, - const MultiVarData *mvd=NULL); + void process_fcst_masks(ShapeData &); + void process_obs_masks(ShapeData &); + void process_output(const MultiVarData *mvdf=NULL, + const MultiVarData *mvdo=NULL); void set_raw_to_full(float *fcst_raw_data, float *obs_raw_data, @@ -147,8 +160,8 @@ class ModeExecutive { // owned by caller - MultiVarData *get_multivar_data(); - void addMultivarMergePass1(MultiVarData *mvdi); + MultiVarData *get_multivar_data(ModeDataType dtype); + void add_multivar_merge_data(MultiVarData *mvdi, ModeDataType dtype); void plot_engine(); @@ -165,6 +178,9 @@ class ModeExecutive { void write_poly_netcdf(netCDF::NcFile *, const ObjPolyType); void write_ct_stats(); + void conf_read(const string &default_config_filename); + static string stype(Processing_t t); + }; diff --git a/src/tools/core/mode/mode_frontend.cc b/src/tools/core/mode/mode_frontend.cc index a37bd89b0c..456ae71f7a 100644 --- a/src/tools/core/mode/mode_frontend.cc +++ b/src/tools/core/mode/mode_frontend.cc @@ -35,8 +35,10 @@ using namespace std; extern const char * const program_name; static ModeExecutive *mode_exec = 0; +static ModeExecutive::Processing_t ptype = ModeExecutive::TRADITIONAL; static int compress_level = -1; + /////////////////////////////////////////////////////////////////////// @@ -58,15 +60,13 @@ ModeFrontEnd::~ModeFrontEnd() } } + /////////////////////////////////////////////////////////////////////// -int ModeFrontEnd::run(const StringArray & Argv, Processing_t ptype, int field_index, int n_files) -{ +Grid ModeFrontEnd::create_verification_grid(const StringArray & Argv) - mlog << Debug(1) << "Running mode front end " << stype(ptype) << "\n"; - //Argv.dump(cout, 0); - +{ if ( mode_exec ) { delete mode_exec; mode_exec = 0; } mode_exec = new ModeExecutive; compress_level = -1; @@ -77,29 +77,125 @@ int ModeFrontEnd::run(const StringArray & Argv, Processing_t ptype, int field_in process_command_line(Argv, false); - mode_exec->init(n_files, ptype != SINGLE_VAR); + mode_exec->init_multivar_verif_grid(); + + ModeConfInfo & conf = mode_exec->engine.conf_info; + conf.set_field_index(0); + if (compress_level >= 0) conf.nc_info.set_compress_level(compress_level); + + + // + // read in data (Note multiple reads of same data) + // + mode_exec->setup_verification_grid(); + Grid g = mode_exec->grid; + delete mode_exec; mode_exec = 0; + return g; +} + + +/////////////////////////////////////////////////////////////////////// + +int ModeFrontEnd::create_multivar_simple_objects(const StringArray & Argv, ModeDataType dtype, + const Grid &verification_grid, int field_index, int n_files) + +{ + init(ModeExecutive::MULTIVAR_SIMPLE); + + // + // Process the command line arguments + // + + process_command_line_for_simple_objects(Argv, dtype); + + mode_exec->init_multivar_simple(n_files, dtype); ModeConfInfo & conf = mode_exec->engine.conf_info; if ( field_index >= 0 ) conf.set_field_index(field_index); if (compress_level >= 0) conf.nc_info.set_compress_level(compress_level); + // need to do this after setting field index above + mode_exec->check_multivar_perc_thresh_settings(); + + // + // read in data (Note multiple reads of data) + // + if (dtype == ModeDataType_MvMode_Fcst) { + mode_exec->setup_fcst_data(verification_grid); + } else { + mode_exec->setup_obs_data(verification_grid); + } + // - // read in data (Note double reads for pass 1 merge and pass 1 not desired) + // mode algorithm // + if ( conf.quilt ) { - mode_exec->setup_fcst_obs_data(); + do_quilt(); + + } else { + + do_straight(); + + } + + // + // done + // + +#ifdef WITH_PYTHON + GP.finalize(); +#endif + return (0); +} + +/////////////////////////////////////////////////////////////////////// + +int ModeFrontEnd::create_multivar_merge_objects(const StringArray & Argv, ModeDataType dtype, + const Grid &verification_grid, int field_index, + int n_files) + +{ + init(ModeExecutive::MULTIVAR_SIMPLE_MERGE); + + // + // Process the command line arguments + // + + process_command_line_for_simple_objects(Argv, dtype); + + mode_exec->init_multivar_simple(n_files, dtype); + + ModeConfInfo & conf = mode_exec->engine.conf_info; + if ( field_index >= 0 ) conf.set_field_index(field_index); + if (compress_level >= 0) conf.nc_info.set_compress_level(compress_level); + + // need to do this after setting field index above + mode_exec->check_multivar_perc_thresh_settings(); + + + // + // read in data (Note multiple reads not desired) + // + + if (dtype == ModeDataType_MvMode_Fcst) { + mode_exec->setup_fcst_data(verification_grid); + } else { + mode_exec->setup_obs_data(verification_grid); + } + // // mode algorithm // if ( conf.quilt ) { - do_quilt(ptype); + do_quilt(); } else { - do_straight(ptype); + do_straight(); } @@ -115,42 +211,90 @@ int ModeFrontEnd::run(const StringArray & Argv, Processing_t ptype, int field_in /////////////////////////////////////////////////////////////////////// -int ModeFrontEnd::run_multivar_pass2(const StringArray & Argv, const MultiVarData &mvd, - bool has_union, - ShapeData &f_merge, ShapeData &o_merge, int field_index) +int ModeFrontEnd::run_traditional(const StringArray & Argv) + { - Processing_t ptype = MULTIVAR_PASS2; - mlog << Debug(1) << "Running mode front end " << stype(ptype) << "\n"; - //Argv.dump(cout, 0); + init(ModeExecutive::TRADITIONAL); - if ( mode_exec ) { delete mode_exec; mode_exec = 0; } + int field_index = -1; + int n_files = 1; - mode_exec = new ModeExecutive; - compress_level = -1; + // + // Process the command line arguments + // + + process_command_line(Argv, false); + + mode_exec->init_traditional(n_files); + + ModeConfInfo & conf = mode_exec->engine.conf_info; + if ( field_index >= 0 ) conf.set_field_index(field_index); + if (compress_level >= 0) conf.nc_info.set_compress_level(compress_level); + + + // + // read in data + // + + mode_exec->setup_fcst_obs_data_traditional(); + + // + // mode algorithm + // + if ( conf.quilt ) { + + do_quilt(); + + } else { + + do_straight(); + + } + + // + // done + // + +#ifdef WITH_PYTHON + GP.finalize(); +#endif + return (0); +} + +/////////////////////////////////////////////////////////////////////// + +int ModeFrontEnd::multivar_intensity_comparisons(const StringArray & Argv, const MultiVarData &mvdf, + const MultiVarData &mvdo, bool has_union_f, + bool has_union_o, ShapeData &merge_f, + ShapeData &merge_o, int field_index_f, int field_index_o) +{ + init(ModeExecutive::MULTIVAR_INTENSITY); // // Process the command line arguments // - process_command_line(Argv, true); - mode_exec->init_multivar(mvd._ftype, mvd._otype); + process_command_line(Argv, false); + + mode_exec->init_multivar_intensities(mvdf._type, mvdo._type); ModeConfInfo & conf = mode_exec->engine.conf_info; if (compress_level >= 0) conf.nc_info.set_compress_level(compress_level); - //if ( field_index >= 0 ) - conf.set_field_index(field_index); + conf.set_field_index(field_index_f, field_index_o); - // for multivar pass2, explicity set the level and units using stored values + // for multivar intensities, explicity set the level and units using stored values // from pass1 - - conf.Fcst->var_info->set_level_name(mvd._flevel.c_str()); - conf.Obs->var_info->set_level_name(mvd._olevel.c_str()); - conf.Fcst->var_info->set_units(mvd._funits.c_str()); - conf.Obs->var_info->set_units(mvd._ounits.c_str()); - - if (has_union && (conf.Fcst->merge_flag == MergeType_Thresh || - conf.Obs->merge_flag == MergeType_Thresh)) { - mlog << Warning << "\nModeFrontEnd::run() -> " + conf.Fcst->var_info->set_level_name(mvdf._level.c_str()); + conf.Fcst->var_info->set_units(mvdf._units.c_str()); + if (has_union_f && conf.Fcst->merge_flag == MergeType_Thresh) { + mlog << Warning << "\nModeFrontEnd::multivar_intensity_comparisons() -> " + << "Logic includes union '||' along with 'merge_flag=THRESH' " + << ". This can lead to bad results\n\n"; + } + conf.Obs->var_info->set_level_name(mvdo._level.c_str()); + conf.Obs->var_info->set_units(mvdo._units.c_str()); + if (has_union_o && conf.Obs->merge_flag == MergeType_Thresh) { + mlog << Warning << "\nModeFrontEnd::multivar_intensity_comparisons() -> " << "Logic includes union '||' along with 'merge_flag=THRESH' " << ". This can lead to bad results\n\n"; } @@ -158,7 +302,7 @@ int ModeFrontEnd::run_multivar_pass2(const StringArray & Argv, const MultiVarDat // // set up data access using inputs // - mode_exec->setup_fcst_obs_data(mvd); + mode_exec->setup_fcst_obs_data_multivar_intensities(mvdf, mvdo); // // run the mode algorithm @@ -166,11 +310,11 @@ int ModeFrontEnd::run_multivar_pass2(const StringArray & Argv, const MultiVarDat if ( conf.quilt ) { - do_quilt(ptype); + do_quilt(); } else { - do_straight(ptype, mvd, f_merge, o_merge); + do_straight_multivar_intensity(mvdf, mvdo, merge_f, merge_o); } @@ -184,7 +328,6 @@ int ModeFrontEnd::run_multivar_pass2(const StringArray & Argv, const MultiVarDat return (0); } - /////////////////////////////////////////////////////////////////////// int ModeFrontEnd::run_super(const StringArray & Argv, @@ -193,26 +336,21 @@ int ModeFrontEnd::run_super(const StringArray & Argv, GrdFileType ftype, GrdFileType otype, const Grid &grid, bool has_union) { - Processing_t ptype = MULTIVAR_SUPER; - mlog << Debug(1) << "Running mode front end " << stype(ptype) << "\n"; - //Argv.dump(cout, 0); - - if ( mode_exec ) { delete mode_exec; mode_exec = 0; } - - mode_exec = new ModeExecutive; - compress_level = -1; + init(ModeExecutive::MULTIVAR_SUPER); // // Process the command line arguments // process_command_line(Argv, true); - mode_exec->init_multivar(ftype, otype); + + mode_exec->init_multivar_intensities(ftype, otype); + ModeConfInfo & conf = mode_exec->engine.conf_info; if (compress_level >= 0) conf.nc_info.set_compress_level(compress_level); if (has_union && (conf.Fcst->merge_flag == MergeType_Thresh || conf.Obs->merge_flag == MergeType_Thresh)) { - mlog << Warning << "\nModeFrontEnd::run() -> " + mlog << Warning << "\nModeFrontEnd::run_super() -> " << "Logic includes union '||' along with 'merge_flag=THRESH' " << ". This can lead to bad results\n\n"; } @@ -220,7 +358,7 @@ int ModeFrontEnd::run_super(const StringArray & Argv, // // set up data access using inputs // - mode_exec->setup_fcst_obs_data(f_super, o_super, grid); + mode_exec->setup_fcst_obs_data_multivar_super(f_super, o_super, grid); // // run the mode algorithm @@ -228,11 +366,11 @@ int ModeFrontEnd::run_super(const StringArray & Argv, if ( conf.quilt ) { - do_quilt(ptype); + do_quilt(); } else { - do_straight(ptype, f_merge, o_merge); + do_straight_multivar_super(f_merge, o_merge); } @@ -249,60 +387,23 @@ int ModeFrontEnd::run_super(const StringArray & Argv, /////////////////////////////////////////////////////////////////////// -void ModeFrontEnd::do_straight(Processing_t ptype, const MultiVarData &mvd, - ShapeData &f_merge, ShapeData &o_merge) +void ModeFrontEnd::do_straight() { - if (ptype != MULTIVAR_PASS2) { - - mlog << Error - << "\n\n " - << program_name - << ": called MULTIVAR_PASS2 method with " - << stype(ptype) << "\n\n"; - exit ( 1 ); - - } - - const ModeConfInfo & conf = mode_exec->engine.conf_info; + int NCT, NCR; - const int NCT = conf.n_conv_threshs(); - const int NCR = conf.n_conv_radii(); - - if ( NCT != NCR ) { - - mlog << Error - << "\n\n " - << program_name - << ": all convolution radius and threshold arrays must have the same number of elements!\n\n"; - - exit ( 1 ); - - } - - if (NCT > 1) { - mlog << Error - << "\n\n " - << program_name - << ": multiple convolution radii and thresholds not implemented in multivar mode\n\n"; - - exit ( 1 ); - } - - - - int index; + do_straight_init(NCT, NCR); mode_exec->clear_internal_r_index(); - for (index=0; indexdo_conv_thresh(index, index, false, true); - mode_exec->do_match_merge(f_merge, o_merge, ptype == MULTIVAR_SUPER); - - // here replace raw data and min/max for plotting + mode_exec->do_conv_thresh(index, index); + if (ptype == ModeExecutive::TRADITIONAL) { - mode_exec->process_output(true, false, &mvd); + mode_exec->do_match_merge(); + mode_exec->process_output(); + } } mode_exec->clear_internal_r_index(); @@ -315,55 +416,29 @@ void ModeFrontEnd::do_straight(Processing_t ptype, const MultiVarData &mvd, } - /////////////////////////////////////////////////////////////////////// -void ModeFrontEnd::do_straight(Processing_t ptype) +void ModeFrontEnd::do_straight_multivar_intensity(const MultiVarData &mvdf, + const MultiVarData &mvdo, + ShapeData &f_merge, + ShapeData &o_merge) { - - const ModeConfInfo & conf = mode_exec->engine.conf_info; - - const int NCT = conf.n_conv_threshs(); - const int NCR = conf.n_conv_radii(); - - if ( NCT != NCR ) { - - mlog << Error - << "\n\n " - << program_name - << ": all convolution radius and threshold arrays must have the same number of elements!\n\n"; - - exit ( 1 ); - - } - - if (NCT > 1 && ptype != SINGLE_VAR) { - mlog << Error - << "\n\n " - << program_name - << ": multiple convolution radii and thresholds not implemented in multivar mode\n\n"; - - exit ( 1 ); - } - - - - int index; + int NCT, NCR; + + do_straight_init(NCT, NCR); mode_exec->clear_internal_r_index(); - for (index=0; indexdo_conv_thresh(index, index, ptype == MULTIVAR_PASS1_MERGE, - ptype == MULTIVAR_PASS2, ptype == MULTIVAR_SUPER); + mode_exec->do_conv_thresh(index, index); + mode_exec->do_match_merge(f_merge, o_merge); - if (ptype == SINGLE_VAR) { + // here replace raw data and min/max for plotting - mode_exec->do_match_merge(); - mode_exec->process_output(false, false); - } + mode_exec->process_output(&mvdf, &mvdo); } mode_exec->clear_internal_r_index(); @@ -377,60 +452,24 @@ void ModeFrontEnd::do_straight(Processing_t ptype) } + /////////////////////////////////////////////////////////////////////// -void ModeFrontEnd::do_straight(Processing_t ptype, - ShapeData &f_merge, ShapeData &o_merge) +void ModeFrontEnd::do_straight_multivar_super(ShapeData &f_merge, ShapeData &o_merge) { - - const ModeConfInfo & conf = mode_exec->engine.conf_info; - - const int NCT = conf.n_conv_threshs(); - const int NCR = conf.n_conv_radii(); - - if ( NCT != NCR ) { - - mlog << Error - << "\n\n " - << program_name - << ": all convolution radius and threshold arrays must have the same number of elements!\n\n"; - - exit ( 1 ); - - } - - if (NCT > 1 && ptype != SINGLE_VAR) { - mlog << Error - << "\n\n " - << program_name - << ": multiple convolution radii and thresholds not implemented in multivar mode\n\n"; - - exit ( 1 ); - } - - - - int index; + int NCT, NCR; + + do_straight_init(NCT, NCR); mode_exec->clear_internal_r_index(); - for (index=0; indexdo_conv_thresh(index, index, ptype == MULTIVAR_PASS1_MERGE, - ptype == MULTIVAR_PASS2, ptype == MULTIVAR_SUPER); - - if (ptype == SINGLE_VAR) { + for (int index=0; indexdo_match_merge(); - mode_exec->process_output(false, false); - } - - if (ptype == MULTIVAR_SUPER) { - mode_exec->do_match_merge(f_merge, o_merge, ptype == MULTIVAR_SUPER); - mode_exec->process_output(false, true); - } + mode_exec->do_conv_thresh(index, index); + mode_exec->do_match_merge(f_merge, o_merge); + mode_exec->process_output(); } mode_exec->clear_internal_r_index(); @@ -447,13 +486,11 @@ void ModeFrontEnd::do_straight(Processing_t ptype, /////////////////////////////////////////////////////////////////////// -void ModeFrontEnd::do_quilt(Processing_t ptype) +void ModeFrontEnd::do_quilt() { - if (ptype != SINGLE_VAR) { - mlog << Error - << program_name << ": quilting not yet implemented for multivar mode \n\n"; - + if (ptype != ModeExecutive::TRADITIONAL) { + mlog << Error << "\nModeFrontend::do_quilt() -> quilting not yet implemented for multivar mode \n\n"; exit ( 1 ); } @@ -471,7 +508,7 @@ void ModeFrontEnd::do_quilt(Processing_t ptype) mode_exec->do_match_merge(); - if (ptype == SINGLE_VAR) { + if (ptype == ModeExecutive::TRADITIONAL) { mode_exec->process_output(); } } @@ -489,16 +526,60 @@ void ModeFrontEnd::do_quilt(Processing_t ptype) /////////////////////////////////////////////////////////////////////// -MultiVarData *ModeFrontEnd::get_multivar_data() {return mode_exec->get_multivar_data(); } +MultiVarData *ModeFrontEnd::get_multivar_data(ModeDataType dtype) +{ + return mode_exec->get_multivar_data(dtype); +} + + +/////////////////////////////////////////////////////////////////////// +void ModeFrontEnd::add_multivar_merge_data(MultiVarData *mvdi, ModeDataType dtype) +{ + return mode_exec->add_multivar_merge_data(mvdi, dtype); +} /////////////////////////////////////////////////////////////////////// -void ModeFrontEnd::addMultivarMergePass1(MultiVarData *mvdi) +void ModeFrontEnd::init(ModeExecutive::Processing_t p) { - return mode_exec->addMultivarMergePass1(mvdi); + ptype = p; + mlog << Debug(1) << "Running multivar front end for " << ModeExecutive::stype(ptype) << "\n"; + + if ( mode_exec ) { delete mode_exec; mode_exec = 0; } + + mode_exec = new ModeExecutive(ptype); + compress_level = -1; } +/////////////////////////////////////////////////////////////////////// + +void ModeFrontEnd::do_straight_init(int &NCT, int &NCR) const +{ + const ModeConfInfo & conf = mode_exec->engine.conf_info; + + NCT = conf.n_conv_threshs(); + NCR = conf.n_conv_radii(); + + if ( NCT != NCR ) { + + mlog << Error << "\nModeFrontEnd::do_straight_init() ->" + << "all convolution radius and threshold arrays must have the same number of elements\n\n"; + + exit ( 1 ); + + } + + if (NCT > 1 && ptype != ModeExecutive::TRADITIONAL) { + + mlog << Error << "\nModeFrontEnd::do_straight_init() ->" + << ": multiple convolution radii and thresholds not implemented in multivar mode\n\n"; + + exit ( 1 ); + } +} + + /////////////////////////////////////////////////////////////////////// void ModeFrontEnd::process_command_line(const StringArray & argv, bool ismultivar) @@ -578,33 +659,74 @@ void ModeFrontEnd::process_command_line(const StringArray & argv, bool ismultiva } } + /////////////////////////////////////////////////////////////////////// -string ModeFrontEnd::stype(Processing_t t) +void ModeFrontEnd::process_command_line_for_simple_objects(const StringArray &argv, ModeDataType dtype) { - string s; - switch (t) { - case MULTIVAR_PASS1: - s = "Multivar Pass 1"; - break; - case MULTIVAR_PASS1_MERGE: - s = "Multivar Pass 1 Merge"; - break; - case MULTIVAR_PASS2: - s = "Multivar Pass 2"; - break; - case MULTIVAR_SUPER: - s = "Multivar Superobject Pass"; - break; - case SINGLE_VAR: - default: - s = "SingleVar"; - break; + CommandLine cline; + ConcatString s; + const int argc = argv.n(); + + // + // Set the default output directory + // + + mode_exec->out_dir = replace_path(default_out_dir); + + // + // Check for zero arguments (note not correct for multivar mode, want to show multivar_usage + // + + if(argc == 1) singlevar_usage(); + + // + // Parse the command line into tokens + // + + cline.set(argv); + + // + // Set the usage function NOTE wrong for multivar, want multivar_usage + // + + cline.set_usage(singlevar_usage); + + // + // Add the options function calls + // + + cline.add(set_config_merge_file, "-config_merge", 1); + cline.add(set_outdir, "-outdir", 1); + cline.add(set_logfile, "-log", 1); + cline.add(set_verbosity, "-v", 1); + cline.add(set_compress, "-compress", 1); + + // + // Parse the command line + // + + cline.parse(); + + // + // Check for error. There should be two arguments left: + // data and config filenames + // + if(cline.n() != 2) singlevar_usage(); + + // + // Store the file name + // + if (dtype == ModeDataType_MvMode_Fcst) { + mode_exec->fcst_file = cline[0]; + mode_exec->obs_file = "None"; + } else { + mode_exec->obs_file = cline[0]; + mode_exec->fcst_file = "None"; } - return s; + mode_exec->match_config_file = cline[1]; } - /////////////////////////////////////////////////////////////////////// void ModeFrontEnd::set_config_merge_file(const StringArray & a) diff --git a/src/tools/core/mode/mode_frontend.h b/src/tools/core/mode/mode_frontend.h index 31d7ad5de3..55ecdf7f50 100644 --- a/src/tools/core/mode/mode_frontend.h +++ b/src/tools/core/mode/mode_frontend.h @@ -20,14 +20,13 @@ #include "mode_exec.h" #include "string_array.h" #include "multivar_data.h" +#include "mode_data_type.h" class ModeFrontEnd { - private: + private: - public: - - typedef enum {SINGLE_VAR, MULTIVAR_PASS1, MULTIVAR_PASS1_MERGE, MULTIVAR_PASS2, MULTIVAR_SUPER} Processing_t; + public: ModeFrontEnd(); ~ModeFrontEnd(); @@ -35,38 +34,54 @@ class ModeFrontEnd { string default_out_dir; - // default single var mode interface, and multivar pass1 options - int run(const StringArray & Argv, Processing_t ptype=SINGLE_VAR, int field_index=-1, int n_files=1); + Grid create_verification_grid(const StringArray & Argv); + + // run the multivar simple object, where there is only one input data, either forecast or obs + int create_multivar_simple_objects(const StringArray & Argv, ModeDataType dtype, const Grid &verification_grid, + int field_index=-1, int n_files=1); + + // run the multivar simple object merge algorithm, with one input data, either forecast or obs + int create_multivar_merge_objects(const StringArray & Argv, ModeDataType dtype, const Grid &verification_grid, + int field_index=-1, int n_files=1); + + // run the default single var mode interface (traditional mode) + int run_traditional(const StringArray & Argv); - // pass2 multivar interface - int run_multivar_pass2(const StringArray & Argv, const MultiVarData &mvd, bool has_union, - ShapeData &f_merge, ShapeData &o_merge, int field_index); + // run the multivar intensity algorithm, where one forecast and one obs are restricted to be within superobjects + // and the traditional mode algorithm compares them + int multivar_intensity_comparisons(const StringArray & Argv, const MultiVarData &mvdf, const MultiVarData &mvdo, + bool has_union_f, bool has_union_o, ShapeData &merge_f, + ShapeData &merge_o, int field_index_f, int field_index_o); - // multivar superobject interface, no intensities + // multivar superobject interface, with no intensities int run_super(const StringArray & Argv, ShapeData &f_super, ShapeData &o_super, ShapeData &f_merge, ShapeData &o_merge, GrdFileType ftype, GrdFileType otype, const Grid &grid, bool has_union); - void do_quilt (Processing_t ptype); + // so far only implemented for traditional mode + void do_quilt (); - // single var mode, or multivar pass1 - void do_straight (Processing_t ptype); + // MODE algorithm for traditional, multivar simple, or multivar merge cases + void do_straight (); - // multivar pass2 - void do_straight (Processing_t ptype, const MultiVarData &mvd, - ShapeData &f_merge, ShapeData &o_merge); + // MODE algorithm when doing multivar intensities + void do_straight_multivar_intensity (const MultiVarData &mvdf, + const MultiVarData &mvdo, ShapeData &mergef, + ShapeData &mergeo); - // multivar super, no intensities - void do_straight (Processing_t ptype, - ShapeData &f_merge, ShapeData &o_merge); + // MODE algorithm when doing multivar super with no intensities + void do_straight_multivar_super (ShapeData &f_merge, ShapeData &o_merge); - MultiVarData *get_multivar_data(); - void addMultivarMergePass1(MultiVarData *mvdi); + MultiVarData *get_multivar_data(ModeDataType dtype); - void process_command_line(const StringArray &, bool is_multivar); + void add_multivar_merge_data(MultiVarData *mvdi, ModeDataType dtype); + + void init(ModeExecutive::Processing_t p); + void do_straight_init(int &NCT, int &NCR) const; - static string stype(Processing_t t); + void process_command_line_for_simple_objects(const StringArray &, ModeDataType dtype); + void process_command_line(const StringArray &, bool is_multivar); static void set_config_merge_file (const StringArray &); static void set_outdir (const StringArray &); diff --git a/src/tools/core/mode/multivar_data.cc b/src/tools/core/mode/multivar_data.cc index 703ad54e8a..1d38d270ba 100644 --- a/src/tools/core/mode/multivar_data.cc +++ b/src/tools/core/mode/multivar_data.cc @@ -38,84 +38,56 @@ static void populate_bool_plane(const string &name, const int * buf, const int n static void _debug_shape_examine(const string &name, const ShapeData &sd, int nx, int ny); -void MultiVarData1::set_fcst_obj(ShapeData *sd) +void MultiVarData1::set_obj(ShapeData *sd) { - if (_fcst_obj_sd) { - delete _fcst_obj_sd; + if (_obj_sd) { + delete _obj_sd; } - _fcst_obj_sd = new ShapeData(*sd); + _obj_sd = new ShapeData(*sd); - if (_fcst_obj_data) { - delete _fcst_obj_data; + if (_obj_data) { + delete _obj_data; } - _fcst_obj_data = _fill_int_array(sd); + _obj_data = _fill_int_array(sd); } -void MultiVarData1::set_fcst_raw(ShapeData *sd) +void MultiVarData1::set_raw(ShapeData *sd) { - if (_fcst_raw_data) { - delete _fcst_raw_data; + if (_raw_data) { + delete _raw_data; } - _fcst_raw_data = _fill_float_array(sd); - + _raw_data = _fill_float_array(sd); } -void MultiVarData1::set_obs_obj(ShapeData *sd) +void MultiVarData1::set_shapedata(const ShapeData &sd) { - if (_obs_obj_sd) { - delete _obs_obj_sd; - } - _obs_obj_sd = new ShapeData(*sd); - - if (_obs_obj_data) { - delete _obs_obj_data; - } - _obs_obj_data = _fill_int_array(sd); -} - -void MultiVarData1::set_obs_raw(ShapeData *sd) -{ - if (_obs_raw_data) { - delete _obs_raw_data; - } - _obs_raw_data = _fill_float_array(sd); - + if (_sd) delete _sd; + _sd = new ShapeData(sd); } -void MultiVarData1::set_fcst_shapedata(const ShapeData &sd) +void MultiVarData1::set_conv_thresh_array(const ThreshArray &t) { - if (_Fcst_sd) delete _Fcst_sd; - _Fcst_sd = new ShapeData(sd); + _convThreshArray = t; } -void MultiVarData1::set_obs_shapedata(const ShapeData &sd) +void MultiVarData1::set_merge_thresh_array(const ThreshArray &t) { - if (_Obs_sd) delete _Obs_sd; - _Obs_sd = new ShapeData(sd); + _mergeThreshArray = t; } void MultiVarData1::objects_from_arrays(bool do_clusters, - BoolPlane & fcst_out, - BoolPlane & obs_out) + BoolPlane & out) { - string name = _name + "_Fcst"; - populate_bool_plane(name, _fcst_obj_data, _nx, _ny, fcst_out); - name = _name + "_Obs"; - populate_bool_plane(name, _obs_obj_data, _nx, _ny, obs_out); + string name = _name + "_" + sprintModeDataType(_dataType); + populate_bool_plane(name, _obj_data, _nx, _ny, out); } -void MultiVarData1::print(const string &fname, const string &oname) const +void MultiVarData1::print(const string &name) const { string n; - n = fname + "_" + _name + "_Fcst_Obj"; - if (_fcst_obj_data) { - _print_summary(n, _fcst_obj_data, *_fcst_obj_sd); - } else { - mlog << Debug(2) << n << " is empty\n"; - } - n = oname + "_" + _name + "_Obs_Obj"; - if (_obs_obj_data) { - _print_summary(n, _obs_obj_data, *_obs_obj_sd); + n = name + "_" + _name + "_" + sprintModeDataType(_dataType) + "_Obj"; + if (_obj_data) { + _print_summary(n, _obj_data, *_obj_sd); } else { mlog << Debug(2) << n << " is empty\n"; } @@ -165,18 +137,16 @@ void MultiVarData1::_print_summary(const string &name, int *data, const ShapeDat } MultiVarData::MultiVarData() : + _dataType(ModeDataType_MvMode_Both), _simple(0), _merge(0), - _f_name("notset"), - _o_name("notset"), + _name("notset"), _nx(0), _ny(0), _grid(0), - _ftype(FileType_None), - _otype(FileType_None) + _type(FileType_None) { } - MultiVarData::~MultiVarData() { _clear(); @@ -185,124 +155,91 @@ MultiVarData::~MultiVarData() void MultiVarData::checkFileTypeConsistency(const MultiVarData &mvdi, int j) { bool err = false; - if (_ftype != mvdi._ftype) { - err = true; - mlog << Error << "\n" - << ": forecast inputs of different file types not supported " - << "Input 0:" << grdfiletype_to_string(_ftype).c_str() - << "Input " << j << ":" << grdfiletype_to_string(mvdi._ftype).c_str() + if (_type != mvdi._type) { + mlog << Error << "MultivarData::checkFileTypeConsistgency() -> " + << "inputs of different file types not supported " + << "Input 0:" << grdfiletype_to_string(_type).c_str() + << "Input " << j << ":" << grdfiletype_to_string(mvdi._type).c_str() << "\n\n"; - } - - if (_otype != mvdi._otype) { - err = true; - mlog << Error << "\n" - << ": obs inputs of different file types not supported " - << "Input 0:" << grdfiletype_to_string(_otype).c_str() - << "Input " << j << ":" << grdfiletype_to_string(mvdi._otype).c_str() - << "\n\n"; - } - if (err) { exit ( 1 ); } } -void MultiVarData::init(const string &fname, const string &oname, - const Grid &grid, GrdFileType ftype, - GrdFileType otype, - const string &funits, const string &ounits, - const string &flevel, const string &olevel, +void MultiVarData::init(ModeDataType dataType, + const string &name, + const Grid &grid, GrdFileType type, + const string &units, + const string &level, double data_min, double data_max) { _clear(); - _f_name = fname; - _o_name = oname; + + _dataType = dataType; + _name = name; _nx = grid.nx(); _ny = grid.ny(); _grid = new Grid(grid); - _ftype = ftype; - _otype = otype; - _funits = funits; - _ounits = ounits; - _flevel = flevel; - _olevel = olevel; + _type = type; + _units = units; + _level = level; _data_min = data_min; _data_max = data_max; - _simple = new MultiVarData1(_nx, _ny, "Simple"); - _merge = new MultiVarData1(_nx, _ny, "Merge"); + _simple = new MultiVarData1(_nx, _ny, "Simple", _dataType); + _merge = new MultiVarData1(_nx, _ny, "Merge", _dataType); } - -void MultiVarData::set_fcst_obj(ShapeData *sd, bool simple) +void MultiVarData::set_obj(ShapeData *sd, bool simple) { if (simple) { - _simple->set_fcst_obj(sd); + _simple->set_obj(sd); } else { - _merge->set_fcst_obj(sd); - } -} - -void MultiVarData::set_fcst_raw(ShapeData *sd, bool simple) -{ - if (simple) { - _simple->set_fcst_raw(sd); - } else { - _merge->set_fcst_raw(sd); + _merge->set_obj(sd); } } -void MultiVarData::set_obs_obj(ShapeData *sd, bool simple) +void MultiVarData::set_raw(ShapeData *sd, bool simple) { if (simple) { - _simple->set_obs_obj(sd); + _simple->set_raw(sd); } else { - _merge->set_obs_obj(sd); + _merge->set_raw(sd); } } -void MultiVarData::set_obs_raw(ShapeData *sd, bool simple) +void MultiVarData::set_shapedata(const ShapeData &sd, bool simple) { if (simple) { - _simple->set_obs_raw(sd); + _simple->set_shapedata(sd); } else { - _merge->set_obs_raw(sd); - } -} - -void MultiVarData::set_fcst_shapedata(const ShapeData &sd, bool simple) -{ - if (simple) { - _simple->set_fcst_shapedata(sd); - } else { - _merge->set_fcst_shapedata(sd); + _merge->set_shapedata(sd); } } -void MultiVarData::set_obs_shapedata(const ShapeData &sd, bool simple) +void MultiVarData::set_conv_thresh_array(const ThreshArray &t, bool simple) { if (simple) { - _simple->set_obs_shapedata(sd); + _simple->set_conv_thresh_array(t); } else { - _merge->set_obs_shapedata(sd); + _merge->set_conv_thresh_array(t); } } -const ShapeData *MultiVarData::fcst_shapedata_ptr(bool simple) const +void MultiVarData::set_merge_thresh_array(const ThreshArray &t, bool simple) { if (simple) { - return _simple->_Fcst_sd; + _simple->set_merge_thresh_array(t); } else { - return _merge->_Fcst_sd; + _merge->set_merge_thresh_array(t); } } -const ShapeData *MultiVarData::obs_shapedata_ptr(bool simple) const +const ShapeData *MultiVarData::shapedata_ptr(bool simple) const { if (simple) { - return _simple->_Obs_sd; + return _simple->_sd; } else { - return _merge->_Obs_sd; + return _merge->_sd; } } @@ -310,14 +247,13 @@ const ShapeData *MultiVarData::obs_shapedata_ptr(bool simple) const void MultiVarData::objects_from_arrays(bool do_clusters, - bool simple, - BoolPlane & fcst_out, - BoolPlane & obs_out) + bool simple, + BoolPlane & out) { if (simple) { - _simple->objects_from_arrays(do_clusters, fcst_out, obs_out); + _simple->objects_from_arrays(do_clusters, out); } else { - _merge->objects_from_arrays(do_clusters, fcst_out, obs_out); + _merge->objects_from_arrays(do_clusters, out); } } @@ -325,11 +261,10 @@ void MultiVarData::objects_from_arrays(bool do_clusters, //////////////////////////////////////////////////////////////////////// - void MultiVarData::print(void) const { - _simple->print(_f_name, _o_name); - _merge->print(_f_name, _o_name); + _simple->print(_name); + _merge->print(_name); } @@ -351,8 +286,7 @@ void MultiVarData::_clear() _grid = 0; } _nx = _ny = 0; - _ftype = FileType_None; - _otype = FileType_None; + _type = FileType_None; } diff --git a/src/tools/core/mode/multivar_data.h b/src/tools/core/mode/multivar_data.h index 99ead96419..142e1aa65b 100644 --- a/src/tools/core/mode/multivar_data.h +++ b/src/tools/core/mode/multivar_data.h @@ -22,6 +22,7 @@ #include "vx_grid.h" #include "data_file_type.h" #include "two_d_array.h" +#include "mode_data_type.h" class MultiVarData1 { @@ -33,50 +34,44 @@ class MultiVarData1 { public: - inline MultiVarData1(int nx, int ny, const string &name) : + inline MultiVarData1(int nx, int ny, const string &name, + ModeDataType dataType) : + _dataType(dataType), _name(name), - _fcst_obj_sd(0), - _obs_obj_sd(0), - _fcst_obj_data(0), - _obs_obj_data(0), - _fcst_raw_data(0), - _obs_raw_data(0), - _Fcst_sd(0), _Obs_sd(0), - _nx(nx), _ny(ny) + _obj_sd(0), + _obj_data(0), + _raw_data(0), + _sd(0), + _nx(nx), _ny(ny), + _convThreshArray(), + _mergeThreshArray() {} inline ~MultiVarData1() { - if (_fcst_obj_sd) delete _fcst_obj_sd; - if (_obs_obj_sd) delete _obs_obj_sd; - if (_fcst_obj_data) delete [] _fcst_obj_data; - if (_obs_obj_data) delete [] _obs_obj_data; - if (_fcst_raw_data) delete [] _fcst_raw_data; - if (_obs_raw_data) delete [] _obs_raw_data; - if (_Fcst_sd) delete _Fcst_sd; - if (_Obs_sd) delete _Obs_sd; + if (_obj_sd) delete _obj_sd; + if (_obj_data) delete [] _obj_data; + if (_raw_data) delete [] _raw_data; + if (_sd) delete _sd; } - void set_fcst_obj(ShapeData *sd); - void set_fcst_raw(ShapeData *sd); - void set_obs_obj(ShapeData *sd); - void set_obs_raw(ShapeData *sd); - void set_fcst_shapedata(const ShapeData &sd); - void set_obs_shapedata(const ShapeData &sd); + void set_obj(ShapeData *sd); + void set_raw(ShapeData *sd); + void set_shapedata(const ShapeData &sd); + void set_conv_thresh_array(const ThreshArray &t); + void set_merge_thresh_array(const ThreshArray &t); void objects_from_arrays(bool do_clusters, - BoolPlane & fcst_out, - BoolPlane & obs_out); - void print(const string &fname, const string &oname) const; + BoolPlane & out); + void print(const string &name) const; + ModeDataType _dataType; string _name; - ShapeData *_fcst_obj_sd; - ShapeData *_obs_obj_sd; - int *_fcst_obj_data; - int *_obs_obj_data; - float *_fcst_raw_data; - float *_obs_raw_data; - ShapeData *_Fcst_sd; - ShapeData *_Obs_sd; + ShapeData *_obj_sd; + int *_obj_data; + float *_raw_data; + ShapeData *_sd; int _nx, _ny; + ThreshArray _convThreshArray; + ThreshArray _mergeThreshArray; }; class MultiVarData { @@ -92,38 +87,34 @@ class MultiVarData { void checkFileTypeConsistency(const MultiVarData &mvdi, int j); - void init(const string &fname, const string &oname, - const Grid &grid, GrdFileType ftype, GrdFileType otype, - const string &funits, const string &ounits, - const string &flevel, const string &olevel, + void init(ModeDataType dataType, + const string &name, + const Grid &grid, GrdFileType type, + const string &units, + const string &level, double data_min, double data_max); - void set_fcst_obj(ShapeData *sd, bool simple); - void set_fcst_raw(ShapeData *sd, bool simple); - void set_obs_obj(ShapeData *sd, bool simple); - void set_obs_raw(ShapeData *sd, bool simple); - void set_fcst_shapedata(const ShapeData &sd, bool simple); - void set_obs_shapedata(const ShapeData &sd, bool simple); - const ShapeData *fcst_shapedata_ptr(bool simple) const; - const ShapeData *obs_shapedata_ptr(bool simple) const; - void objects_from_arrays(bool do_clusters, bool simple, BoolPlane & fcst_out, - BoolPlane & obs_out); + + void set_obj(ShapeData *sd, bool simple); + void set_raw(ShapeData *sd, bool simple); + void set_shapedata(const ShapeData &sd, bool simple); + void set_conv_thresh_array(const ThreshArray &t, bool simple); + void set_merge_thresh_array(const ThreshArray &t, bool simple); + const ShapeData *shapedata_ptr(bool simple) const; + void objects_from_arrays(bool do_clusters, bool simple, BoolPlane & out); void print(void) const; - + ModeDataType _dataType; MultiVarData1 *_simple; MultiVarData1 *_merge; - string _f_name; - string _o_name; + string _name; int _nx, _ny; Grid *_grid; - GrdFileType _ftype; - GrdFileType _otype; - string _funits, _ounits; - string _flevel, _olevel; + GrdFileType _type; + string _units; + string _level; double _data_min, _data_max; }; - #endif /* __MODE_FRONT_END_H__ */ diff --git a/src/tools/core/mode/multivar_frontend.cc b/src/tools/core/mode/multivar_frontend.cc index c19a3ad0b0..2205fc4329 100644 --- a/src/tools/core/mode/multivar_frontend.cc +++ b/src/tools/core/mode/multivar_frontend.cc @@ -51,6 +51,7 @@ using namespace std; #include "parse_file_list.h" #include "mode_frontend.h" #include "multivar_data.h" +#include "mode_data_type.h" using namespace netCDF; @@ -79,6 +80,7 @@ static string obs_fof; static string config_file; static string outdir; +static Grid verification_grid; //////////////////////////////////////////////////////////////////////// @@ -88,19 +90,33 @@ static void set_logfile (const StringArray &); static void set_verbosity (const StringArray &); static void multivar_consistency_checks(StringArray &fcst_filenames, StringArray &obs_filenames, - BoolCalc &f_calc, BoolCalc &o_calc, int &n_files); + BoolCalc &f_calc, BoolCalc &o_calc, int &n_fcst_files, + int &n_obs_files); static ConcatString set_multivar_dir(); -static MultiVarData *create_simple_objects(int j, int n_files, - const string &fcst_filename, const string &obs_filename, +static void create_verification_grid(const string &fcst_filename, + const string &obs_filename, + const ConcatString &dir); + +static MultiVarData *create_simple_objects(ModeDataType dtype, int j, int n_files, + const string &filename, const ConcatString &dir); -static void create_singlevar_intensity_objects(int j, const BoolPlane &f_result, - const BoolPlane &o_result, - int nx, int ny, const ConcatString &dir, - MultiVarData &mvd, bool has_union, - ShapeData &f_merge, ShapeData &o_merge); +static void create_superobjects(int n_fcst_files, const vector &mvdFcst, + int n_obs_files, const vector &mvdObs, + BoolCalc &f_calc, BoolCalc &o_calc, + BoolPlane &f_simple_result, BoolPlane &o_simple_result, + ShapeData &f_simple_sd, ShapeData &o_simple_sd, + ShapeData &f_merge_sd_split, ShapeData &o_merge_sd_split); + +static void create_intensity_comparisons(int findex, int oindex, const BoolPlane &f_result, + BoolPlane &o_result, + const ConcatString &dir, + MultiVarData &mvdf, MultiVarData &mvdo, + bool has_union_f, bool has_union_o, + const string &fcst_filename, const string &obs_filename, + ShapeData &merge_f, ShapeData &merge_o); static void process_superobjects(ShapeData &f_result, ShapeData &o_result, ShapeData &f_merge, ShapeData &o_merge, @@ -130,7 +146,7 @@ int multivar_frontend(const StringArray & Argv) if ( Argc < 4 ) multivar_usage(); - int j, n_files; + int j, n_fcst_files, n_obs_files; StringArray fcst_filenames; StringArray obs_filenames; BoolCalc f_calc, o_calc ; @@ -139,182 +155,111 @@ int multivar_frontend(const StringArray & Argv) read_config(config_file); - multivar_consistency_checks(fcst_filenames, obs_filenames, f_calc, o_calc, n_files); + multivar_consistency_checks(fcst_filenames, obs_filenames, f_calc, o_calc, + n_fcst_files, n_obs_files); - bool has_union = f_calc.has_union() || o_calc.has_union(); + bool f_has_union = f_calc.has_union(); + bool o_has_union = o_calc.has_union(); mlog << Debug(2) << "\n" << sep << "\n"; ConcatString dir = set_multivar_dir(); + // first thing to do is to define the verification grid using the 0th + // fcst and obs inputs + mlog << Debug(2) << "\n creating the verification grid \n" << sep << "\n"; + + create_verification_grid(fcst_filenames[0], obs_filenames[0], dir); + // // do the individual mode runs which produce everything needed to create - // super objects (stored in 'mvd') (both simple and 'merge'). + // super objects (stored in 'mvdObs', 'mvdFcst') (both simple and merge steps + // are done here). // - vector mvd; + vector mvdObs, mvdFcst; - for (j=0; j 0) { - mvd[0]->checkFileTypeConsistency(*mvdi, j); + mvdFcst[0]->checkFileTypeConsistency(*mvdi, j); } - mvd.push_back(mvdi); + mvdFcst.push_back(mvdi); mvdi->print(); - } // for j - mlog << Debug(2) << "\n finished with individual mode runs " << "\n" << sep << "\n"; + for (j=0; j 0) { + mvdObs[0]->checkFileTypeConsistency(*mvdi, j); + } + mvdObs.push_back(mvdi); + mvdi->print(); + } // for j - BoolPlane * f_simple_plane = new BoolPlane [n_files]; - BoolPlane * o_simple_plane = new BoolPlane [n_files]; - BoolPlane * f_merge_plane = new BoolPlane [n_files]; - BoolPlane * o_merge_plane = new BoolPlane [n_files]; + mlog << Debug(2) << "\n finished with simple multivar mode runs " << "\n" << sep << "\n"; - bool simple = true; - for (j=0; jobjects_from_arrays(do_clusters, simple, f_simple_plane[j], o_simple_plane[j]); - } + // now create forecast and obs superobjects + + BoolPlane f_simple_result, o_simple_result; + ShapeData f_simple_sd, o_simple_sd, f_merge_sd_split, o_merge_sd_split; - simple = false; - for (j=0; jobjects_from_arrays(do_clusters, simple, f_merge_plane[j], o_merge_plane[j]); - } + create_superobjects(n_fcst_files, mvdFcst, n_obs_files, mvdObs, + f_calc, o_calc, f_simple_result, o_simple_result, + f_simple_sd, o_simple_sd, + f_merge_sd_split, o_merge_sd_split); // - // combine the objects into super-objects - // - - const int nx = f_simple_plane[0].nx(); - const int ny = f_simple_plane[0].ny(); - BoolPlane f_simple_result, o_simple_result, f_merge_result, o_merge_result; - - f_simple_result.set_size(nx, ny); - o_simple_result.set_size(nx, ny); - f_merge_result.set_size(nx, ny); - o_merge_result.set_size(nx, ny); - - combine_boolplanes("Fcst_Simple", f_simple_plane, n_files, f_calc, f_simple_result); - combine_boolplanes("Obs_Simple", o_simple_plane, n_files, o_calc, o_simple_result); - - combine_boolplanes("Fcst_Merge", f_merge_plane, n_files, f_calc, f_merge_result); - combine_boolplanes("Obs_Merge", o_merge_plane, n_files, o_calc, o_merge_result); + // Filter the data to within the superobjects only and do statistics by invoking mode algorithm again + // on the masked data pairs + // + for (int k=0; k_ftype; - GrdFileType otype = mvd[0]->_otype; + if (config.fcst_multivar_compare_index.n() <= 0) { - // might need this for a super passs, so store locally - Grid grid = *(mvd[0]->_grid); + // grab all the info needed for superobject mode + int nx = mvdFcst[0]->_nx; + int ny = mvdFcst[0]->_ny; + GrdFileType ftype = mvdFcst[0]->_type; + GrdFileType otype = mvdObs[0]->_type; + Grid grid = *(mvdFcst[0]->_grid); - // create ShapeData objects using something from mvd as a template - // shape data with 1's or bad + // here run one more time using superobjects as input - ShapeData f_simple_sd = ShapeData(*(mvd[0]->_simple->_Fcst_sd)); - for (int x=0; x_simple->_Fcst_sd)); - for (int x=0; x_simple->_Fcst_sd)); - for (int x=0; x_simple->_Fcst_sd)); - for (int x=0; x" + << "fcst multivar logic not specified in multivar mode!\n\n"; exit ( 1 ); } if ( config.obs_multivar_logic.empty() ) { - mlog << Error << "\n" << program_name - << ": obs multivar logic not specified in multivar mode!\n\n"; + mlog << Error << "\nmultivar_consistency_checks() ->" + << "obs multivar logic not specified in multivar mode!\n\n"; exit ( 1 ); } - // - // make sure there are the same number of obs and fcst files - // - fcst_filenames = parse_ascii_file_list(fcst_fof.c_str()); obs_filenames = parse_ascii_file_list(obs_fof.c_str()); - if ( fcst_filenames.n() != obs_filenames.n() ) { - - mlog << Error << "\n" << program_name - << ": number of fcst and obs files should be the same in multivar mode!\n\n"; - exit ( 1 ); - - } + n_fcst_files = fcst_filenames.n(); + n_obs_files = obs_filenames.n(); // // check for multivar being actually multi. // + if ( n_fcst_files < 2 && n_obs_files < 2) { - n_files = fcst_filenames.n(); - if ( n_files < 2 ) { - - mlog << Error << "\n" << program_name - << ": want at least 2 input forecast files in multivar mode, got " << n_files << "\n\n"; + mlog << Error << "\nmultivar_consistency_checks() ->" + << "Want at least 2 input files for fcst or obs in multivar mode, neither had 2 or more\n\n"; exit ( 1 ); - } // @@ -490,43 +423,43 @@ void multivar_consistency_checks(StringArray &fcst_filenames, StringArray &obs_f f_calc.set(config.fcst_multivar_logic.text()); o_calc.set(config.obs_multivar_logic.text()); - if (!f_calc.check_args(n_files)) { + if (!f_calc.check_args(n_fcst_files)) { exit ( 1 ); } - if (!o_calc.check_args(n_files)) { + if (!o_calc.check_args(n_obs_files)) { exit ( 1 ); } - // - // check that the multivar_intensity vector is the right length. - // If empty set to the default of all FALSE - // - int num_multivar = (int)config.multivar_intensity.n(); - if (num_multivar == 0) { - // note this will not happen until the method - // ModeConfInfo::check_multivar_not_immplemented() allows 'all false' - // right now error exit before you get to here. - - mlog << Warning << "\nmultivar_frontend() -> " - << "empty multivar intensity array, setting to all FALSE \n\n"; + if (config.fcst_multivar_compare_index.n() != config.obs_multivar_compare_index.n()) { + mlog << Error << "\nmultivar_consistency_checks() ->" + << " Need equal number of multivar_compare_index entries for obs and fcst\n\n"; + exit(1); + } - for (int i=0; i n_fcst_files) { + mlog << Error << "\nmultivar_consistency_checks() ->" + << " forecast index " << findex + << " out of range, " << conf_key_fcst_multivar_compare_index << " array\n"; + badIndex = true; + } + if (oindex <= 0 || oindex > n_obs_files) { + mlog << Error << "\nmultivar_consistency_checks() ->" + << " obs index " << oindex + << " out of range, " << conf_key_obs_multivar_compare_index << " array\n"; + badIndex = true; } - - } else if (num_multivar != n_files) { - - mlog << Error << "\n" << program_name - << ": wrong size multivar_intensity array, wanted " - << n_files << " got " << num_multivar << "\n\n"; - exit ( 1 ); } - - // check that fcst and obs arrays are both the same length as everything else - // actually don't need this as it's done inside the mode_config class - + if (badIndex) { + mlog << Error << "\n"; + exit(1); + } } //////////////////////////////////////////////////////////////////////// @@ -556,8 +489,8 @@ ConcatString set_multivar_dir() if ( status < 0 ) { - mlog << Error << "\n" << program_name - << ": unable to create output directory \"" + mlog << Error << "\nset_multivar_dir() ->" + << " unable to create output directory \"" << dir << "\"\n\n"; exit ( 1 ); @@ -568,15 +501,14 @@ ConcatString set_multivar_dir() //////////////////////////////////////////////////////////////////////// -MultiVarData *create_simple_objects(int j, int n_files, const string &fcst_filename, - const string &obs_filename, - const ConcatString &dir) +void create_verification_grid(const string &fcst_filename, const string &obs_filename, + const ConcatString &dir) { ConcatString command; StringArray a, mode_argv; // - // build the command for running mode + // build the command for running mode frontend // mode_argv.clear(); @@ -588,7 +520,7 @@ MultiVarData *create_simple_objects(int j, int n_files, const string &fcst_filen command << cs_erase << mode_path << ' ' << fcst_filename << ' ' - << obs_filename << ' ' + << obs_filename << ' ' << config_file; mode_argv.add("-v"); @@ -608,17 +540,65 @@ MultiVarData *create_simple_objects(int j, int n_files, const string &fcst_filen mlog << Debug(3) << "Running mode command: \"" << command << "\"\n\n"; ModeFrontEnd *frontend = new ModeFrontEnd; - int status = frontend->run(mode_argv, ModeFrontEnd::MULTIVAR_PASS1, j, n_files); - MultiVarData *mvdi = frontend->get_multivar_data(); + verification_grid = frontend->create_verification_grid(mode_argv); + delete frontend; + + +} + +//////////////////////////////////////////////////////////////////////// + +MultiVarData *create_simple_objects(ModeDataType dtype, int j, int n_files, + const string &filename, + const ConcatString &dir) +{ + ConcatString command; + StringArray a, mode_argv; + + // + // build the command for running mode frontend + // + + mode_argv.clear(); + mode_argv.add(mode_path); + mode_argv.add(filename); + mode_argv.add(config_file); + + command << cs_erase + << mode_path << ' ' + << filename << ' ' + << config_file; + + mode_argv.add("-v"); + char junk [256]; + snprintf(junk, sizeof(junk), "%d", mlog.verbosity_level()); + mode_argv.add(junk); + + mode_argv.add("-outdir"); + mode_argv.add(dir); + + command << " -v " << mlog.verbosity_level(); + command << " -outdir " << dir; + + // + // create the simple objects, forecast or obs, from this input data file + // + + mlog << Debug(3) << "Running mode command: \"" << command << "\"\n\n"; + ModeFrontEnd *frontend = new ModeFrontEnd; + int status = frontend->create_multivar_simple_objects(mode_argv, dtype, verification_grid, j, n_files); + MultiVarData *mvdi = frontend->get_multivar_data(dtype); delete frontend; // - // run the pass1 merge portions of mode, which creates merge simple objects + // create simple merge objects // frontend = new ModeFrontEnd; - status = frontend->run(mode_argv, ModeFrontEnd::MULTIVAR_PASS1_MERGE, j, n_files); - frontend->addMultivarMergePass1(mvdi); + status = frontend->create_multivar_merge_objects(mode_argv, dtype, verification_grid, j, n_files); + + // add the merge results to the mvdi object + frontend->add_multivar_merge_data(mvdi, dtype); delete frontend; return mvdi; @@ -626,24 +606,136 @@ MultiVarData *create_simple_objects(int j, int n_files, const string &fcst_filen //////////////////////////////////////////////////////////////////////// -void create_singlevar_intensity_objects(int j, const BoolPlane &f_result, - const BoolPlane &o_result, int nx, int ny, - const ConcatString &dir, MultiVarData &mvd, - bool has_union, ShapeData &f_merge, ShapeData &o_merge) +void create_superobjects(int n_fcst_files, const vector &mvdFcst, + int n_obs_files, const vector &mvdObs, + BoolCalc &f_calc, BoolCalc &o_calc, + BoolPlane &f_simple_result, BoolPlane &o_simple_result, + ShapeData &f_simple_sd, ShapeData &o_simple_sd, + ShapeData &f_merge_sd_split, ShapeData &o_merge_sd_split) +{ + // + // set the BoolPlane values using the mvd content + // + + BoolPlane * f_simple_plane = new BoolPlane [n_fcst_files]; + BoolPlane * o_simple_plane = new BoolPlane [n_obs_files]; + BoolPlane * f_merge_plane = new BoolPlane [n_fcst_files]; + BoolPlane * o_merge_plane = new BoolPlane [n_obs_files]; + + for (int j=0; jobjects_from_arrays(do_clusters, true, f_simple_plane[j]); + mvdFcst[j]->objects_from_arrays(do_clusters, false, f_merge_plane[j]); + } + + for (int j=0; jobjects_from_arrays(do_clusters, true, o_simple_plane[j]); + mvdObs[j]->objects_from_arrays(do_clusters, false, o_merge_plane[j]); + } + + // + // combine the objects into super-objects + // + const int nx = f_simple_plane[0].nx(); + const int ny = f_simple_plane[0].ny(); + + BoolPlane f_merge_result, o_merge_result; + f_simple_result.set_size(nx, ny); + o_simple_result.set_size(nx, ny); + f_merge_result.set_size(nx, ny); + o_merge_result.set_size(nx, ny); + + combine_boolplanes("Fcst_Simple", f_simple_plane, n_fcst_files, f_calc, f_simple_result); + combine_boolplanes("Obs_Simple", o_simple_plane, n_obs_files, o_calc, o_simple_result); + combine_boolplanes("Fcst_Merge", f_merge_plane, n_fcst_files, f_calc, f_merge_result); + combine_boolplanes("Obs_Merge", o_merge_plane, n_obs_files, o_calc, o_merge_result); + + + // create ShapeData objects using something from mvd as a template + // (shape data has 1's or bad) + + f_simple_sd = ShapeData(*(mvdFcst[0]->_simple->_sd)); + for (int x=0; x_simple->_sd)); + for (int x=0; x_simple->_sd)); + for (int x=0; x_simple->_sd)); + for (int x=0; x_Fcst_sd->data); - mask_data("Obs", nx, ny, o_result, mvd._simple->_Obs_sd->data); + mask_data("Fcst", nx, ny, f_result, mvdf._simple->_sd->data); + mask_data("Obs", nx, ny, o_result, mvdo._simple->_sd->data); + // + // build the command for running mode frontend + // StringArray mode_argv; char junk [256]; - // - // build the command for running mode - // mode_argv.clear(); mode_argv.add(mode_path); + mode_argv.add(fcst_filename); + mode_argv.add(obs_filename); mode_argv.add(config_file); mode_argv.add("-v"); snprintf(junk, sizeof(junk), "%d", mlog.verbosity_level()); @@ -651,13 +743,15 @@ void create_singlevar_intensity_objects(int j, const BoolPlane &f_result, mode_argv.add("-outdir"); mode_argv.add(dir); - mlog << Debug(1) << "Running filtered mode \n\n"; + mlog << Debug(1) << "Running mvmode intensity comparisions \n\n"; ModeFrontEnd *frontend = new ModeFrontEnd; - int status = frontend->run_multivar_pass2(mode_argv, mvd, has_union, f_merge, o_merge, j); + int status = frontend->multivar_intensity_comparisons(mode_argv, mvdf, mvdo, has_union_f, + has_union_o, merge_f, merge_o, findex, + oindex); delete frontend; } - + //////////////////////////////////////////////////////////////////////// void process_superobjects(ShapeData &f_result, ShapeData &o_result, @@ -670,8 +764,8 @@ void process_superobjects(ShapeData &f_result, ShapeData &o_result, char junk [256]; // - // build the command for running mode - // + // build the command for running mode frontend + // mode_argv.clear(); mode_argv.add(mode_path); mode_argv.add(config_file); @@ -701,7 +795,7 @@ void mask_data(const string &name, int nx, int ny, const BoolPlane &bp, DataPlan { if (nx != data.nx() || ny != data.ny()) { - mlog << Error << "\n" << program_name << ":" << name + mlog << Error << "\nmask_data() -> " << name << " :dimensions don't match " << nx << " " << ny << " " << data.nx() << " " << data.ny() << "\n\n"; @@ -735,7 +829,7 @@ void mask_data_super(const string &name, int nx, int ny, DataPlane &data) { if (nx != data.nx() || ny != data.ny()) { - mlog << Error << "\n" << program_name << ":" << name + mlog << Error << "\nmask_data_super() -> " << name << " :dimensions don't match " << nx << " " << ny << " " << data.nx() << " " << data.ny() << "\n\n"; @@ -780,7 +874,7 @@ int _mkdir(const char *dir) string s = tmp; if (s != ".") { if (mkdir(tmp, dir_creation_mode) < 0) { - mlog << Error << "\n making " << tmp << "\n"; + mlog << Error << "\n_mkdir() -> Error making " << tmp << "\n"; return -1; } }