From 9f9b4cda7fbc636bd8bf228c6dff4fcc977591d7 Mon Sep 17 00:00:00 2001 From: davidalbo Date: Fri, 16 Jun 2023 13:38:29 -0600 Subject: [PATCH] Feature #1283 mvmode mods (#2569) Co-authored-by: John Halley Gotway Co-authored-by: Dave Albo --- docs/Users_Guide/config_options.rst | 2 +- docs/Users_Guide/mode.rst | 34 +- .../config/MODEConfig_multivar_fake_data | 14 +- ...Config_multivar_fake_data_with_intensities | 269 ++++ internal/test_unit/xml/unit_mode_multivar.xml | 39 +- src/basic/vx_config/config_constants.h | 16 +- src/basic/vx_config/dictionary.cc | 20 + src/basic/vx_config/dictionary.h | 7 + src/basic/vx_util/bool_array.h | 42 + src/basic/vx_util/data_plane.cc | 108 ++ src/basic/vx_util/data_plane.h | 9 +- src/libcode/vx_bool_calc/bool_calc.cc | 61 + src/libcode/vx_bool_calc/bool_calc.h | 5 +- src/libcode/vx_data2d_nccf/var_info_nccf.h | 5 +- src/libcode/vx_nc_util/write_netcdf.cc | 1 - src/libcode/vx_shapedata/engine.cc | 564 +++++++- src/libcode/vx_shapedata/engine.h | 39 +- src/libcode/vx_shapedata/mode_conf_info.cc | 178 ++- src/libcode/vx_shapedata/mode_conf_info.h | 22 + src/libcode/vx_shapedata/mode_field_info.cc | 44 +- src/libcode/vx_shapedata/mode_field_info.h | 1 + src/libcode/vx_shapedata/shapedata.cc | 26 + src/libcode/vx_shapedata/shapedata.h | 9 + src/tools/core/mode/Makefile.am | 3 +- src/tools/core/mode/Makefile.in | 55 +- src/tools/core/mode/cluster_page.cc | 360 ++--- src/tools/core/mode/combine_boolplanes.cc | 73 +- src/tools/core/mode/combine_boolplanes.h | 15 +- src/tools/core/mode/fcst_enlarge_page.cc | 44 +- src/tools/core/mode/mode.cc | 85 +- src/tools/core/mode/mode_exec.cc | 1022 ++++++++++---- src/tools/core/mode/mode_exec.h | 126 +- src/tools/core/mode/mode_frontend.cc | 552 ++++++-- src/tools/core/mode/mode_frontend.h | 83 ++ src/tools/core/mode/mode_multivar.cc | 329 ----- src/tools/core/mode/mode_ps_file.cc | 926 ++++++------- src/tools/core/mode/mode_ps_file.h | 166 +-- src/tools/core/mode/mode_singlevar.cc | 329 ----- src/tools/core/mode/mode_usage.cc | 122 +- src/tools/core/mode/multivar_data.cc | 422 ++++++ src/tools/core/mode/multivar_data.h | 130 ++ src/tools/core/mode/multivar_frontend.cc | 795 +++++++---- src/tools/core/mode/objects_from_netcdf.cc | 111 +- src/tools/core/mode/objects_from_netcdf.h | 10 +- src/tools/core/mode/obs_enlarge_page.cc | 44 +- src/tools/core/mode/overlap_page.cc | 56 +- src/tools/core/mode/page_1.cc | 1182 ++++++++--------- src/tools/core/mode/plot_engine.cc | 58 +- 48 files changed, 5537 insertions(+), 3076 deletions(-) create mode 100644 internal/test_unit/config/MODEConfig_multivar_fake_data_with_intensities create mode 100644 src/basic/vx_util/bool_array.h create mode 100644 src/tools/core/mode/mode_frontend.h delete mode 100644 src/tools/core/mode/mode_multivar.cc delete mode 100644 src/tools/core/mode/mode_singlevar.cc create mode 100644 src/tools/core/mode/multivar_data.cc create mode 100644 src/tools/core/mode/multivar_data.h diff --git a/docs/Users_Guide/config_options.rst b/docs/Users_Guide/config_options.rst index d60967cbd3..aace75f995 100644 --- a/docs/Users_Guide/config_options.rst +++ b/docs/Users_Guide/config_options.rst @@ -275,6 +275,7 @@ and, in some cases, elevation for all stations based on stationId. This set of stations comes from 2 online sources: the `active stations website `_ and the `complete stations website `_. + As these lists can change as a function of time, a script can be run to pull down the contents of both websites and merge any changes with the existing stations file content, creating an updated stations file locally. @@ -301,7 +302,6 @@ can be deleted once the final output file is created. MET_BASE ^^^^^^^^ - The MET_BASE variable is defined in the code at compilation time as the path to the MET shared data. These are things like the default configuration files, common polygons and color scales. MET_BASE may be used in the MET configuration diff --git a/docs/Users_Guide/mode.rst b/docs/Users_Guide/mode.rst index 2e3b93a08f..dc72107b8b 100644 --- a/docs/Users_Guide/mode.rst +++ b/docs/Users_Guide/mode.rst @@ -110,9 +110,13 @@ Multi-Variate MODE Traditionally, MODE defines objects by smoothing and thresholding data from a single input field. MET version 10.1.0 extends MODE by adding the option to define objects using multiple input fields. -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 a *super* object for both the forecast and observation data. +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** 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** 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. + +If all **multivar_intensity** 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_logic** configuration entry, described in :numref:`MODE-configuration-file`, defines the boolean logic for combining objects from multiple fields into a *super* object. If this configuration option is set, there must be an equal or greater number of fields defined in an array of dictionaries for it define a *super* object of more than one field. Note that the multi-variate MODE forecast and observation input fields and combination logic do not need to match. The resulting forecast and observation *super* objects are written to NetCDF output files. Users can then configure and run traditional MODE to compare the forecast super object to the observed super object. Practical information ===================== @@ -241,6 +245,32 @@ The **multivar_logic** entry is parsed separately from the **fcst** and **obs** _____________________ +.. code-block:: none + + multivar_intensity = [FALSE, TRUE, TRUE]; + +The **multivar_intensity** 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** 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** is FALSE, the input is skipped over. If all the multivar_intensity values are FALSE, traditional mode output is created for the super objects, but with no intensity information. + + +_____________________ + +.. code-block:: none + + multivar_name = "Precip"; + +The **multivar_name** entry appears only in the **MODEMultivarConfig_default** file. This option is used only when the multivar option is enabled, and only when all **multivar_intensity** flag values are FALSE. It can be thought of as an identifier for the multivariate super object. It shows up in output files names and content. If not set the default value is "Super". It can be set separately for forecasts and observations, or as a common value for both. + + +_____________________ + +.. code-block:: none + + multivar_level = "LO"; + +The **multivar_level** entry appears only in the **MODEMultivarConfig_default** file. This option is used only when the multivar option is enabled, and only when all **multivar_intensity** flag values are FALSE. It is the identifier for the multivariate super object as regards level. It shows up in output files names and content. If not set the default value is "NA". It can be set separately for forecasts and observations, or as a common value for both. + +_____________________ + .. code-block:: none fcst = { diff --git a/internal/test_unit/config/MODEConfig_multivar_fake_data b/internal/test_unit/config/MODEConfig_multivar_fake_data index 45689f0551..c8941f8b92 100644 --- a/internal/test_unit/config/MODEConfig_multivar_fake_data +++ b/internal/test_unit/config/MODEConfig_multivar_fake_data @@ -53,6 +53,11 @@ quilt = FALSE; // multivar_logic = "#1 && #2 && #3"; +// +// MODE Multivar intensity logic +// +multivar_intensity_flag = [FALSE, FALSE, FALSE]; + // // Forecast and observation fields to be verified // @@ -63,16 +68,19 @@ fcst = { { name = "ALPHA"; level = "(*,*)"; + merge_flag = NONE; }, { name = "BETA"; level = "(*,*)"; + merge_flag = NONE; }, { name = "GAMMA"; level = "(*,*)"; + merge_flag = NONE; } ]; @@ -84,6 +92,8 @@ fcst = { filter_attr_thresh = []; merge_thresh = >=3.5; merge_flag = NONE; + multivar_name = "Super"; + multivar_level = "LO"; } obs = fcst; @@ -97,12 +107,12 @@ mask_missing_flag = NONE; // // Match objects between the forecast and observation fields // -match_flag = NONE; +match_flag = MERGE_BOTH; // // Maximum centroid distance for objects to be compared // -max_centroid_dist = 800.0/grid_res; +max_centroid_dist = 800.0; //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/MODEConfig_multivar_fake_data_with_intensities b/internal/test_unit/config/MODEConfig_multivar_fake_data_with_intensities new file mode 100644 index 0000000000..af6d1720a5 --- /dev/null +++ b/internal/test_unit/config/MODEConfig_multivar_fake_data_with_intensities @@ -0,0 +1,269 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// MODE configuration file. +// +// For additional information, please see the MET User's Guide. +// +//////////////////////////////////////////////////////////////////////////////// + +// +// Output model name to be written +// +model = "WRF"; + +// +// Output description to be written +// +desc = "NA"; + +// +// Output observation type to be written +// +obtype = "PRECIP"; + +//////////////////////////////////////////////////////////////////////////////// + +// +// Verification grid +// +regrid = { + to_grid = NONE; + method = NEAREST; + width = 1; + vld_thresh = 0.5; + shape = SQUARE; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Approximate grid resolution (km) +// +grid_res = 20; + +//////////////////////////////////////////////////////////////////////////////// + +// +// Run all permutations of radius and threshold +// +quilt = FALSE; + +// +// MODE Multivar boolean combination logic +// +multivar_logic = "#1 && #2 && #3"; + +// +// MODE Multivar intensity logic +// +multivar_intensity_flag = [TRUE, TRUE, TRUE]; + +// +// Forecast and observation fields to be verified +// +fcst = { + + field = [ + + { + name = "ALPHA"; + level = "(*,*)"; + merge_flag = NONE; + }, + + { + name = "BETA"; + level = "(*,*)"; + merge_flag = NONE; + }, + + { + name = "GAMMA"; + level = "(*,*)"; + merge_flag = NONE; + } + + ]; + + conv_radius = 2; // in grid squares + conv_thresh = >=5.0; + vld_thresh = 0.5; + filter_attr_name = []; + filter_attr_thresh = []; + merge_thresh = >=3.5; + merge_flag = NONE; + multivar_name = "Super"; + multivar_level = "LO"; +} +obs = fcst; + +//////////////////////////////////////////////////////////////////////////////// + +// +// Handle missing data +// +mask_missing_flag = NONE; + +// +// Match objects between the forecast and observation fields +// +match_flag = MERGE_BOTH; + +// +// Maximum centroid distance for objects to be compared +// +max_centroid_dist = 800.0; + +//////////////////////////////////////////////////////////////////////////////// + +// +// Verification masking regions +// +mask = { + grid = ""; + grid_flag = NONE; // Apply to NONE, FCST, OBS, or BOTH + poly = ""; + poly_flag = NONE; // Apply to NONE, FCST, OBS, or BOTH +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Fuzzy engine weights +// +weight = { + centroid_dist = 2.0; + boundary_dist = 4.0; + convex_hull_dist = 0.0; + angle_diff = 1.0; + aspect_diff = 0.0; + area_ratio = 1.0; + int_area_ratio = 2.0; + curvature_ratio = 0.0; + complexity_ratio = 0.0; + inten_perc_ratio = 0.0; + inten_perc_value = 50; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Fuzzy engine interest functions +// +interest_function = { + + centroid_dist = ( + ( 0.0, 1.0 ) + ( 60.0/grid_res, 1.0 ) + ( 600.0/grid_res, 0.0 ) + ); + + boundary_dist = ( + ( 0.0, 1.0 ) + ( 400.0/grid_res, 0.0 ) + ); + + convex_hull_dist = ( + ( 0.0, 1.0 ) + ( 400.0/grid_res, 0.0 ) + ); + + angle_diff = ( + ( 0.0, 1.0 ) + ( 30.0, 1.0 ) + ( 90.0, 0.0 ) + ); + + aspect_diff = ( + ( 0.00, 1.0 ) + ( 0.10, 1.0 ) + ( 0.75, 0.0 ) + ); + + corner = 0.8; + ratio_if = ( + ( 0.0, 0.0 ) + ( corner, 1.0 ) + ( 1.0, 1.0 ) + ); + + area_ratio = ratio_if; + + int_area_ratio = ( + ( 0.00, 0.00 ) + ( 0.10, 0.50 ) + ( 0.25, 1.00 ) + ( 1.00, 1.00 ) + ); + + curvature_ratio = ratio_if; + + complexity_ratio = ratio_if; + + inten_perc_ratio = ratio_if; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Total interest threshold for determining matches +// +total_interest_thresh = 0.7; + +// +// Interest threshold for printing output pair information +// +print_interest_thresh = 0.0; + +//////////////////////////////////////////////////////////////////////////////// + +// +// Plotting information +// +met_data_dir = "MET_BASE"; + +fcst_raw_plot = { + color_table = "MET_BASE/colortables/met_default.ctable"; + plot_min = 0.0; + plot_max = 25.4; +} + +obs_raw_plot = { + color_table = "MET_BASE/colortables/met_default.ctable"; + plot_min = 0.0; + plot_max = 25.4; +} + +object_plot = { + color_table = "MET_BASE/colortables/mode_obj.ctable"; +} + +// +// Boolean for plotting on the region of valid data within the domain +// +plot_valid_flag = FALSE; + +// +// Plot polyline edges using great circle arcs instead of straight lines +// +plot_gcarc_flag = FALSE; + +//////////////////////////////////////////////////////////////////////////////// + +// +// NetCDF matched pairs, PostScript, and contingency table output files +// +ps_plot_flag = TRUE; +nc_pairs_flag = TRUE; +ct_stats_flag = TRUE; + +//////////////////////////////////////////////////////////////////////////////// + +shift_right = 0; // grid squares + +//////////////////////////////////////////////////////////////////////////////// + +output_prefix = ""; +version = "V11.1.0"; + +//////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/xml/unit_mode_multivar.xml b/internal/test_unit/xml/unit_mode_multivar.xml index ebfcf179cb..4aad5dc7d6 100644 --- a/internal/test_unit/xml/unit_mode_multivar.xml +++ b/internal/test_unit/xml/unit_mode_multivar.xml @@ -34,8 +34,43 @@ -v 2 - &OUTPUT_DIR;/mode_multivar/f_super.nc - &OUTPUT_DIR;/mode_multivar/o_super.nc + &OUTPUT_DIR;/mode_multivar/mode_Fcst_Super_LO_Obs_Super_LO_300000L_20120410_180000V_060000A_obj.nc + &OUTPUT_DIR;/mode_multivar/mode_Fcst_Super_LO_Obs_Super_LO_300000L_20120410_180000V_060000A_obj.txt + &OUTPUT_DIR;/mode_multivar/mode_Fcst_Super_LO_Obs_Super_LO_300000L_20120410_180000V_060000A_cts.txt + &OUTPUT_DIR;/mode_multivar/mode_Fcst_Super_LO_Obs_Super_LO_300000L_20120410_180000V_060000A.ps + + + + + echo "&DATA_DIR_MODEL;/mode_multivar/alpha_fcst.nc \ + &DATA_DIR_MODEL;/mode_multivar/beta_fcst.nc \ + &DATA_DIR_MODEL;/mode_multivar/gamma_fcst.nc" \ + > &OUTPUT_DIR;/mode_multivar/input_fcst_file_list; \ + echo "&DATA_DIR_MODEL;/mode_multivar/alpha_obs.nc \ + &DATA_DIR_MODEL;/mode_multivar/beta_obs.nc \ + &DATA_DIR_MODEL;/mode_multivar/gamma_obs.nc" \ + > &OUTPUT_DIR;/mode_multivar/input_obs_file_list; \ + &MET_BIN;/mode + \ + &OUTPUT_DIR;/mode_multivar/input_fcst_file_list \ + &OUTPUT_DIR;/mode_multivar/input_obs_file_list \ + &CONFIG_DIR;/MODEConfig_multivar_fake_data_with_intensities \ + -outdir &OUTPUT_DIR;/mode_multivar \ + -v 2 + + + &OUTPUT_DIR;/mode_multivar/mode_Fcst_ALPHA_all_all_Obs_ALPHA_all_all_300000L_20120410_180000V_060000A_cts.txt + &OUTPUT_DIR;/mode_multivar/mode_Fcst_ALPHA_all_all_Obs_ALPHA_all_all_300000L_20120410_180000V_060000A_obj.nc + &OUTPUT_DIR;/mode_multivar/mode_Fcst_ALPHA_all_all_Obs_ALPHA_all_all_300000L_20120410_180000V_060000A_obj.txt + &OUTPUT_DIR;/mode_multivar/mode_Fcst_ALPHA_all_all_Obs_ALPHA_all_all_300000L_20120410_180000V_060000A.ps + &OUTPUT_DIR;/mode_multivar/mode_Fcst_BETA_all_all_Obs_BETA_all_all_300000L_20120410_180000V_060000A_cts.txt + &OUTPUT_DIR;/mode_multivar/mode_Fcst_BETA_all_all_Obs_BETA_all_all_300000L_20120410_180000V_060000A_obj.nc + &OUTPUT_DIR;/mode_multivar/mode_Fcst_BETA_all_all_Obs_BETA_all_all_300000L_20120410_180000V_060000A_obj.txt + &OUTPUT_DIR;/mode_multivar/mode_Fcst_BETA_all_all_Obs_BETA_all_all_300000L_20120410_180000V_060000A.ps + &OUTPUT_DIR;/mode_multivar/mode_Fcst_GAMMA_all_all_Obs_GAMMA_all_all_300000L_20120410_180000V_060000A_cts.txt + &OUTPUT_DIR;/mode_multivar/mode_Fcst_GAMMA_all_all_Obs_GAMMA_all_all_300000L_20120410_180000V_060000A_obj.nc + &OUTPUT_DIR;/mode_multivar/mode_Fcst_GAMMA_all_all_Obs_GAMMA_all_all_300000L_20120410_180000V_060000A_obj.txt + &OUTPUT_DIR;/mode_multivar/mode_Fcst_GAMMA_all_all_Obs_GAMMA_all_all_300000L_20120410_180000V_060000A.ps diff --git a/src/basic/vx_config/config_constants.h b/src/basic/vx_config/config_constants.h index fed261e595..34da078eb1 100644 --- a/src/basic/vx_config/config_constants.h +++ b/src/basic/vx_config/config_constants.h @@ -17,6 +17,7 @@ #include "gsl_randist.h" #include "config_gaussian.h" #include "config_funcs.h" +#include "interp_mthd.h" //////////////////////////////////////////////////////////////////////// @@ -701,12 +702,6 @@ static const char conf_key_is_wind_speed[] = "is_wind_speed"; static const char conf_key_is_wind_direction[] = "is_wind_direction"; static const char conf_key_is_prob[] = "is_prob"; -// -// for use with mode multivar -// - -static const char conf_key_multivar_logic [] = "multivar_logic"; - // // Climatology parameter key names // @@ -901,6 +896,15 @@ static const char conf_key_plot_gcarc_flag[] = "plot_gcarc_flag"; static const char conf_key_ct_stats_flag[] = "ct_stats_flag"; static const char conf_key_shift_right[] = "shift_right"; +// +// Multivar MODE specific parameter key names +// + +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"; + // // MTD specific parameter key names // diff --git a/src/basic/vx_config/dictionary.cc b/src/basic/vx_config/dictionary.cc index 50bedb809b..b6181c843f 100644 --- a/src/basic/vx_config/dictionary.cc +++ b/src/basic/vx_config/dictionary.cc @@ -1517,6 +1517,26 @@ return Entry->b_value(); //////////////////////////////////////////////////////////////////////// +BoolArray Dictionary::lookup_bool_array(const char * name, + bool error_out, + bool print_warning, + bool search_parent) { + +BoolArray array; +NumArray num_array = lookup_num_array(name, error_out, print_warning); + +for (int i=0; i + +#include "num_array.h" + +#include "crc_array.h" + + +//////////////////////////////////////////////////////////////////////// + + +typedef CRC_Array BoolArray; + + +//////////////////////////////////////////////////////////////////////// + + +#endif /* __BOOL_ARRAY_H__ */ + + +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/basic/vx_util/data_plane.cc b/src/basic/vx_util/data_plane.cc index 384f2b73f1..2dd2dcaf38 100644 --- a/src/basic/vx_util/data_plane.cc +++ b/src/basic/vx_util/data_plane.cc @@ -22,6 +22,8 @@ using namespace std; +#include + #include "data_plane.h" #include "vx_log.h" @@ -113,6 +115,26 @@ DataPlane & DataPlane::operator/=(const double v) { return(*this); } +bool DataPlane::operator==(const DataPlane &d) const { + + const char *method_name = "DataPlane::operator==(const DataPlane &) -> "; + + // don't check times, only data + + // Check for matching dimensions + if(Nx != d.Nx || Ny != d.Ny) { + return false; + } + + for(int i=0; i values; + vector count; + int total_count = 0; + + for (int x=0; x::iterator vi; + vi = find(values.begin(), values.end(), v); + if (vi == values.end()) { + values.push_back(v); + count.push_back(1); + } else { + int ii = vi - values.begin(); + count[ii] = count[ii] + 1; + } + } + } + } + if (show_all_values) { + for (size_t i=0; i " + << "the data dimensions do not match: (" + << Nx << ", " << Ny << ") != (" + << nx << ", " << ny << ")!\n\n"; + exit(1); + } + for (int x=0; x #include #include "two_to_one.h" @@ -58,13 +59,16 @@ class DataPlane { DataPlane & operator=(const DataPlane &); DataPlane & operator+=(const DataPlane &); DataPlane & operator/=(const double); - + bool operator==(const DataPlane &) const; void clear(); void erase(); void dump(std::ostream &, int = 0) const; + void debug_examine(bool show_all_value=false) const; + std::string sdebug_examine() const; + // // Set functions // @@ -81,6 +85,8 @@ class DataPlane { void set_lead(int); void set_accum(int); + void set_all(float *data, int nx, int ny); + // // Get functions // @@ -115,6 +121,7 @@ class DataPlane { void standard_anomaly(const DataPlane &, const DataPlane &); void replace_bad_data(const double value); + void set_all_to_bad_data(); int two_to_one(int x, int y, bool to_north=true) const; void one_to_two(int n, int &x, int &y) const; diff --git a/src/libcode/vx_bool_calc/bool_calc.cc b/src/libcode/vx_bool_calc/bool_calc.cc index 4f7f62330f..21ccd83921 100644 --- a/src/libcode/vx_bool_calc/bool_calc.cc +++ b/src/libcode/vx_bool_calc/bool_calc.cc @@ -131,6 +131,47 @@ return; //////////////////////////////////////////////////////////////////////// +bool BoolCalc::check_args(int expectedNargs) const + +{ + +Program & P = *program; +Token tok; +vector args; +bool status = true; + +for (size_t j=0; j " + << "expect " << expectedNargs << " args, got " << args.size() << "\n\n"; + status = false; +} +for (size_t j=0; j= expectedNargs) { + mlog << Error << "\nBoolCalc::check_args() -> " + << "arg out of range " << args[j] << " range is 1 to " << expectedNargs << "\n\n"; + status = false; + } +} +if (!status) { + dump_program(cerr); +} + +return status; + +} + +//////////////////////////////////////////////////////////////////////// + + bool BoolCalc::run(const vector arg) { @@ -214,5 +255,25 @@ return ( result ); //////////////////////////////////////////////////////////////////////// +bool BoolCalc::has_union() const + +{ + +Program & P = *program; + +for (int j=0; j<((int) P.size()); ++j) { + + Token tok = P[j]; + if (tok.type == tok_union) { + return true; + } +} + +return false; + +} + + +//////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_bool_calc/bool_calc.h b/src/libcode/vx_bool_calc/bool_calc.h index 7e65b81153..a8604a6eed 100644 --- a/src/libcode/vx_bool_calc/bool_calc.h +++ b/src/libcode/vx_bool_calc/bool_calc.h @@ -41,7 +41,8 @@ class BoolCalc { void dump_program(std::ostream &) const; - + // check that all the args from 1 to expectedNargs are found + bool check_args(int expectedNargs) const; int Max_depth; // maximum stack depth needed to run the program @@ -53,6 +54,8 @@ class BoolCalc { bool run(const vector); + // return true if one of the operations is a union (or) + bool has_union() const; }; diff --git a/src/libcode/vx_data2d_nccf/var_info_nccf.h b/src/libcode/vx_data2d_nccf/var_info_nccf.h index 021009f0f4..2463bcbde2 100644 --- a/src/libcode/vx_data2d_nccf/var_info_nccf.h +++ b/src/libcode/vx_data2d_nccf/var_info_nccf.h @@ -20,10 +20,7 @@ #include "long_array.h" #include "math_constants.h" #include "nc_constants.h" - -/////////////////////////////////////////////////////////////////////////////// - -typedef CRC_Array BoolArray; +#include "bool_array.h" /////////////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_nc_util/write_netcdf.cc b/src/libcode/vx_nc_util/write_netcdf.cc index d492979138..a3614167cb 100644 --- a/src/libcode/vx_nc_util/write_netcdf.cc +++ b/src/libcode/vx_nc_util/write_netcdf.cc @@ -90,7 +90,6 @@ return; void write_netcdf_latlon(NcFile *f_out, NcDim *lat_dim, NcDim *lon_dim, const Grid &grid) { - // Write 1-dimensional arrays for lat/lon grids if(grid.info().ll != 0) { write_netcdf_latlon_1d(f_out, lat_dim, lon_dim, grid); diff --git a/src/libcode/vx_shapedata/engine.cc b/src/libcode/vx_shapedata/engine.cc index 1c70eaa7e9..d16ba7de6c 100644 --- a/src/libcode/vx_shapedata/engine.cc +++ b/src/libcode/vx_shapedata/engine.cc @@ -157,6 +157,9 @@ void ModeFuzzyEngine::init_from_scratch() { need_obs_merge = true; need_obs_clus_split = true; + is_multivar_super = false; + is_multivar_intensity= false; + need_match = true; fcst_raw = new ShapeData; @@ -287,6 +290,56 @@ void ModeFuzzyEngine::set_no_conv(const ShapeData &fcst_wd, const ShapeData &obs } +/////////////////////////////////////////////////////////////////////// + +void ModeFuzzyEngine::set_only_split(const ShapeData &fcst_wd, const ShapeData &obs_wd) + +{ + + ConcatString path; + + clear_features(); + clear_colors(); + ctable.clear(); + + collection.clear(); + + set_fcst_only_split (fcst_wd); + set_obs_only_split ( obs_wd); + + path = replace_path(conf_info.object_pi.color_table.c_str()); + + ctable.read(path.c_str()); + + return; + +} + +/////////////////////////////////////////////////////////////////////// + +void ModeFuzzyEngine::set_super(const ShapeData &fcst_wd, const ShapeData &obs_wd) + +{ + + ConcatString path; + + clear_features(); + clear_colors(); + ctable.clear(); + + collection.clear(); + + set_fcst_super (fcst_wd); + set_obs_super ( obs_wd); + + path = replace_path(conf_info.object_pi.color_table.c_str()); + + ctable.read(path.c_str()); + + return; + +} + /////////////////////////////////////////////////////////////////////// @@ -383,6 +436,130 @@ void ModeFuzzyEngine::set_obs_no_conv(const ShapeData &obs_wd) { } + +/////////////////////////////////////////////////////////////////////// + + +void ModeFuzzyEngine::set_fcst_only_split(const ShapeData &fcst_wd) + +{ + *fcst_raw = fcst_wd; // real valued + *fcst_conv = *fcst_raw; // real valued + *fcst_mask = *fcst_conv; // 1s and 0s + fcst_mask->set_to_1_or_0(); + *fcst_thresh = *fcst_raw; //1s and 0s + fcst_thresh->set_to_1_or_0(); + + need_fcst_conv = false; + need_fcst_thresh = false; + need_fcst_filter = false; + need_fcst_split = true; + need_fcst_merge = true; + need_fcst_clus_split = true; + need_match = true; + + // do_fcst_convolution(); + //do_fcst_thresholding(); + //do_fcst_filtering(); + do_fcst_splitting(); + return; +} + + +/////////////////////////////////////////////////////////////////////// + + +void ModeFuzzyEngine::set_obs_only_split(const ShapeData &obs_wd) { + + *obs_raw = obs_wd; // real valued + *obs_conv = *obs_raw; // real valued + *obs_mask = *obs_conv; // 1s and 0s + obs_mask->set_to_1_or_0(); + *obs_thresh = *obs_raw; // 1s and 0s + obs_thresh->set_to_1_or_0(); + + need_obs_conv = false; + need_obs_thresh = false; + need_obs_filter = false; + need_obs_split = true; + need_obs_merge = true; + need_obs_clus_split = true; + need_match = true; + + // do_obs_convolution(); + // do_obs_thresholding(); + // do_obs_filtering(); + do_obs_splitting(); + + return; +} + +/////////////////////////////////////////////////////////////////////// + + +void ModeFuzzyEngine::set_fcst_super(const ShapeData &fcst_wd) + +{ + *fcst_raw = fcst_wd; // real valued + *fcst_conv = *fcst_raw; // real valued + *fcst_mask = *fcst_conv; // 1s and 0s + fcst_mask->set_to_1_or_0(); + *fcst_thresh = *fcst_raw; //1s and 0s + fcst_thresh->set_to_1_or_0(); + + // set fcst_raw and fcst_conv to missing everywhere + fcst_raw->data.set_all_to_bad_data(); + fcst_conv->data.set_all_to_bad_data(); + + need_fcst_conv = false; + need_fcst_thresh = false; + need_fcst_filter = false; + need_fcst_split = true; + need_fcst_merge = true; + need_fcst_clus_split = true; + need_match = true; + + // do_fcst_convolution(); + //do_fcst_thresholding(); + //do_fcst_filtering(); + do_fcst_splitting(); + return; +} + + +/////////////////////////////////////////////////////////////////////// + + +void ModeFuzzyEngine::set_obs_super(const ShapeData &obs_wd) { + + *obs_raw = obs_wd; // real valued + *obs_conv = *obs_raw; // real valued + *obs_mask = *obs_conv; // 1s and 0s + obs_mask->set_to_1_or_0(); + *obs_thresh = *obs_raw; // 1s and 0s + obs_thresh->set_to_1_or_0(); + + // set obs_raw and obs_conv to missing everywhere + obs_raw->data.set_all_to_bad_data(); + obs_conv->data.set_all_to_bad_data(); + + need_obs_conv = false; + need_obs_thresh = false; + need_obs_filter = false; + need_obs_split = true; + need_obs_merge = true; + need_obs_clus_split = true; + need_match = true; + + // do_obs_convolution(); + // do_obs_thresholding(); + // do_obs_filtering(); + do_obs_splitting(); + + return; +} + + /////////////////////////////////////////////////////////////////////// @@ -413,8 +590,14 @@ void ModeFuzzyEngine::do_fcst_convolution() { // // Apply a circular convolution to the raw field // + + mlog << Debug(4) << " Before fcst convolution: " << fcst_conv->sdebug_examine() << "\n"; + + if(r > 0) fcst_conv->conv_filter_circ(2*r + 1, conf_info.Fcst->vld_thresh); + mlog << Debug(4) << " After fcst convolution: " << fcst_conv->sdebug_examine() << "\n"; + need_fcst_conv = false; need_fcst_thresh = true; need_fcst_filter = true; @@ -442,11 +625,15 @@ void ModeFuzzyEngine::do_obs_convolution() { mlog << Debug(3) << "Applying circular convolution of radius " << r << " to the observation field.\n"; + mlog << Debug(4) << " Before obs convolution: " << obs_conv->sdebug_examine() << "\n"; + // // Apply a circular convolution to the raw field // if(r > 0) obs_conv->conv_filter_circ(2*r + 1, conf_info.Obs->vld_thresh); + mlog << Debug(4) << " After obs convolution: " << obs_conv->sdebug_examine() << "\n"; + need_obs_conv = false; need_obs_thresh = true; need_obs_filter = true; @@ -470,11 +657,13 @@ void ModeFuzzyEngine::do_fcst_thresholding() { *fcst_thresh = *fcst_raw; fcst_thresh->threshold(conf_info.Fcst->conv_thresh); + mlog << Debug(4) << " After thresholding raw fcst field: " << fcst_thresh->sdebug_examine() << "\n"; // // Threshold the convolved field // fcst_mask->threshold(conf_info.Fcst->conv_thresh); + mlog << Debug(4) << " After thresholding convolved fcst field: " << fcst_mask->sdebug_examine() << "\n"; mlog << Debug(3) << "Applying convolution threshold " << conf_info.Fcst->conv_thresh.get_str() @@ -503,11 +692,13 @@ void ModeFuzzyEngine::do_obs_thresholding() { *obs_thresh = *obs_raw; obs_thresh->threshold(conf_info.Obs->conv_thresh); + mlog << Debug(4) << " After thresholding raw obs field: " << obs_thresh->sdebug_examine() << "\n"; // // Threshold the convolved field // obs_mask->threshold(conf_info.Obs->conv_thresh); + mlog << Debug(4) << " After thresholding convolved obs field: " << obs_mask->sdebug_examine() << "\n"; mlog << Debug(3) << "Applying convolution threshold " << conf_info.Obs->conv_thresh.get_str() @@ -542,6 +733,7 @@ void ModeFuzzyEngine::do_fcst_filtering() { fcst_raw, conf_info.Fcst->conv_thresh, grid, conf_info.Fcst->var_info->is_precipitation()); + mlog << Debug(4) << " After attribute filtering of fcst field: " << fcst_mask->sdebug_examine() << "\n"; mlog << Debug(3) << "Applying object attribute filtering" << " resulted in " << fcst_mask->n_objects() << " simple forecast objects.\n"; @@ -577,6 +769,7 @@ void ModeFuzzyEngine::do_obs_filtering() { obs_raw, conf_info.Obs->conv_thresh, grid, conf_info.Obs->var_info->is_precipitation()); + mlog << Debug(4) << " After attribute filtering of obs field: " << obs_mask->sdebug_examine() << "\n"; mlog << Debug(3) << "Applying object attribute filtering" << " resulted in " << obs_mask->n_objects() << " simple observation objects.\n"; @@ -604,6 +797,7 @@ void ModeFuzzyEngine::do_fcst_splitting() { if(!need_fcst_split) return; *fcst_split = split(*fcst_mask, n_fcst); + mlog << Debug(4) << " After splitting of fcst field: " << fcst_split->sdebug_examine() << "\n"; need_fcst_split = false; need_fcst_merge = true; @@ -622,6 +816,7 @@ void ModeFuzzyEngine::do_obs_splitting() { if(!need_obs_split) return; *obs_split = split(*obs_mask, n_obs); + mlog << Debug(4) << " After splitting of obs field: " << obs_split->sdebug_examine() << "\n"; need_obs_split = false; need_obs_merge = true; @@ -707,6 +902,79 @@ void ModeFuzzyEngine::do_obs_merging(const char *default_config, /////////////////////////////////////////////////////////////////////// +void ModeFuzzyEngine::do_fcst_merging(const char *default_config, + const char *merge_config, + const ShapeData &merge_data) +{ + + if(need_fcst_thresh) do_fcst_thresholding(); + if(!need_fcst_merge) return; + + if (fcst_thresh->data.nx() != merge_data.data.nx() || + fcst_thresh->data.ny() != merge_data.data.ny()) { + mlog << Error << "\nModeFuzzyEngine::do_fcst_merging() -> " + << "inconsistent array dims\n\n"; + exit(1); + } + + if(conf_info.Fcst->merge_flag == MergeType_Both || + conf_info.Fcst->merge_flag == MergeType_Thresh) + do_fcst_merge_thresh(merge_data); + + if(conf_info.Fcst->merge_flag == MergeType_Both || + conf_info.Fcst->merge_flag == MergeType_Engine) + do_fcst_merge_engine(default_config, merge_config); + + // + // Done + // + + need_fcst_merge = false; + need_fcst_clus_split = true; + need_match = true; + + return; +} + +/////////////////////////////////////////////////////////////////////// + +void ModeFuzzyEngine::do_obs_merging(const char *default_config, + const char *merge_config, + const ShapeData &merge_data) +{ + if(need_obs_thresh) do_obs_thresholding(); + + if(!need_obs_merge) return; + + if (obs_thresh->data.nx() != merge_data.data.nx() || + obs_thresh->data.ny() != merge_data.data.ny()) { + mlog << Error << "\nModeFuzzyEngine::do_obs_merging() -> " + << "inconsistent array dims\n\n"; + exit(1); + } + + + if(conf_info.Obs->merge_flag == MergeType_Both || + conf_info.Obs->merge_flag == MergeType_Thresh) + do_obs_merge_thresh(merge_data); + + if(conf_info.Obs->merge_flag == MergeType_Both || + conf_info.Obs->merge_flag == MergeType_Engine) + do_obs_merge_engine(default_config, merge_config); + + // + // Done + // + + need_obs_merge = false; + need_obs_clus_split = true; + need_match = true; + + return; +} + +/////////////////////////////////////////////////////////////////////// + void ModeFuzzyEngine::do_matching() { if(!need_match) return; @@ -1260,6 +1528,244 @@ void ModeFuzzyEngine::do_obs_merge_thresh() { return; } + +void ModeFuzzyEngine::do_fcst_merge_thresh(const ShapeData &merge_data) { + int j, k, x, y; + int n_fcst_merge, intersection; + int count, first_k; + //ShapeData fcst_merge_mask; + ShapeData fcst_merge_split; + ShapeData * fcst_shape = (ShapeData *) 0; + ShapeData * fcst_merge_shape = (ShapeData *) 0; + + do_fcst_splitting(); + + // + // Define the forecast merge field by applying the specified threshold + // to the convolved field + // + fcst_merge_split = merge_data; + n_fcst_merge = fcst_merge_split.n_objects(); + + // fcst_merge_mask = *fcst_conv; + + // // + // // Threshold the forecast merge field + // // + // fcst_merge_mask.threshold(conf_info.Fcst->merge_thresh); + + // // + // // Split up the forecast merge field + // // + // fcst_merge_split = split(fcst_merge_mask, n_fcst_merge); + + // + // Allocate space for all of the simple forecast shapes and + // forecast merge shapes + // + fcst_shape = new ShapeData [n_fcst]; + fcst_merge_shape = new ShapeData [n_fcst_merge]; + + if(!fcst_shape || !fcst_merge_shape) { + + mlog << Error << "\nModeFuzzyEngine::do_fcst_merge_thresh() -> " + << "memory allocation error\n\n"; + exit(1); + } + + // + // Select all of the simple forecast shapes and + // forecast merge shapes + // + for(j=0; j= fcst area + // + + if(intersection >= fcst_shape[k].area()) { + + collection.make_room(); + + // + // Keep track of the first embedded shape. You only want to + // create a composite if there are more than 1 shapes in it. + // + if(count == 0) first_k = k+1; + + else if(count == 1) { + collection.set[collection.n_sets].add_pair(first_k, -1); + collection.set[collection.n_sets].add_pair(k+1, -1); + } + else { + collection.set[collection.n_sets].add_pair(k+1, -1); + } + + count++; + } + } // end for k + + if(count > 0) collection.n_sets++; + } // end for j + + // + // Done + // + + delete [] fcst_shape; fcst_shape = (ShapeData *) 0; + delete [] fcst_merge_shape; fcst_merge_shape = (ShapeData *) 0; + + mlog << Debug(4) << " After merging of fcst field: " << fcst_split->sdebug_examine() << "\n"; + return; +} + +void ModeFuzzyEngine::do_obs_merge_thresh(const ShapeData &merge_data) { + int j, k, x, y; + int n_obs_merge, intersection; + int count, first_k; + //ShapeData obs_merge_mask; + ShapeData obs_merge_split; + ShapeData * obs_shape = (ShapeData *) 0; + ShapeData * obs_merge_shape = (ShapeData *) 0; + + do_obs_splitting(); + + // + // Define the forecast merge field by applying the specified threshold + // to the convolved field + // + // obs_merge_mask = *obs_conv; + + // + // Threshold the forecast merge field + // + // obs_merge_mask.threshold(conf_info.Obs->merge_thresh); + + // + // Split up the forecast merge field + // + obs_merge_split = merge_data; //split(obs_merge_mask, n_obs_merge); + n_obs_merge = obs_merge_split.n_objects(); + + // + // Allocate space for all of the simple observation shapes and + // observation merge shapes + // + obs_shape = new ShapeData [n_obs]; + obs_merge_shape = new ShapeData [n_obs_merge]; + + if(!obs_shape || !obs_merge_shape) { + + mlog << Error << "\nModeFuzzyEngine::do_obs_merge_thresh() -> " + << "memory allocation error\n\n"; + exit(1); + } + + // + // Select all of the simple observation shapes and + // simple merge shapes + // + for(j=0; j= obs area + // + if(intersection >= obs_shape[k].area()) { + + collection.make_room(); + + // + // Keep track of the first embedded shape. You only want to + // create a composite if there are more than 1 shapes in it. + // + if(count == 0) first_k = k+1; + + else if(count == 1) { + collection.set[collection.n_sets].add_pair(-1, first_k); + collection.set[collection.n_sets].add_pair(-1, k+1); + } + else { + collection.set[collection.n_sets].add_pair(-1, k+1); + } + + count++; + } + } // end for k + + if(count > 0) collection.n_sets++; + } // end for j + + // + // Done + // + + delete [] obs_shape; obs_shape = (ShapeData *) 0; + delete [] obs_merge_shape; obs_merge_shape = (ShapeData *) 0; + + mlog << Debug(4) << " After merging of obs field: " << obs_split->sdebug_examine() << "\n"; + return; +} + /////////////////////////////////////////////////////////////////////// // // Perform merging of the forecast field using a fuzzy engine matching @@ -2606,10 +3112,14 @@ double interest_percentile(ModeFuzzyEngine &eng, const double p, const int flag) /////////////////////////////////////////////////////////////////////// -void write_engine_stats(ModeFuzzyEngine & eng, const Grid & grid, AsciiTable & at) +void write_engine_stats(ModeFuzzyEngine & eng, const Grid & grid, AsciiTable & at, + bool isMultivarSuper, bool isMultivarIntensity) { + eng.is_multivar_super = isMultivarSuper; + eng.is_multivar_intensity = isMultivarIntensity; + int i, j, row; // @@ -2832,33 +3342,67 @@ void write_header_columns(ModeFuzzyEngine & eng, const Grid & grid, AsciiTable & eng.conf_info.Obs->conv_thresh.get_str()); // Forecast Variable Name - s = check_hdr_str(conf_key_fcst_var, - eng.conf_info.Fcst->var_info->name_attr()); + if (eng.is_multivar_super) { + s = eng.conf_info.fcst_multivar_name; + } else if (eng.is_multivar_intensity) { + s = eng.conf_info.fcst_multivar_name; + s.add("_"); + s.add(check_hdr_str(conf_key_fcst_var, + eng.conf_info.Fcst->var_info->name_attr())); + } else { + s = check_hdr_str(conf_key_fcst_var, + eng.conf_info.Fcst->var_info->name_attr()); + } at.set_entry(row, c++, s.text()); // Forecast Variable Units - s = check_hdr_str(conf_key_fcst_units, - eng.conf_info.Fcst->var_info->units_attr(), true); + if (eng.is_multivar_super) { + s = "NA"; + } else { + s = check_hdr_str(conf_key_fcst_units, + eng.conf_info.Fcst->var_info->units_attr(), true); + } at.set_entry(row, c++, s.text()); // Forecast Variable Level - s = check_hdr_str(conf_key_fcst_lev, + if (eng.is_multivar_super) { + s = eng.conf_info.fcst_multivar_level; + } else { + s = check_hdr_str(conf_key_fcst_lev, eng.conf_info.Fcst->var_info->level_attr(), true); + } at.set_entry(row, c++, s.text()); // Observation Variable Name - s = check_hdr_str(conf_key_obs_var, + if (eng.is_multivar_super) { + s = eng.conf_info.obs_multivar_name; + } else if (eng.is_multivar_intensity) { + s = eng.conf_info.obs_multivar_name; + s.add("_"); + s.add(check_hdr_str(conf_key_fcst_var, + eng.conf_info.Obs->var_info->name_attr())); + } else { + s = check_hdr_str(conf_key_obs_var, eng.conf_info.Obs->var_info->name_attr()); + } at.set_entry(row, c++, s.text()); // Observation Variable Units - s = check_hdr_str(conf_key_obs_units, - eng.conf_info.Obs->var_info->units_attr(), true); + if (eng.is_multivar_super) { + s = "NA"; + } else { + s = check_hdr_str(conf_key_obs_units, + eng.conf_info.Obs->var_info->units_attr(), true); + } at.set_entry(row, c++, s.text()); // Observation Variable Level - s = check_hdr_str(conf_key_obs_lev, + if (eng.is_multivar_super) { + s = eng.conf_info.obs_multivar_level; + } else { + s = check_hdr_str(conf_key_obs_lev, eng.conf_info.Obs->var_info->level_attr(), true); + } at.set_entry(row, c++, s.text()); // Observation type diff --git a/src/libcode/vx_shapedata/engine.h b/src/libcode/vx_shapedata/engine.h index c1fcd3547e..c975a06691 100644 --- a/src/libcode/vx_shapedata/engine.h +++ b/src/libcode/vx_shapedata/engine.h @@ -181,8 +181,9 @@ class ModeFuzzyEngine { void set_grid(const Grid *); void set(const ShapeData &fcst_wd, const ShapeData &obs_wd); - void set_no_conv(const ShapeData &fcst_wd, const ShapeData &obs_wd); + void set_only_split(const ShapeData &fcst_wd, const ShapeData &obs_wd); + void set_super(const ShapeData &fcst_wd, const ShapeData &obs_wd); void set_fcst (const ShapeData & fcst_wd); void set_obs (const ShapeData & obs_wd); @@ -190,6 +191,12 @@ class ModeFuzzyEngine { void set_fcst_no_conv (const ShapeData & fcst_wd); void set_obs_no_conv (const ShapeData & obs_wd); + void set_fcst_only_split (const ShapeData & fcst_wd); + void set_obs_only_split (const ShapeData & obs_wd); + + void set_fcst_super (const ShapeData & fcst_wd); + void set_obs_super (const ShapeData & obs_wd); + int two_to_one(int, int) const; void do_fcst_convolution(); @@ -209,8 +216,14 @@ class ModeFuzzyEngine { void do_fcst_merging(const char *default_config, const char *merge_config); + void do_fcst_merging(const char *default_config, + const char *merge_config, + const ShapeData &merge_data); void do_obs_merging(const char *default_config, const char *merge_config); + void do_obs_merging(const char *default_config, + const char *merge_config, + const ShapeData &merge_data); void do_matching(); @@ -236,6 +249,14 @@ class ModeFuzzyEngine { void do_fcst_merge_thresh(); void do_obs_merge_thresh(); + // + // Perform merging of the forecast and observation fields + // based on an input merge shapes object + // + + void do_fcst_merge_thresh(const ShapeData &merge_data); + void do_obs_merge_thresh(const ShapeData &merge_data); + // // Perform merging of the forecast and observation fields // using a Fuzzy ModeFuzzyEngine @@ -293,14 +314,17 @@ class ModeFuzzyEngine { bool need_fcst_clus_split; bool need_obs_clus_split; + bool is_multivar_super; // used when producing output files + bool is_multivar_intensity; // used when producing output files + const Grid * grid; // not allocated ShapeData * fcst_raw; // allocated - ShapeData * fcst_thresh; // allocated - ShapeData * fcst_conv; // allocated - ShapeData * fcst_mask; // allocated - ShapeData * fcst_split; // allocated - ShapeData * fcst_clus_split; // allocated + ShapeData * fcst_thresh; // allocated thresholded raw (values are 1 or 0) + ShapeData * fcst_conv; // allocated convolve of raw + ShapeData * fcst_mask; // allocated thresholded convolved, filtered using attribute logic (values are 1 or 0) + ShapeData * fcst_split; // allocated split of fcst_mask.. final one, numbers 1, 2, ... + ShapeData * fcst_clus_split; // allocated numbered 1 and up ShapeData * obs_raw; // allocated ShapeData * obs_thresh; // allocated @@ -353,7 +377,8 @@ class ModeFuzzyEngine { extern double total_interest (ModeConfInfo &, const PairFeature &, int, int, bool is_single); extern double interest_percentile(ModeFuzzyEngine &, const double, const int); -extern void write_engine_stats (ModeFuzzyEngine &, const Grid &, AsciiTable &); +extern void write_engine_stats (ModeFuzzyEngine &, const Grid &, AsciiTable &, bool isMultiVarSuper=false, + bool isMultivarIntensity=false); extern void write_header_row (ModeFuzzyEngine &, AsciiTable &, const int row); // row usually zero extern void write_header_columns (ModeFuzzyEngine &, const Grid &, AsciiTable &, const int row); extern void write_fcst_single (ModeFuzzyEngine &, const int, const Grid &, AsciiTable &, const int); diff --git a/src/libcode/vx_shapedata/mode_conf_info.cc b/src/libcode/vx_shapedata/mode_conf_info.cc index af16067528..aea85582c0 100644 --- a/src/libcode/vx_shapedata/mode_conf_info.cc +++ b/src/libcode/vx_shapedata/mode_conf_info.cc @@ -24,6 +24,10 @@ using namespace std; #include "vx_data2d_factory.h" #include "vx_log.h" +//////////////////////////////////////////////////////////////////////// + +static const char default_multivar_name[] = "Super"; + //////////////////////////////////////////////////////////////////////// // // Code for class ModeConfInfo @@ -565,7 +569,7 @@ const DictionaryEntry * ee = dict->lookup(conf_key_field); if ( !ee ) { - mlog << "\n\n ModeConfInfo::read_fields () -> \"field\" entry not found in dictionary!\n\n"; + mlog << "\nModeConfInfo::read_fields () -> \"field\" entry not found in dictionary!\n\n"; exit ( 1 ); @@ -577,9 +581,6 @@ const int N = ( (field->is_array()) ? (field->n_entries()) : 1 ); info_array = new Mode_Field_Info [N]; -N_fields = N; - - if ( field->is_array() ) { int j, k; @@ -589,11 +590,12 @@ if ( field->is_array() ) { if ( (N_fields > 0) && (N != N_fields) ) { mlog << Error - << "\n\n ModeConfInfo::read_field_dict() -> fcst and obs dictionaries have different number of entries\n\n"; + << "\nModeConfInfo::read_field_dict() -> fcst and obs dictionaries have different number of entries\n\n"; exit ( 1 ); } + N_fields = N; for (j=0; jis_array() ) { if ( (e->type() != DictionaryType) && (e->type() != ArrayType) ) { mlog << Error - << "\n\n ModeConfInfo::read_field_dict() -> field entry # " << (j + 1) << " is not a dictionary!\n\n"; + << "\nModeConfInfo::read_field_dict() -> field entry # " << (j + 1) << " is not a dictionary!\n\n"; exit ( 1 ); @@ -626,10 +628,12 @@ if ( field->is_array() ) { } // if is array + // // nope, traditional mode // +N_fields = N; info_array[0].set(false, 0, dict, &conf, type, _fo); // @@ -688,7 +692,7 @@ void ModeConfInfo::set_field_index(int k) if ( (k < 0) || (k >= N_fields) ) { mlog << Error - << "\n\n ModeConfInfo::set_field_index(int) -> range check error\n\n"; + << "\nModeConfInfo::set_field_index(int) -> range check error\n\n"; exit ( 1 ); @@ -854,7 +858,7 @@ if ( (k < 0) || (k >= Fcst->conv_radius_array.n_elements()) ) { } Fcst->conv_radius = Fcst->conv_radius_array[k]; - Obs->conv_radius = Obs->conv_radius_array[k]; +Obs->conv_radius = Obs->conv_radius_array[k]; return; @@ -864,6 +868,23 @@ return; //////////////////////////////////////////////////////////////////////// +void ModeConfInfo::set_conv_thresh(SingleThresh s) +{ +Fcst->conv_thresh = s; +Obs->conv_thresh = s; +} + +//////////////////////////////////////////////////////////////////////// + +void ModeConfInfo::set_conv_radius(int r) +{ +Fcst->conv_radius = r; +Obs->conv_radius = r; +} + +//////////////////////////////////////////////////////////////////////// + + void ModeConfInfo::set_conv_thresh_by_index(int k) { @@ -908,6 +929,62 @@ return; //////////////////////////////////////////////////////////////////////// +void ModeConfInfo::set_fcst_conv_thresh_by_merge_index(int k) + +{ + +Fcst->set_conv_thresh_by_merge_index(k); + +return; + +} + + +//////////////////////////////////////////////////////////////////////// + + +void ModeConfInfo::set_obs_conv_thresh_by_merge_index(int k) + +{ + +Obs->set_conv_thresh_by_merge_index(k); + +return; + +} + + +//////////////////////////////////////////////////////////////////////// + +void ModeConfInfo::set_fcst_merge_flag(MergeType t) +{ +Fcst->merge_flag = t; +} + +//////////////////////////////////////////////////////////////////////// + +void ModeConfInfo::set_obs_merge_flag(MergeType t) +{ +Obs->merge_flag = t; +} + +//////////////////////////////////////////////////////////////////////// + +void ModeConfInfo::set_fcst_merge_thresh(SingleThresh s) +{ +Fcst->merge_thresh = s; +} + +//////////////////////////////////////////////////////////////////////// + +void ModeConfInfo::set_obs_merge_thresh(SingleThresh s) +{ +Obs->merge_thresh = s; +} + +//////////////////////////////////////////////////////////////////////// + + void ModeConfInfo::set_obs_merge_thresh_by_index(int k) { @@ -937,7 +1014,7 @@ return ( nr*nt ); //////////////////////////////////////////////////////////////////////// -bool ModeConfInfo::is_multivar() +bool ModeConfInfo::is_multivar() { @@ -946,7 +1023,7 @@ const DictionaryEntry * e = conf.lookup("fcst"); if ( e->type() != DictionaryType ) { mlog << Error - << "\n\n ModeConfInfo::is_multivar() const -> bad object type for entry \"fcst\"\n\n"; + << "\nModeConfInfo::is_multivar() const -> bad object type for entry \"fcst\"\n\n"; exit ( 1 ); @@ -963,7 +1040,7 @@ switch ( e2->type() ) { default: mlog << Error - << "\n\n ModeConfInfo::is_multivar() const -> bad object type for entry \"fcst.field\"\n\n"; + << "\nModeConfInfo::is_multivar() const -> bad object type for entry \"fcst.field\"\n\n"; exit ( 1 ); } @@ -984,24 +1061,90 @@ void ModeConfInfo::get_multivar_programs() Dictionary * dict = (Dictionary *) 0; fcst_multivar_logic.clear(); - obs_multivar_logic.clear(); - +obs_multivar_logic.clear(); +fcst_multivar_name = default_multivar_name; +obs_multivar_name = default_multivar_name; +fcst_multivar_level = na_str; +obs_multivar_level = na_str; dict = conf.lookup_dictionary(conf_key_fcst); -if ( dict->lookup(conf_key_multivar_logic) ) fcst_multivar_logic = dict->lookup_string(conf_key_multivar_logic); +if ( dict->lookup(conf_key_multivar_logic) ) fcst_multivar_logic = dict->lookup_string(conf_key_multivar_logic); +if ( dict->lookup(conf_key_multivar_name) ) fcst_multivar_name = dict->lookup_string(conf_key_multivar_name); +if ( dict->lookup(conf_key_multivar_level) ) fcst_multivar_level = dict->lookup_string(conf_key_multivar_level); dict = conf.lookup_dictionary(conf_key_obs); -if ( dict->lookup(conf_key_multivar_logic) ) obs_multivar_logic = dict->lookup_string(conf_key_multivar_logic); - +if ( dict->lookup(conf_key_multivar_logic) ) obs_multivar_logic = dict->lookup_string(conf_key_multivar_logic); +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; +} + +//////////////////////////////////////////////////////////////////////// + + +void ModeConfInfo::check_multivar_not_implemented() +{ + if (!is_multivar()) { + return; + } + + bool status = false; + if (quilt) { + mlog << Error + << "\nModeConfInfo::multivar_not_implemented:\n" + << " quilting not yet implemented for multivar mode\n\n"; + status = true; + } + + for (int i=0; i +#include #include "vx_config.h" #include "vx_data2d.h" @@ -89,9 +90,16 @@ class ModeConfInfo { ConcatString fcst_multivar_logic; ConcatString obs_multivar_logic; + BoolArray multivar_intensity; + ConcatString fcst_multivar_name; + ConcatString fcst_multivar_level; + ConcatString obs_multivar_name; + ConcatString obs_multivar_level; void get_multivar_programs(); + void check_multivar_not_implemented(); + bool multivar_intensities_all_false() const; ///////////////////////////////////////////////////////////////////// @@ -215,17 +223,29 @@ class ModeConfInfo { void set_conv_radius_by_index (int); void set_conv_thresh_by_index (int); + void set_conv_thresh(SingleThresh); + void set_conv_radius(int); int n_conv_threshs () const; int n_conv_radii () const; int n_runs() const; // # threshs times # radii + int n_fields() const; // should be 1 for traditional mode, > 1 for muiltivar + int get_compression_level(); void set_fcst_merge_thresh_by_index (int); void set_obs_merge_thresh_by_index (int); + void set_fcst_conv_thresh_by_merge_index (int); + void set_obs_conv_thresh_by_merge_index (int); + + void set_fcst_merge_flag(MergeType); + void set_obs_merge_flag(MergeType); + void set_fcst_merge_thresh(SingleThresh); + void set_obs_merge_thresh(SingleThresh); + }; @@ -242,6 +262,8 @@ inline int ModeConfInfo::get_compression_level() { return conf.nc_compression(); inline int ModeConfInfo::field_index() const { return Field_Index; } +inline int ModeConfInfo::n_fields() const { return N_fields; } + //////////////////////////////////////////////////////////////////////// diff --git a/src/libcode/vx_shapedata/mode_field_info.cc b/src/libcode/vx_shapedata/mode_field_info.cc index 94943ed2e1..6cecb55d07 100644 --- a/src/libcode/vx_shapedata/mode_field_info.cc +++ b/src/libcode/vx_shapedata/mode_field_info.cc @@ -231,13 +231,22 @@ if ( dict->lookup(conf_key_vld_thresh) ) { } -if ( dict->lookup(conf_key_merge_flag) ) { - - merge_flag = int_to_mergetype(dict->lookup_int(conf_key_merge_flag)); - +// for the multivar case, go without parent, and error out if merge flag is +// not set for the individual field +if ( _multivar ) { + if ( dict->lookup(conf_key_merge_flag, false)) { + merge_flag = int_to_mergetype(dict->lookup_int(conf_key_merge_flag)); + } else { + mlog << Error << "\nMode_Field_Info::set() -> " + << "'merge_flag' must be explicitly set for all fields with multivariate mode\n\n"; + exit ( 1 ); + } +} else { + if ( dict->lookup(conf_key_merge_flag, true)) { + merge_flag = int_to_mergetype(dict->lookup_int(conf_key_merge_flag)); + } } - - + filter_attr_map = parse_conf_filter_attr_map(dict); if ( FO == 'F' ) raw_pi = parse_conf_plot_info(conf->lookup_dictionary(conf_key_fcst_raw_plot)); @@ -258,6 +267,29 @@ return; //////////////////////////////////////////////////////////////////////// + +void Mode_Field_Info::set_conv_thresh_by_merge_index (int k) +{ +if ( (k < 0) || (k >= merge_thresh_array.n_elements()) ) { + + mlog << Error << "\nMode_Field_Info::set_conv_thresh_by_merge_index(int) -> " + << "range check error\n\n"; + + exit ( 1 ); + +} + +conv_thresh = merge_thresh_array[k]; + + +return; + +} + + +//////////////////////////////////////////////////////////////////////// + + void Mode_Field_Info::set_merge_thresh_by_index (int k) { diff --git a/src/libcode/vx_shapedata/mode_field_info.h b/src/libcode/vx_shapedata/mode_field_info.h index bdcd93b51b..132f2df4b2 100644 --- a/src/libcode/vx_shapedata/mode_field_info.h +++ b/src/libcode/vx_shapedata/mode_field_info.h @@ -89,6 +89,7 @@ class Mode_Field_Info { // member functions // + void set_conv_thresh_by_merge_index (int); void set_merge_thresh_by_index (int); int n_merge_threshs () const; bool need_merge_thresh () const; // mergetype is both or thresh diff --git a/src/libcode/vx_shapedata/shapedata.cc b/src/libcode/vx_shapedata/shapedata.cc index 467f950122..9051d00819 100644 --- a/src/libcode/vx_shapedata/shapedata.cc +++ b/src/libcode/vx_shapedata/shapedata.cc @@ -1961,6 +1961,32 @@ void ShapeData::threshold(SingleThresh t) { /////////////////////////////////////////////////////////////////////////////// +void ShapeData::set_to_1_or_0() +{ + int j, x, y; + double v; + const int nx = data.nx(); + const int ny = data.ny(); + + for(x=0; x &attr_map, const ShapeData *raw_ptr, const SingleThresh &obj_thresh, diff --git a/src/libcode/vx_shapedata/shapedata.h b/src/libcode/vx_shapedata/shapedata.h index afc5111dd3..939b4c5fe5 100644 --- a/src/libcode/vx_shapedata/shapedata.h +++ b/src/libcode/vx_shapedata/shapedata.h @@ -26,6 +26,7 @@ /////////////////////////////////////////////////////////////////////////////// #include +#include #include "moments.h" #include "vx_util.h" @@ -105,6 +106,10 @@ class ShapeData { bool is_zero (int x, int y) const; bool is_nonzero (int x, int y) const; + void debug_examine() const; + std::string sdebug_examine() const; + + // // check if a point or it's neighbors are non-zero // @@ -161,6 +166,7 @@ class ShapeData { int n_objects() const; + void set_to_1_or_0() ; void threshold(double t); void threshold(SingleThresh); void threshold_attr(const std::map&, @@ -188,6 +194,9 @@ inline bool ShapeData::is_bad_data (int x, int y) const { return ( ::is_bad_da inline bool ShapeData::is_zero (int x, int y) const { return ( is_eq(data(x, y), 0.0) ); } inline bool ShapeData::is_nonzero (int x, int y) const { return ( ! is_eq(data(x, y), 0.0) ); } +inline void ShapeData::debug_examine() const { data.debug_examine(); } +inline std::string ShapeData::sdebug_examine() const { return data.sdebug_examine(); } + /////////////////////////////////////////////////////////////////////////////// diff --git a/src/tools/core/mode/Makefile.am b/src/tools/core/mode/Makefile.am index 5903eef16b..c3a9ccbfa5 100644 --- a/src/tools/core/mode/Makefile.am +++ b/src/tools/core/mode/Makefile.am @@ -13,8 +13,7 @@ include ${top_srcdir}/Make-include bin_PROGRAMS = mode mode_SOURCES = mode_usage.cc \ mode_frontend.cc \ - mode_multivar.cc \ - mode_singlevar.cc \ + multivar_data.cc \ multivar_frontend.cc \ mode.cc \ combine_boolplanes.cc \ diff --git a/src/tools/core/mode/Makefile.in b/src/tools/core/mode/Makefile.in index 655306db7b..4bab26a2ce 100644 --- a/src/tools/core/mode/Makefile.in +++ b/src/tools/core/mode/Makefile.in @@ -102,9 +102,9 @@ CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_mode_OBJECTS = mode-mode_usage.$(OBJEXT) \ - mode-mode_frontend.$(OBJEXT) mode-mode_multivar.$(OBJEXT) \ - mode-mode_singlevar.$(OBJEXT) mode-multivar_frontend.$(OBJEXT) \ - mode-mode.$(OBJEXT) mode-combine_boolplanes.$(OBJEXT) \ + mode-mode_frontend.$(OBJEXT) mode-multivar_data.$(OBJEXT) \ + mode-multivar_frontend.$(OBJEXT) mode-mode.$(OBJEXT) \ + mode-combine_boolplanes.$(OBJEXT) \ mode-objects_from_netcdf.$(OBJEXT) mode-mode_ps_file.$(OBJEXT) \ mode-plot_engine.$(OBJEXT) mode-page_1.$(OBJEXT) \ mode-fcst_enlarge_page.$(OBJEXT) \ @@ -135,10 +135,9 @@ am__depfiles_remade = ./$(DEPDIR)/mode-cluster_page.Po \ ./$(DEPDIR)/mode-fcst_enlarge_page.Po ./$(DEPDIR)/mode-mode.Po \ ./$(DEPDIR)/mode-mode_exec.Po \ ./$(DEPDIR)/mode-mode_frontend.Po \ - ./$(DEPDIR)/mode-mode_multivar.Po \ ./$(DEPDIR)/mode-mode_ps_file.Po \ - ./$(DEPDIR)/mode-mode_singlevar.Po \ ./$(DEPDIR)/mode-mode_usage.Po \ + ./$(DEPDIR)/mode-multivar_data.Po \ ./$(DEPDIR)/mode-multivar_frontend.Po \ ./$(DEPDIR)/mode-objects_from_netcdf.Po \ ./$(DEPDIR)/mode-obs_enlarge_page.Po \ @@ -338,8 +337,7 @@ top_srcdir = @top_srcdir@ MAINTAINERCLEANFILES = Makefile.in mode_SOURCES = mode_usage.cc \ mode_frontend.cc \ - mode_multivar.cc \ - mode_singlevar.cc \ + multivar_data.cc \ multivar_frontend.cc \ mode.cc \ combine_boolplanes.cc \ @@ -488,10 +486,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode-mode.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode-mode_exec.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode-mode_frontend.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode-mode_multivar.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode-mode_ps_file.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode-mode_singlevar.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode-mode_usage.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode-multivar_data.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode-multivar_frontend.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode-objects_from_netcdf.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode-obs_enlarge_page.Po@am__quote@ # am--include-marker @@ -547,33 +544,19 @@ mode-mode_frontend.obj: mode_frontend.cc @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o mode-mode_frontend.obj `if test -f 'mode_frontend.cc'; then $(CYGPATH_W) 'mode_frontend.cc'; else $(CYGPATH_W) '$(srcdir)/mode_frontend.cc'; fi` -mode-mode_multivar.o: mode_multivar.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT mode-mode_multivar.o -MD -MP -MF $(DEPDIR)/mode-mode_multivar.Tpo -c -o mode-mode_multivar.o `test -f 'mode_multivar.cc' || echo '$(srcdir)/'`mode_multivar.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mode-mode_multivar.Tpo $(DEPDIR)/mode-mode_multivar.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='mode_multivar.cc' object='mode-mode_multivar.o' libtool=no @AMDEPBACKSLASH@ +mode-multivar_data.o: multivar_data.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT mode-multivar_data.o -MD -MP -MF $(DEPDIR)/mode-multivar_data.Tpo -c -o mode-multivar_data.o `test -f 'multivar_data.cc' || echo '$(srcdir)/'`multivar_data.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mode-multivar_data.Tpo $(DEPDIR)/mode-multivar_data.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='multivar_data.cc' object='mode-multivar_data.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o mode-mode_multivar.o `test -f 'mode_multivar.cc' || echo '$(srcdir)/'`mode_multivar.cc +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o mode-multivar_data.o `test -f 'multivar_data.cc' || echo '$(srcdir)/'`multivar_data.cc -mode-mode_multivar.obj: mode_multivar.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT mode-mode_multivar.obj -MD -MP -MF $(DEPDIR)/mode-mode_multivar.Tpo -c -o mode-mode_multivar.obj `if test -f 'mode_multivar.cc'; then $(CYGPATH_W) 'mode_multivar.cc'; else $(CYGPATH_W) '$(srcdir)/mode_multivar.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mode-mode_multivar.Tpo $(DEPDIR)/mode-mode_multivar.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='mode_multivar.cc' object='mode-mode_multivar.obj' libtool=no @AMDEPBACKSLASH@ +mode-multivar_data.obj: multivar_data.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT mode-multivar_data.obj -MD -MP -MF $(DEPDIR)/mode-multivar_data.Tpo -c -o mode-multivar_data.obj `if test -f 'multivar_data.cc'; then $(CYGPATH_W) 'multivar_data.cc'; else $(CYGPATH_W) '$(srcdir)/multivar_data.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mode-multivar_data.Tpo $(DEPDIR)/mode-multivar_data.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='multivar_data.cc' object='mode-multivar_data.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o mode-mode_multivar.obj `if test -f 'mode_multivar.cc'; then $(CYGPATH_W) 'mode_multivar.cc'; else $(CYGPATH_W) '$(srcdir)/mode_multivar.cc'; fi` - -mode-mode_singlevar.o: mode_singlevar.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT mode-mode_singlevar.o -MD -MP -MF $(DEPDIR)/mode-mode_singlevar.Tpo -c -o mode-mode_singlevar.o `test -f 'mode_singlevar.cc' || echo '$(srcdir)/'`mode_singlevar.cc -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mode-mode_singlevar.Tpo $(DEPDIR)/mode-mode_singlevar.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='mode_singlevar.cc' object='mode-mode_singlevar.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o mode-mode_singlevar.o `test -f 'mode_singlevar.cc' || echo '$(srcdir)/'`mode_singlevar.cc - -mode-mode_singlevar.obj: mode_singlevar.cc -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT mode-mode_singlevar.obj -MD -MP -MF $(DEPDIR)/mode-mode_singlevar.Tpo -c -o mode-mode_singlevar.obj `if test -f 'mode_singlevar.cc'; then $(CYGPATH_W) 'mode_singlevar.cc'; else $(CYGPATH_W) '$(srcdir)/mode_singlevar.cc'; fi` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mode-mode_singlevar.Tpo $(DEPDIR)/mode-mode_singlevar.Po -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='mode_singlevar.cc' object='mode-mode_singlevar.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o mode-mode_singlevar.obj `if test -f 'mode_singlevar.cc'; then $(CYGPATH_W) 'mode_singlevar.cc'; else $(CYGPATH_W) '$(srcdir)/mode_singlevar.cc'; fi` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o mode-multivar_data.obj `if test -f 'multivar_data.cc'; then $(CYGPATH_W) 'multivar_data.cc'; else $(CYGPATH_W) '$(srcdir)/multivar_data.cc'; fi` mode-multivar_frontend.o: multivar_frontend.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT mode-multivar_frontend.o -MD -MP -MF $(DEPDIR)/mode-multivar_frontend.Tpo -c -o mode-multivar_frontend.o `test -f 'multivar_frontend.cc' || echo '$(srcdir)/'`multivar_frontend.cc @@ -877,10 +860,9 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/mode-mode.Po -rm -f ./$(DEPDIR)/mode-mode_exec.Po -rm -f ./$(DEPDIR)/mode-mode_frontend.Po - -rm -f ./$(DEPDIR)/mode-mode_multivar.Po -rm -f ./$(DEPDIR)/mode-mode_ps_file.Po - -rm -f ./$(DEPDIR)/mode-mode_singlevar.Po -rm -f ./$(DEPDIR)/mode-mode_usage.Po + -rm -f ./$(DEPDIR)/mode-multivar_data.Po -rm -f ./$(DEPDIR)/mode-multivar_frontend.Po -rm -f ./$(DEPDIR)/mode-objects_from_netcdf.Po -rm -f ./$(DEPDIR)/mode-obs_enlarge_page.Po @@ -938,10 +920,9 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/mode-mode.Po -rm -f ./$(DEPDIR)/mode-mode_exec.Po -rm -f ./$(DEPDIR)/mode-mode_frontend.Po - -rm -f ./$(DEPDIR)/mode-mode_multivar.Po -rm -f ./$(DEPDIR)/mode-mode_ps_file.Po - -rm -f ./$(DEPDIR)/mode-mode_singlevar.Po -rm -f ./$(DEPDIR)/mode-mode_usage.Po + -rm -f ./$(DEPDIR)/mode-multivar_data.Po -rm -f ./$(DEPDIR)/mode-multivar_frontend.Po -rm -f ./$(DEPDIR)/mode-objects_from_netcdf.Po -rm -f ./$(DEPDIR)/mode-obs_enlarge_page.Po diff --git a/src/tools/core/mode/cluster_page.cc b/src/tools/core/mode/cluster_page.cc index aad7b4ba40..06efac80d3 100644 --- a/src/tools/core/mode/cluster_page.cc +++ b/src/tools/core/mode/cluster_page.cc @@ -41,13 +41,13 @@ void ModePsFile::do_cluster_page(ModeFuzzyEngine & eng, EngineType eng_type, con { -int i; -double Htab_a, Htab_b; -double Htab, Vtab; -double dx, dy; -const double Htab_cen = PageWidth/2.0; -ConcatString label; -char junk[1024]; + int i; + double Htab_a, Htab_b; + double Htab, Vtab; + double dx, dy; + const double Htab_cen = PageWidth/2.0; + ConcatString label; + char junk[1024]; ///////////////////////////////////////////////////////////////// // @@ -55,21 +55,21 @@ char junk[1024]; // ///////////////////////////////////////////////////////////////// -inc_pagenumber(); + inc_pagenumber(); -Htab_a = Htab_cen - SmallPane.width()/4.0; -Htab_b = Htab_cen + SmallPane.width()/4.0; + Htab_a = Htab_cen - SmallPane.width()/4.0; + Htab_b = Htab_cen + SmallPane.width()/4.0; -Vtab = PageHeight - 2.0*Vmargin; -set_view(Vtab - LargePlotHeight, Vtab, Htab_cen); + Vtab = PageHeight - 2.0*Vmargin; + set_view(Vtab - LargePlotHeight, Vtab, Htab_cen); -choose_font(31, 24.0); -write_centered_text(1, 1, Htab_cen, View_box.top() + TextSep/2.0, - 0.5, 0.5, "Cluster Object Information"); + choose_font(31, 24.0); + write_centered_text(1, 1, Htab_cen, View_box.top() + TextSep/2.0, + 0.5, 0.5, "Cluster Object Information"); -choose_font(31, 18.0); -write_centered_text(1, 1, Htab_a, 727.0, 0.5, 0.5, FcstString.c_str()); -write_centered_text(1, 1, Htab_b, 727.0, 0.5, 0.5, ObsString.c_str()); + choose_font(31, 18.0); + write_centered_text(1, 1, Htab_a, 727.0, 0.5, 0.5, FcstString.c_str()); + write_centered_text(1, 1, Htab_b, 727.0, 0.5, 0.5, ObsString.c_str()); ///////////////////////////////////////////////////////////////// // @@ -77,12 +77,12 @@ write_centered_text(1, 1, Htab_b, 727.0, 0.5, 0.5, ObsString.c_str()); // ///////////////////////////////////////////////////////////////// -set_view(Vtab_1, Vtab_1 + SmallPlotHeight, Htab_a); -comment("cluster page: fcst split"); -render_ppm(eng, eng_type, *(eng.fcst_split), 1, 1); -outline_view(); -draw_map( &(eng.conf_info.conf) ); -draw_convex_hulls(eng, 1, 0); + set_view(Vtab_1, Vtab_1 + SmallPlotHeight, Htab_a); + comment("cluster page: fcst split"); + render_ppm(eng, eng_type, *(eng.fcst_split), 1, 1); + outline_view(); + draw_map( &(eng.conf_info.conf) ); + draw_convex_hulls(eng, 1, 0); ///////////////////////////////////////////////////////////////// // @@ -90,12 +90,12 @@ draw_convex_hulls(eng, 1, 0); // ///////////////////////////////////////////////////////////////// -set_view(Vtab_1, Vtab_1 + SmallPlotHeight, Htab_b); -comment("cluster page: obs split"); -render_ppm(eng, eng_type, *(eng.obs_split), 0, 1); -outline_view(); -draw_map( &(eng.conf_info.conf) ); -draw_convex_hulls(eng, 0, 0); + set_view(Vtab_1, Vtab_1 + SmallPlotHeight, Htab_b); + comment("cluster page: obs split"); + render_ppm(eng, eng_type, *(eng.obs_split), 0, 1); + outline_view(); + draw_map( &(eng.conf_info.conf) ); + draw_convex_hulls(eng, 0, 0); ///////////////////////////////////////////////////////////////// // @@ -103,10 +103,10 @@ draw_convex_hulls(eng, 0, 0); // ///////////////////////////////////////////////////////////////// -set_view(Vtab_2, Vtab_2 + SmallPlotHeight, Htab_a); -outline_view(); -draw_map( &(eng.conf_info.conf) ); -draw_convex_hulls(eng, 1, 1); + set_view(Vtab_2, Vtab_2 + SmallPlotHeight, Htab_a); + outline_view(); + draw_map( &(eng.conf_info.conf) ); + draw_convex_hulls(eng, 1, 1); ///////////////////////////////////////////////////////////////// // @@ -114,10 +114,10 @@ draw_convex_hulls(eng, 1, 1); // ///////////////////////////////////////////////////////////////// -set_view(Vtab_2, Vtab_2 + SmallPlotHeight, Htab_b); -outline_view(); -draw_map( &(eng.conf_info.conf) ); -draw_convex_hulls(eng, 0, 1); + set_view(Vtab_2, Vtab_2 + SmallPlotHeight, Htab_b); + outline_view(); + draw_map( &(eng.conf_info.conf) ); + draw_convex_hulls(eng, 0, 1); ///////////////////////////////////////////////////////////////// // @@ -125,167 +125,167 @@ draw_convex_hulls(eng, 0, 1); // ///////////////////////////////////////////////////////////////// -int j, r, c; -TableHelper t; + int j, r, c; + TableHelper t; -j = eng.n_clus; + j = eng.n_clus; -if ( j > max_table_rows ) j = max_table_rows; + if ( j > max_table_rows ) j = max_table_rows; -t.set(*this, j + 1, 13); + t.set(*this, j + 1, 13); -for (j=0; j<(t.ncols()); ++j) t.set_col_width(j, 45.0); + for (j=0; j<(t.ncols()); ++j) t.set_col_width(j, 45.0); -t.set_row_height(0, 25.0); + t.set_row_height(0, 25.0); -for (j=1; j<(t.nrows()); ++j) t.set_row_height(j, 15.0); + for (j=1; j<(t.nrows()); ++j) t.set_row_height(j, 15.0); -t.set_pin(306.0, Vtab_2 - TextSep, 0.5, 1.0); + t.set_pin(306.0, Vtab_2 - TextSep, 0.5, 1.0); -t.fill_row(0, blue1); + t.fill_row(0, blue1); -for (j=2; j<(t.nrows()); j+=2) t.fill_row(j, light_gray); + for (j=2; j<(t.nrows()); j+=2) t.fill_row(j, light_gray); -t.draw_skeleton(0.2); -t.outline_table(0.2, black); + t.draw_skeleton(0.2); + t.outline_table(0.2, black); -choose_font(31, 11.0); + choose_font(31, 11.0); -Vtab = Vtab_2 - 1.0*TextSep; + Vtab = Vtab_2 - 1.0*TextSep; // // Plot the column headers // -c = 0; + c = 0; -bold(); + bold(); -write_header_cell(t, c++, "CLUS", "PAIR"); -write_header_cell(t, c++, "CEN", "DIST"); -write_header_cell(t, c++, "ANG", "DIFF"); -write_header_cell(t, c++, "FCST", "AREA"); -write_header_cell(t, c++, "OBS", "AREA"); -write_header_cell(t, c++, "INTER", "AREA"); -write_header_cell(t, c++, "UNION", "AREA"); -write_header_cell(t, c++, "SYMM", "DIFF"); -write_header_cell(t, c++, "FCST", "INT 50"); -write_header_cell(t, c++, "OBS", "INT 50"); -write_header_cell(t, c++, "FCST", "INT 90"); -write_header_cell(t, c++, "OBS", "INT 90"); -write_header_cell(t, c++, "TOT", "INTR"); + write_header_cell(t, c++, "CLUS", "PAIR"); + write_header_cell(t, c++, "CEN", "DIST"); + write_header_cell(t, c++, "ANG", "DIFF"); + write_header_cell(t, c++, "FCST", "AREA"); + write_header_cell(t, c++, "OBS", "AREA"); + write_header_cell(t, c++, "INTER", "AREA"); + write_header_cell(t, c++, "UNION", "AREA"); + write_header_cell(t, c++, "SYMM", "DIFF"); + write_header_cell(t, c++, "FCST", "INT 50"); + write_header_cell(t, c++, "OBS", "INT 50"); + write_header_cell(t, c++, "FCST", "INT 90"); + write_header_cell(t, c++, "OBS", "INT 90"); + write_header_cell(t, c++, "TOT", "INTR"); -roman(); + roman(); -Vtab -= (TextSep + 10.0); + Vtab -= (TextSep + 10.0); // // // -dx = 3.0*TextSep; - -dy = 2.0; - -for(i=0; i= Vmargin; i++) { - - r = i + 1; - - c = 0; - - if ( r >= t.nrows() ) break; - - Htab = Hmargin; - - // Cluster ID - snprintf(junk, sizeof(junk), "%d", i+1); - t.write_xy1_to_cell(r, c++, 10.0, dy, 0.5, 0.0, junk); - // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); - Htab += dx; - - // Centroid Distance - snprintf(junk, sizeof(junk), "%.2f", eng.pair_cluster[i].centroid_dist); - t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); - // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); - Htab += dx; - - // Angle Difference - snprintf(junk, sizeof(junk), "%.2f", eng.pair_cluster[i].angle_diff); - t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); - // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); - Htab += dx; - - // Forecast Area - snprintf(junk, sizeof(junk), "%i", nint(eng.pair_cluster[i].Fcst[0].area)); - t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); - // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); - Htab += dx; - - // Observation Area - snprintf(junk, sizeof(junk), "%i", nint(eng.pair_cluster[i].Obs[0].area)); - t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); - // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); - Htab += dx; - - // Intersection Area - snprintf(junk, sizeof(junk), "%i", nint(eng.pair_cluster[i].intersection_area)); - t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); - // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); - Htab += dx; - - // Union Area - snprintf(junk, sizeof(junk), "%i", nint(eng.pair_cluster[i].union_area)); - t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); - // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); - Htab += dx; - - // Symmetric Difference - snprintf(junk, sizeof(junk), "%i", nint(eng.pair_cluster[i].symmetric_diff)); - t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); - // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); - Htab += dx; - - // Forecast median intensity - snprintf(junk, sizeof(junk), "%.2f", eng.pair_cluster[i].Fcst[0].intensity_ptile.p50); - t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); - // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); - Htab += dx; - - // Observation median intensity - snprintf(junk, sizeof(junk), "%.2f", eng.pair_cluster[i].Obs[0].intensity_ptile.p50); - t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); - // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); - Htab += dx; - - // Forecast 90th percentile of intensity - snprintf(junk, sizeof(junk), "%.2f", eng.pair_cluster[i].Fcst[0].intensity_ptile.p90); - t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); - // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); - Htab += dx; - - // Observation median intensity - snprintf(junk, sizeof(junk), "%.2f", eng.pair_cluster[i].Obs[0].intensity_ptile.p90); - t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); - // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); - Htab += dx; - - // Total Interest - if(eng.info_clus[i].interest_value < 0) label = na_str; - else { - snprintf(junk, sizeof(junk), "%.4f", eng.info_clus[i].interest_value); - label = junk; - } - t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); - // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, label); - // Htab += dx; - - Vtab -= TextSep; - -} // for i + dx = 3.0*TextSep; + + dy = 2.0; + + for(i=0; i= Vmargin; i++) { + + r = i + 1; + + c = 0; + + if ( r >= t.nrows() ) break; + + Htab = Hmargin; + + // Cluster ID + snprintf(junk, sizeof(junk), "%d", i+1); + t.write_xy1_to_cell(r, c++, 10.0, dy, 0.5, 0.0, junk); + // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); + Htab += dx; + + // Centroid Distance + snprintf(junk, sizeof(junk), "%.2f", eng.pair_cluster[i].centroid_dist); + t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); + // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); + Htab += dx; + + // Angle Difference + snprintf(junk, sizeof(junk), "%.2f", eng.pair_cluster[i].angle_diff); + t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); + // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); + Htab += dx; + + // Forecast Area + snprintf(junk, sizeof(junk), "%i", nint(eng.pair_cluster[i].Fcst[0].area)); + t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); + // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); + Htab += dx; + + // Observation Area + snprintf(junk, sizeof(junk), "%i", nint(eng.pair_cluster[i].Obs[0].area)); + t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); + // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); + Htab += dx; + + // Intersection Area + snprintf(junk, sizeof(junk), "%i", nint(eng.pair_cluster[i].intersection_area)); + t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); + // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); + Htab += dx; + + // Union Area + snprintf(junk, sizeof(junk), "%i", nint(eng.pair_cluster[i].union_area)); + t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); + // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); + Htab += dx; + + // Symmetric Difference + snprintf(junk, sizeof(junk), "%i", nint(eng.pair_cluster[i].symmetric_diff)); + t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); + // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); + Htab += dx; + + // Forecast median intensity + snprintf(junk, sizeof(junk), "%.2f", eng.pair_cluster[i].Fcst[0].intensity_ptile.p50); + t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); + // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); + Htab += dx; + + // Observation median intensity + snprintf(junk, sizeof(junk), "%.2f", eng.pair_cluster[i].Obs[0].intensity_ptile.p50); + t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); + // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); + Htab += dx; + + // Forecast 90th percentile of intensity + snprintf(junk, sizeof(junk), "%.2f", eng.pair_cluster[i].Fcst[0].intensity_ptile.p90); + t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); + // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); + Htab += dx; + + // Observation median intensity + snprintf(junk, sizeof(junk), "%.2f", eng.pair_cluster[i].Obs[0].intensity_ptile.p90); + t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); + // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, junk); + Htab += dx; + + // Total Interest + if(eng.info_clus[i].interest_value < 0) label = na_str; + else { + snprintf(junk, sizeof(junk), "%.4f", eng.info_clus[i].interest_value); + label = junk; + } + t.write_xy1_to_cell(r, c++, 40.0, dy, 1.0, 0.0, junk); + // write_centered_text(1, 1, Htab, Vtab, 0.0, 0.5, label); + // Htab += dx; + + Vtab -= TextSep; + + } // for i ///////////////////////////////////////////////////////////////// // @@ -293,9 +293,9 @@ for(i=0; i= Vmargin; i++) { // ///////////////////////////////////////////////////////////////// -showpage(); + showpage(); -return; + return; } @@ -303,9 +303,9 @@ return; //////////////////////////////////////////////////////////////////////// - // - // code for misc functions - // +// +// code for misc functions +// //////////////////////////////////////////////////////////////////////// @@ -315,14 +315,14 @@ void write_header_cell(TableHelper & t, int col, const char * s1, const char * s { -double v1 = 15.0; -double v2 = 3.0; -const double x = 0.5*(t.col_width(col)); + double v1 = 15.0; + double v2 = 3.0; + const double x = 0.5*(t.col_width(col)); -t.write_xy1_to_cell(0, col, x, v1, 0.5, 0.0, s1); -t.write_xy1_to_cell(0, col, x, v2, 0.5, 0.0, s2); + t.write_xy1_to_cell(0, col, x, v1, 0.5, 0.0, s1); + t.write_xy1_to_cell(0, col, x, v2, 0.5, 0.0, s2); -return; + return; } diff --git a/src/tools/core/mode/combine_boolplanes.cc b/src/tools/core/mode/combine_boolplanes.cc index caaf52dbd5..cabe71ea07 100644 --- a/src/tools/core/mode/combine_boolplanes.cc +++ b/src/tools/core/mode/combine_boolplanes.cc @@ -18,51 +18,52 @@ using namespace std; //////////////////////////////////////////////////////////////////////// - // - // assumes all the input BoolPlanes (and the output BoolPlane) are the same size - // +// +// assumes all the input BoolPlanes (and the output BoolPlane) are the same size +// -void combine_boolplanes(const BoolPlane * bpa, const int n_planes, +void combine_boolplanes(const string &name, + const BoolPlane * bpa, const int n_planes, BoolCalc & calc, BoolPlane & bp_out) { -int j, x, y; -const int nx = bp_out.nx(); -const int ny = bp_out.ny(); -vector v(n_planes); -bool tf = false; - - -for (x=0; x v(n_planes); + bool tf = false; + double nTotal = (double)(nx*ny); + double nTrue = 0.0; - v[j] = bpa[j].get(x, y); - } // for j + for (x=0; xrun(Argv); -} + if ( frontend ) { delete frontend; frontend = 0; } + } // // done // -return ( status ); + return ( status ); } diff --git a/src/tools/core/mode/mode_exec.cc b/src/tools/core/mode/mode_exec.cc index cce19fcb42..104c6c31cf 100644 --- a/src/tools/core/mode/mode_exec.cc +++ b/src/tools/core/mode/mode_exec.cc @@ -16,7 +16,7 @@ using namespace std; #include #include #include - +#include #include using namespace netCDF; @@ -36,19 +36,25 @@ static const char program_name [] = "mode"; static const char * default_config_filename = "MET_BASE/config/MODEConfig_default"; +// took this out of the do_conv_thresh() method +static int local_r_index = -1; + +static string fcst_magic_string = ""; +static string obs_magic_string = ""; /////////////////////////////////////////////////////////////////////// static void nc_add_string(NcFile *, const char * text, const char * var_name, const char * dim_name); +static void replaceAll(std::string& str, const std::string& from, const std::string& to); /////////////////////////////////////////////////////////////////////// - // - // Code for class ModeExecutive - // +// +// Code for class ModeExecutive +// /////////////////////////////////////////////////////////////////////// @@ -58,7 +64,7 @@ ModeExecutive::ModeExecutive() { -init_from_scratch(); + init_from_scratch(); } @@ -70,7 +76,7 @@ ModeExecutive::~ModeExecutive() { -clear(); + clear(); } @@ -82,12 +88,12 @@ void ModeExecutive::init_from_scratch() { -fcst_mtddf = (Met2dDataFile *) 0; - obs_mtddf = (Met2dDataFile *) 0; + fcst_mtddf = (Met2dDataFile *) 0; + obs_mtddf = (Met2dDataFile *) 0; -clear(); + clear(); -return; + return; } @@ -99,37 +105,37 @@ void ModeExecutive::clear() { -default_config_file.clear(); -match_config_file.clear(); -merge_config_file.clear(); + default_config_file.clear(); + match_config_file.clear(); + merge_config_file.clear(); -fcst_file.clear(); -obs_file.clear(); + fcst_file.clear(); + obs_file.clear(); -if ( fcst_mtddf ) { delete fcst_mtddf; fcst_mtddf = (Met2dDataFile *) 0; } -if ( obs_mtddf ) { delete obs_mtddf; obs_mtddf = (Met2dDataFile *) 0; } + if ( fcst_mtddf ) { delete fcst_mtddf; fcst_mtddf = (Met2dDataFile *) 0; } + if ( obs_mtddf ) { delete obs_mtddf; obs_mtddf = (Met2dDataFile *) 0; } -for (int j=0; jset_shift_right(shift); - obs_mtddf->set_shift_right(shift); + obs_mtddf->set_shift_right(shift); // List the input files mlog << Debug(1) @@ -201,10 +213,58 @@ R_index = T_index = 0; engine.conf_info.nc_info.compress_level = engine.conf_info.get_compression_level(); -return; + return; } +/////////////////////////////////////////////////////////////////////// + +void ModeExecutive::init_multivar(GrdFileType ftype, GrdFileType otype) + +{ + + R_index = T_index = 0; + + // 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(1) + << "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()); + + // 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)); + GrdFileType l_otype = parse_conf_file_type(engine.conf_info.conf.lookup_dictionary(conf_key_obs)); + + // actually use the values passed in instead, the config ones are not set for this second pass + l_ftype = ftype; + l_otype = otype; + + // Process the configuration + engine.conf_info.process_config(l_ftype, l_otype); + + // check one again for multivar problems + engine.conf_info.check_multivar_not_implemented(); + + // NOTE: do not do shifting, should have been done in the first pass + // const int shift = engine.conf_info.shift_right; + // fcst_mtddf->set_shift_right(shift); + // obs_mtddf->set_shift_right(shift); + + engine.conf_info.nc_info.compress_level = engine.conf_info.get_compression_level(); + + return; + +} /////////////////////////////////////////////////////////////////////// @@ -217,9 +277,9 @@ void ModeExecutive::setup_fcst_obs_data() double fmin, omin, fmax, omax; Fcst_sd.clear(); - Obs_sd.clear(); + Obs_sd.clear(); - // Read the gridded data from the input forecast file + // Read the gridded data from the input forecast file if ( !(fcst_mtddf->data_plane(*(engine.conf_info.Fcst->var_info), Fcst_sd.data)) ) { @@ -241,16 +301,16 @@ void ModeExecutive::setup_fcst_obs_data() exit(1); } - // Determine the verification grid + // Determine the verification grid grid = parse_vx_grid(engine.conf_info.Fcst->var_info->regrid(), &(fcst_mtddf->grid()), &(obs_mtddf->grid())); - // Store the grid + // Store the grid engine.set_grid(&grid); - // Regrid, if necessary + // Regrid, if necessary if ( !(fcst_mtddf->grid() == grid) ) { mlog << Debug(1) @@ -260,7 +320,7 @@ void ModeExecutive::setup_fcst_obs_data() engine.conf_info.Fcst->var_info->regrid()); } - // Regrid, if necessary + // Regrid, if necessary if ( !(obs_mtddf->grid() == grid) ) { mlog << Debug(1) @@ -270,15 +330,15 @@ void ModeExecutive::setup_fcst_obs_data() engine.conf_info.Obs->var_info->regrid()); } - // Rescale probabilites from [0, 100] to [0, 1] + // Rescale probabilites from [0, 100] to [0, 1] if ( engine.conf_info.Fcst->var_info->p_flag() ) rescale_probability(Fcst_sd.data); - // Rescale probabilites from [0, 100] to [0, 1] + // Rescale probabilites from [0, 100] to [0, 1] if ( engine.conf_info.Obs->var_info->p_flag() ) rescale_probability(Obs_sd.data); - // Print a warning if the valid times do not match + // Print a warning if the valid times do not match if(Fcst_sd.data.valid() != Obs_sd.data.valid()) { @@ -290,7 +350,7 @@ 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 && @@ -314,23 +374,23 @@ void ModeExecutive::setup_fcst_obs_data() << engine.conf_info.Obs->var_info->level_attr() << "\n"; - // Mask out the missing data between fields + // 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 + // 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 + // 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 + // 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); @@ -342,81 +402,304 @@ void ModeExecutive::setup_fcst_obs_data() 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 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; + return; } - /////////////////////////////////////////////////////////////////////// - -void ModeExecutive::do_conv_thresh(const int r_index, const int t_index) +void ModeExecutive::setup_fcst_obs_data(const MultiVarData &mvd) { + double fmin, omin, fmax, omax; -ModeConfInfo & conf = engine.conf_info; + bool simple = true; + Fcst_sd = *(mvd.fcst_shapedata_ptr(simple)); + Fcst_sd.debug_examine(); + Obs_sd = *(mvd.obs_shapedata_ptr(simple)); + Obs_sd.debug_examine(); + grid = *(mvd._grid); -static int local_r_index = -1; + // 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 + + // Store the grid + + engine.set_grid(&grid); + + // regridding of inputs is not needed in the second pass, as regridded data outputs + // are stored to input mvd + + // Rescale probabilites from [0, 100] to [0, 1] also not neede in the second pass + + // 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"; + } + + // 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() -> " + << "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"; + + // 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 + // do this in the 2nd pass as data has now been masked to within superobjects -R_index = r_index; -T_index = t_index; + 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; -conf.set_conv_radius_by_index (R_index); -conf.set_conv_thresh_by_index (T_index); + // 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(); -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); + // store the input data level + flevel = engine.conf_info.Fcst->var_info->level_name(); + olevel = engine.conf_info.Obs->var_info->level_name(); // - // Set up the engine with these raw fields + // done // -mlog << Debug(2) - << "Identifying objects in the forecast and observation fields...\n"; + return; + +} + + +/////////////////////////////////////////////////////////////////////// + +void ModeExecutive::setup_fcst_obs_data(ShapeData &f_super, ShapeData &o_super, + const Grid &igrid) +{ + double fmin, omin, fmax, omax; + + bool simple = true; + Fcst_sd = f_super; + Fcst_sd.debug_examine(); + Obs_sd = o_super; + Obs_sd.debug_examine(); + grid = igrid; + + // 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 -if ( r_index != local_r_index ) { // need to do convolution + // Store the grid - engine.set(Fcst_sd, Obs_sd); + engine.set_grid(&grid); + + // regridding of inputs is not needed in the second pass, as regridded data outputs + // are stored to input mvd + + // Rescale probabilites from [0, 100] to [0, 1] also not neede in the second pass -} else { // don't need to do convolution + // 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"; + } - engine.set_no_conv(Fcst_sd, Obs_sd); + // 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() -> " + << "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"; + + // 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 + // 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; + + 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 + // 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); + + // + // done + // + + return; } + + +/////////////////////////////////////////////////////////////////////// + + +void ModeExecutive::do_conv_thresh(const int r_index, const int t_index, + bool isMultivarPass1Merge, + bool isMultivarPass2, + bool isMultivarSuper) + +{ + + ModeConfInfo & conf = engine.conf_info; + + 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) { + SingleThresh s("ne-9999"); + conf.set_conv_thresh(s); + conf.set_conv_radius(0.0); + } else { + 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); + + // + // Set up the engine with these raw fields + // + + mlog << Debug(2) + << "Identifying objects in the forecast and observation fields...\n"; + + if ( r_index != local_r_index ) { // need to do convolution + + if (isMultivarPass2) { + engine.set_only_split(Fcst_sd, Obs_sd); + } else if (isMultivarSuper) { + engine.set_only_split(Fcst_sd, Obs_sd); + //engine.set_super(Fcst_sd, Obs_sd); + } else { + 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) { + engine.set_only_split(Fcst_sd, Obs_sd); + //engine.set_super(Fcst_sd, Obs_sd); + } else { + engine.set_no_conv(Fcst_sd, Obs_sd); + } + } // // Compute the contingency table statistics for the fields, if needed // -if ( conf.ct_stats_flag ) compute_ct_stats(); + if ( conf.ct_stats_flag ) compute_ct_stats(); // // done // -local_r_index = r_index; + local_r_index = r_index; -return; + return; } - /////////////////////////////////////////////////////////////////////// +void ModeExecutive::clear_internal_r_index() +{ + local_r_index = -1; +} -void ModeExecutive::do_match_merge() +/////////////////////////////////////////////////////////////////////// +void ModeExecutive::do_merging() { - mlog << Debug(2) << "Identified: " << engine.n_fcst << " forecast objects " << "and " << engine.n_obs << " observation objects.\n"; @@ -443,16 +726,83 @@ void ModeExecutive::do_match_merge() << "Remaining: " << engine.n_fcst << " forecast objects " << "and " << engine.n_obs << " observation objects.\n"; +} + +/////////////////////////////////////////////////////////////////////// + +void ModeExecutive::do_merging(ShapeData &f_merge, ShapeData &o_merge, + bool isMultivarSuper) +{ + if (isMultivarSuper) { + // set the merge flag and merge_thresh appropriately + ModeConfInfo & conf = engine.conf_info; + SingleThresh s("ne-9999"); + conf.set_fcst_merge_flag(MergeType_Thresh); + conf.set_fcst_merge_thresh(s); + conf.set_obs_merge_flag(MergeType_Thresh); + conf.set_obs_merge_thresh(s); + } + + + mlog << Debug(2) + << "Identified: " << engine.n_fcst << " forecast objects " + << "and " << engine.n_obs << " observation objects.\n"; + mlog << Debug(2) - << "Performing matching (" - << matchtype_to_string(engine.conf_info.match_flag) - << ") between the forecast and observation fields.\n"; + << "Performing merging (" + << mergetype_to_string(engine.conf_info.Fcst->merge_flag) + << ") in the forecast field.\n"; + + // Do the forecast merging + + engine.do_fcst_merging(default_config_file.c_str(), merge_config_file.c_str(), + f_merge); + + mlog << Debug(2) + << "Performing merging (" + << mergetype_to_string(engine.conf_info.Obs->merge_flag) + << ") in the observation field.\n"; + + // Do the observation merging + + engine.do_obs_merging(default_config_file.c_str(), merge_config_file.c_str(), + o_merge); + + mlog << Debug(2) + << "Remaining: " << engine.n_fcst << " forecast objects " + << "and " << engine.n_obs << " observation objects.\n"; + +} + +/////////////////////////////////////////////////////////////////////// + + +void ModeExecutive::do_match_merge(ShapeData &f_merge, ShapeData &o_merge, bool isMultivarSuper) + +{ + do_merging(f_merge, o_merge, isMultivarSuper); // Do the matching of objects between fields engine.do_matching(); -return; + return; + +} + +/////////////////////////////////////////////////////////////////////// + + +void ModeExecutive::do_match_merge() + +{ + do_merging(); + + // Do the matching of objects between fields + + engine.do_matching(); + + return; } @@ -515,21 +865,84 @@ void ModeExecutive::process_masks(ShapeData & fcst_sd, ShapeData & obs_sd) /////////////////////////////////////////////////////////////////////// -void ModeExecutive::process_output() - +void ModeExecutive::set_raw_to_full(float *fcst_raw_data, + float *obs_raw_data, + int nx, int ny, + double idata_min, double idata_max) { + engine.fcst_raw->data.set_all(fcst_raw_data, nx, ny); + engine.obs_raw->data.set_all(obs_raw_data, nx, ny); + data_min = idata_min; + data_max = idata_max; +} + +/////////////////////////////////////////////////////////////////////// + +void ModeExecutive::process_output(bool isMultivar, bool isMultivarSuper, + const MultiVarData *mvd) +{ + // store to class member so don't have to pass it around + isMultivarOutput = isMultivar; + isMultivarSuperOutput = isMultivarSuper; + + if (isMultivar) { + + // get the magic strings, which will be used in file naming + 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(), '/', '_'); + + // replace (*,*) with '_all_all_' + replaceAll(fcst_magic_string, "*", "all"); + replaceAll(obs_magic_string, "*", "all"); + replaceAll(fcst_magic_string, ",", "_"); + replaceAll(obs_magic_string, ",", "_"); + replaceAll(fcst_magic_string, "(", "_"); + replaceAll(obs_magic_string, "(", "_"); + replaceAll(fcst_magic_string, ")", ""); + replaceAll(obs_magic_string, ")", ""); + + } else if (isMultivarSuper) { + + // use the configured multivar name and level + fcst_magic_string = engine.conf_info.fcst_multivar_name.string() + "_" + engine.conf_info.fcst_multivar_level.string(); + obs_magic_string = engine.conf_info.obs_multivar_name.string() + "_" + engine.conf_info.obs_multivar_level.string(); + + } else { + + // just in case make these empty + fcst_magic_string = ""; + obs_magic_string = ""; + + } + // Create output stats files and plots -write_obj_stats(); + write_obj_stats(); -if ( engine.conf_info.ct_stats_flag ) write_ct_stats(); + if ( engine.conf_info.ct_stats_flag ) write_ct_stats(); -write_obj_netcdf(engine.conf_info.nc_info); + 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); + } else { + mlog << Error << "\nprocess_output() -> " + << "no multivar data when data is expected\n\n"; + exit(1); + } + } + write_obj_netcdf(engine.conf_info.nc_info); -if ( engine.conf_info.ps_plot_flag ) plot_engine(); + if ( engine.conf_info.ps_plot_flag ) plot_engine(); -return; + return; } @@ -590,23 +1003,23 @@ void ModeExecutive::plot_engine() { -ModePsFile plot; -ConcatString ps_file; + ModePsFile plot; + ConcatString ps_file; -plot.set(engine, grid, data_min, data_max); + plot.set(engine, grid, data_min, data_max); -build_outfile_name(".ps", ps_file); + build_outfile_name(".ps", ps_file); -// -// List the image file as it is being created -// -mlog << Debug(1) << "Creating postscript file: " << ps_file << "\n"; + // + // List the image file as it is being created + // + mlog << Debug(1) << "Creating postscript file: " << ps_file << "\n"; -plot.open(ps_file.c_str()); + plot.open(ps_file.c_str()); -plot.make_plot(); + plot.make_plot(isMultivarSuperOutput); -return; + return; } @@ -618,31 +1031,41 @@ void ModeExecutive::build_outfile_prefix(ConcatString &str) { // - // Create leading part of output file name + // Create leading part of output file name including out_dir // - // Append the output directory and program name -str << cs_erase - << out_dir << "/" << program_name; + if (isMultivarOutput || isMultivarSuperOutput) { + + // Append the program name and magic strings + + str << cs_erase << out_dir << "/" << program_name + << "_Fcst_" << fcst_magic_string + << "_Obs_" << obs_magic_string; + } else { + // Append the program name + + str << cs_erase << out_dir << "/" << program_name; + } + // Append the output prefix, if defined -if(engine.conf_info.output_prefix.nonempty()) - str << "_" << engine.conf_info.output_prefix; + if(engine.conf_info.output_prefix.nonempty()) + str << "_" << engine.conf_info.output_prefix; // Append the timing information -str << "_" - << sec_to_hhmmss(engine.fcst_raw->data.lead()) << "L_" - << unix_to_yyyymmdd_hhmmss(engine.fcst_raw->data.valid()) << "V_" - << sec_to_hhmmss(engine.fcst_raw->data.accum()) << "A"; + str << "_" + << sec_to_hhmmss(engine.fcst_raw->data.lead()) << "L_" + << unix_to_yyyymmdd_hhmmss(engine.fcst_raw->data.valid()) << "V_" + << sec_to_hhmmss(engine.fcst_raw->data.accum()) << "A"; // // done // -return; + return; } @@ -654,13 +1077,13 @@ void ModeExecutive::build_simple_outfile_name(const char *suffix, ConcatString & { -build_outfile_prefix(str); + build_outfile_prefix(str); // Append the suffix -str << suffix; + str << suffix; -return; + return; } @@ -672,32 +1095,32 @@ void ModeExecutive::build_outfile_name(const char *suffix, ConcatString &str) { -if ( engine.conf_info.n_runs() == 1 ) { + if ( engine.conf_info.n_runs() == 1 ) { - build_simple_outfile_name(suffix, str); + build_simple_outfile_name(suffix, str); + + return; - return; - -} + } -build_outfile_prefix(str); + build_outfile_prefix(str); // // append the radius and threshold indices // -char junk[256]; + char junk[256]; -snprintf(junk, sizeof(junk), "R%d_T%d", R_index + 1, T_index + 1); + snprintf(junk, sizeof(junk), "R%d_T%d", R_index + 1, T_index + 1); -str << '_' << junk; + str << '_' << junk; // Append the suffix -str << suffix; + str << suffix; -return; + return; } @@ -738,7 +1161,8 @@ void ModeExecutive::write_obj_stats() // // Write the output statistics to an AsciiTable object // - write_engine_stats(engine, grid, obj_at); + write_engine_stats(engine, grid, obj_at, isMultivarSuperOutput, + isMultivarOutput); // // Write the AsciiTable object to the output file @@ -814,6 +1238,47 @@ void ModeExecutive::write_obj_stats() return; } +////////////////////////////////////////////////////////////////////// + + +MultiVarData *ModeExecutive::get_multivar_data() +{ + 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); + + return mvd; +} + +/////////////////////////////////////////////////////////////////////// + + +void ModeExecutive::addMultivarMergePass1(MultiVarData *mvd) +{ + 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); +} /////////////////////////////////////////////////////////////////////// @@ -822,7 +1287,7 @@ void ModeExecutive::write_obj_netcdf(const ModeNcOutInfo & info) { -if ( info.all_false() ) return; + if ( info.all_false() ) return; int n, x, y; ConcatString out_file; @@ -897,7 +1362,7 @@ if ( info.all_false() ) return; write_netcdf_proj(f_out, grid, lat_dim, lon_dim); fcst_thresh_dim = add_dim(f_out, "fcst_thresh_length", fcst_thresh.length()); - obs_thresh_dim = add_dim(f_out, "obs_thresh_length", obs_thresh.length()); + obs_thresh_dim = add_dim(f_out, "obs_thresh_length", obs_thresh.length()); // Add the lat/lon variables if ( info.do_latlon ) write_netcdf_latlon(f_out, &lat_dim, &lon_dim, grid); @@ -948,50 +1413,60 @@ if ( info.all_false() ) return; } fcst_radius_var = add_var(f_out, (string)"fcst_conv_radius", ncInt, deflate_level); - obs_radius_var = add_var(f_out, (string) "obs_conv_radius", ncInt, deflate_level); + obs_radius_var = add_var(f_out, (string) "obs_conv_radius", ncInt, deflate_level); fcst_thresh_var = add_var(f_out, "fcst_conv_threshold", ncChar, fcst_thresh_dim, deflate_level); - obs_thresh_var = add_var(f_out, "obs_conv_threshold", ncChar, obs_thresh_dim, deflate_level); + obs_thresh_var = add_var(f_out, "obs_conv_threshold", ncChar, obs_thresh_dim, deflate_level); // // write the radius and threshold values // 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) ) { + || !put_nc_data(&obs_radius_var, &engine.conf_info.Obs->conv_radius) ) { - mlog << Error - << "write_obj_netcdf() -> " - << "error writing fcst/obs convolution radii\n\n"; + mlog << Error + << "write_obj_netcdf() -> " + << "error writing fcst/obs convolution radii\n\n"; - exit(1); + exit(1); } if ( ! put_nc_data(&fcst_thresh_var, fcst_thresh.c_str()) - || ! put_nc_data(& obs_thresh_var, obs_thresh.c_str()) ) { + || ! put_nc_data(& obs_thresh_var, obs_thresh.c_str()) ) { - mlog << Error - << "write_obj_netcdf() -> " - << "error writing fcst/obs thresholds\n\n"; + mlog << Error + << "write_obj_netcdf() -> " + << "error writing fcst/obs thresholds\n\n"; - exit(1); + exit(1); } - // - // fcst and obs values for variable, level and units - // + // + // fcst and obs values for variable, level and units + // - nc_add_string(f_out, engine.conf_info.Fcst->var_info->name_attr().c_str(), "fcst_variable", "fcst_variable_length"); - nc_add_string(f_out, engine.conf_info.Obs->var_info->name_attr().c_str(), "obs_variable", "obs_variable_length"); + if (isMultivarSuperOutput) { + nc_add_string(f_out, engine.conf_info.fcst_multivar_name.c_str(), "fcst_variable", "fcst_variable_length"); + nc_add_string(f_out, engine.conf_info.obs_multivar_name.c_str(), "obs_variable", "obs_variable_length"); - nc_add_string(f_out, engine.conf_info.Fcst->var_info->level_attr().c_str(), "fcst_level", "fcst_level_length"); - nc_add_string(f_out, engine.conf_info.Obs->var_info->level_attr().c_str(), "obs_level", "obs_level_length"); + nc_add_string(f_out, engine.conf_info.fcst_multivar_level.c_str(), "fcst_level", "fcst_level_length"); + nc_add_string(f_out, engine.conf_info.obs_multivar_level.c_str(), "obs_level", "obs_level_length"); - nc_add_string(f_out, engine.conf_info.Fcst->var_info->units_attr().c_str(), "fcst_units", "fcst_units_length"); - nc_add_string(f_out, engine.conf_info.Obs->var_info->units_attr().c_str(), "obs_units", "obs_units_length"); + nc_add_string(f_out, "NA", "fcst_units", "fcst_units_length"); + nc_add_string(f_out, "NA", "obs_units", "obs_units_length"); + } else { + nc_add_string(f_out, engine.conf_info.Fcst->var_info->name_attr().c_str(), "fcst_variable", "fcst_variable_length"); + nc_add_string(f_out, engine.conf_info.Obs->var_info->name_attr().c_str(), "obs_variable", "obs_variable_length"); + nc_add_string(f_out, engine.conf_info.Fcst->var_info->level_attr().c_str(), "fcst_level", "fcst_level_length"); + nc_add_string(f_out, engine.conf_info.Obs->var_info->level_attr().c_str(), "obs_level", "obs_level_length"); + + nc_add_string(f_out, engine.conf_info.Fcst->var_info->units_attr().c_str(), "fcst_units", "fcst_units_length"); + nc_add_string(f_out, engine.conf_info.Obs->var_info->units_attr().c_str(), "obs_units", "obs_units_length"); + } // Add forecast variable attributes @@ -1067,81 +1542,81 @@ if ( info.all_false() ) return; n = DefaultTO.two_to_one(grid.nx(), grid.ny(), x, y); - // - // Get raw values and object ID's for each grid box - // Extra nullptr checks to satisfy Fortify + // + // Get raw values and object ID's for each grid box + // Extra nullptr checks to satisfy Fortify if ( info.do_raw && - fcst_raw_data != nullptr && obs_raw_data != nullptr && - engine.fcst_raw != nullptr && engine.obs_raw != nullptr ) { + fcst_raw_data != nullptr && obs_raw_data != nullptr && + engine.fcst_raw != nullptr && engine.obs_raw != nullptr ) { - fcst_raw_data[n] = engine.fcst_raw->data (x, y); - obs_raw_data[n] = engine.obs_raw->data (x, y); + fcst_raw_data[n] = engine.fcst_raw->data (x, y); + obs_raw_data[n] = engine.obs_raw->data (x, y); } if(engine.fcst_split->is_nonzero(x, y) ) { - if ( info.do_object_raw && fcst_obj_raw_data != nullptr && engine.fcst_raw != nullptr ) { - fcst_obj_raw_data[n] = engine.fcst_raw->data(x, y); - } - if ( info.do_object_id && fcst_obj_data != nullptr && engine.fcst_split != nullptr ) { - fcst_obj_data[n] = nint(engine.fcst_split->data(x, y)); - } + if ( info.do_object_raw && fcst_obj_raw_data != nullptr && engine.fcst_raw != nullptr ) { + fcst_obj_raw_data[n] = engine.fcst_raw->data(x, y); + } + if ( info.do_object_id && fcst_obj_data != nullptr && engine.fcst_split != nullptr ) { + fcst_obj_data[n] = nint(engine.fcst_split->data(x, y)); + } } else { if ( info.do_object_raw && fcst_obj_raw_data != nullptr ) { - fcst_obj_raw_data[n] = bad_data_float; - } + fcst_obj_raw_data[n] = bad_data_float; + } if ( info.do_object_id && fcst_obj_data != nullptr ) { - fcst_obj_data[n] = bad_data_int; - } + fcst_obj_data[n] = bad_data_int; + } } if(engine.obs_split->is_nonzero(x, y) ) { - if ( info.do_object_raw && obs_obj_raw_data != nullptr ) { - obs_obj_raw_data[n] = engine.obs_raw->data(x, y); - } - if ( info.do_object_id && obs_obj_data != nullptr ) { - obs_obj_data[n] = nint(engine.obs_split->data(x, y)); - } + if ( info.do_object_raw && obs_obj_raw_data != nullptr ) { + obs_obj_raw_data[n] = engine.obs_raw->data(x, y); + } + if ( info.do_object_id && obs_obj_data != nullptr ) { + obs_obj_data[n] = nint(engine.obs_split->data(x, y)); + } } else { - if ( info.do_object_raw && obs_obj_raw_data != nullptr) { - obs_obj_raw_data[n] = bad_data_float; - } - if ( info.do_object_id && obs_obj_data != nullptr ) { - obs_obj_data[n] = bad_data_int; - } + if ( info.do_object_raw && obs_obj_raw_data != nullptr) { + obs_obj_raw_data[n] = bad_data_float; + } + if ( info.do_object_id && obs_obj_data != nullptr ) { + obs_obj_data[n] = bad_data_int; + } } - // - // Get cluster object ID's for each grid box - // + // + // Get cluster object ID's for each grid box + // if ( info.do_cluster_id && fcst_clus_data != nullptr && obs_clus_data != nullptr) { - // Write the index of the cluster object + // Write the index of the cluster object if ( engine.fcst_clus_split->data(x, y) > 0 ) { fcst_clus_data[n] = nint(engine.fcst_clus_split->data(x, y)); } - // Write a value of 0 for unmatched simple objects + // Write a value of 0 for unmatched simple objects else if(engine.fcst_split->data(x, y) > 0) { fcst_clus_data[n] = unmatched_id; } - // Otherwise, write bad data + // Otherwise, write bad data else { fcst_clus_data[n] = bad_data_int; } - // Write the index of the cluster object + // Write the index of the cluster object if(engine.obs_clus_split->data(x, y) > 0) { obs_clus_data[n] = nint(engine.obs_clus_split->data(x, y)); } - // Write a value of 0 for unmatched simple objects + // Write a value of 0 for unmatched simple objects else if(engine.obs_split->data(x, y) > 0) { obs_clus_data[n] = unmatched_id; } - // Otherwise, write bad data + // Otherwise, write bad data else { obs_clus_data[n] = bad_data_int; } @@ -1180,9 +1655,9 @@ if ( info.all_false() ) return; } - // - // Write the forecast and observation object ID variables - // + // + // Write the forecast and observation object ID variables + // if ( info.do_object_id ) { @@ -1196,9 +1671,9 @@ if ( info.all_false() ) return; } - // - // Write the forecast and observation cluster object ID variables - // + // + // Write the forecast and observation cluster object ID variables + // if ( info.do_cluster_id ) { @@ -1226,9 +1701,9 @@ if ( info.all_false() ) return; if (obs_obj_data) { delete [] obs_obj_data; obs_obj_data = (int *) 0; } if (obs_clus_data) { delete [] obs_clus_data; obs_clus_data = (int *) 0; } - // - // Write out the values of the vertices of the polylines. - // + // + // Write out the values of the vertices of the polylines. + // if ( info.do_polylines ) write_poly_netcdf(f_out); @@ -1339,56 +1814,56 @@ void ModeExecutive::write_poly_netcdf(NcFile *f_out, ObjPolyType poly_type) // and set up strings switch(poly_type) { - case FcstSimpBdyPoly: - n_poly = engine.n_fcst; - field_name = "fcst"; - field_long = "Forecast"; - poly_name = "simp_bdy"; - poly_long = "Simple Boundary"; - break; - - case ObsSimpBdyPoly: - n_poly = engine.n_obs; - field_name = "obs"; - field_long = "Observation"; - poly_name = "simp_bdy"; - poly_long = "Simple Boundary"; - break; - - case FcstSimpHullPoly: - n_poly = engine.n_fcst; - field_name = "fcst"; - field_long = "Forecast"; - poly_name = "simp_hull"; - poly_long = "Simple Convex Hull"; - break; - - case ObsSimpHullPoly: - n_poly = engine.n_obs; - field_name = "obs"; - field_long = "Observation"; - poly_name = "simp_hull"; - poly_long = "Simple Convex Hull"; - break; - - case FcstClusHullPoly: - n_poly = engine.n_clus; - field_name = "fcst"; - field_long = "Forecast"; - poly_name = "clus_hull"; - poly_long = "Cluster Convex Hull"; - break; - - case ObsClusHullPoly: - n_poly = engine.n_clus; - field_name = "obs"; - field_long = "Observation"; - poly_name = "clus_hull"; - poly_long = "Cluster Convex Hull"; - break; - - default: - return; + case FcstSimpBdyPoly: + n_poly = engine.n_fcst; + field_name = "fcst"; + field_long = "Forecast"; + poly_name = "simp_bdy"; + poly_long = "Simple Boundary"; + break; + + case ObsSimpBdyPoly: + n_poly = engine.n_obs; + field_name = "obs"; + field_long = "Observation"; + poly_name = "simp_bdy"; + poly_long = "Simple Boundary"; + break; + + case FcstSimpHullPoly: + n_poly = engine.n_fcst; + field_name = "fcst"; + field_long = "Forecast"; + poly_name = "simp_hull"; + poly_long = "Simple Convex Hull"; + break; + + case ObsSimpHullPoly: + n_poly = engine.n_obs; + field_name = "obs"; + field_long = "Observation"; + poly_name = "simp_hull"; + poly_long = "Simple Convex Hull"; + break; + + case FcstClusHullPoly: + n_poly = engine.n_clus; + field_name = "fcst"; + field_long = "Forecast"; + poly_name = "clus_hull"; + poly_long = "Cluster Convex Hull"; + break; + + case ObsClusHullPoly: + n_poly = engine.n_clus; + field_name = "obs"; + field_long = "Observation"; + poly_name = "clus_hull"; + poly_long = "Cluster Convex Hull"; + break; + + default: + return; } // Setup dimension name strings @@ -1423,32 +1898,32 @@ void ModeExecutive::write_poly_netcdf(NcFile *f_out, ObjPolyType poly_type) switch(poly_type) { - case FcstSimpBdyPoly: - poly[i] = &engine.fcst_single[i].boundary[0]; - break; + case FcstSimpBdyPoly: + poly[i] = &engine.fcst_single[i].boundary[0]; + break; - case ObsSimpBdyPoly: - poly[i] = &engine.obs_single[i].boundary[0]; - break; + case ObsSimpBdyPoly: + poly[i] = &engine.obs_single[i].boundary[0]; + break; - case FcstSimpHullPoly: - poly[i] = &engine.fcst_single[i].convex_hull; - break; + case FcstSimpHullPoly: + poly[i] = &engine.fcst_single[i].convex_hull; + break; - case ObsSimpHullPoly: - poly[i] = &engine.obs_single[i].convex_hull; - break; + case ObsSimpHullPoly: + poly[i] = &engine.obs_single[i].convex_hull; + break; - case FcstClusHullPoly: - poly[i] = &engine.fcst_cluster[i].convex_hull; - break; + case FcstClusHullPoly: + poly[i] = &engine.fcst_cluster[i].convex_hull; + break; - case ObsClusHullPoly: - poly[i] = &engine.obs_cluster[i].convex_hull; - break; + case ObsClusHullPoly: + poly[i] = &engine.obs_cluster[i].convex_hull; + break; - default: - break; + default: + break; } } @@ -1612,7 +2087,7 @@ void ModeExecutive::write_ct_stats() cts_at.set_size(3, i); // Set table size justify_mode_cols(cts_at); // Justify columns cts_at.set_precision( // Set the precision - engine.conf_info.conf.output_precision()); + engine.conf_info.conf.output_precision()); cts_at.set_bad_data_value(bad_data_double); // Set the bad data value cts_at.set_bad_data_str(na_str); // Set the bad data string cts_at.set_delete_trailing_blank_rows(1); // No trailing blank rows @@ -1628,7 +2103,7 @@ void ModeExecutive::write_ct_stats() // Write out the MODE contingecy table header columns // for(i=0; i #include - -#include "string_array.h" - +#include "mode_frontend.h" #include "mode_usage.h" -#include "mode_exec.h" #ifdef WITH_PYTHON #include "global_python.h" #endif +extern const char * const program_name; + +static ModeExecutive *mode_exec = 0; +static int compress_level = -1; + -/////////////////////////////////////////////////////////////////////// -// -// Create output files using the following naming convention: -// -// mode_YYYYMMDDI_FHH_HHA.ps/.txt -// -// Where I indicates initilization time, L indicates lead time, -// and A indicates accumulation time. -// /////////////////////////////////////////////////////////////////////// -extern const char * const program_name; +ModeFrontEnd::ModeFrontEnd() : + default_out_dir(".") +{ + mode_exec = 0; + compress_level = -1; +} + -static ModeExecutive * mode_exec = 0; +/////////////////////////////////////////////////////////////////////// +ModeFrontEnd::~ModeFrontEnd() +{ + if ( mode_exec ) { + delete mode_exec; mode_exec = 0; + } +} + /////////////////////////////////////////////////////////////////////// +int ModeFrontEnd::run(const StringArray & Argv, Processing_t ptype, int field_index, int n_files) + +{ -static const char * default_out_dir = "."; + 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; -static int compress_level = -1; + // + // Process the command line arguments + // -static int field_index = -1; + process_command_line(Argv, false); + mode_exec->init(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 (Note double reads for pass 1 merge and pass 1 not desired) + // + mode_exec->setup_fcst_obs_data(); -static void do_quilt (); -static void do_straight (); + // + // mode algorithm + // + if ( conf.quilt ) { -static void process_command_line(const StringArray &); + do_quilt(ptype); + } else { -static void set_config_merge_file (const StringArray &); -static void set_outdir (const StringArray &); -static void set_logfile (const StringArray &); -static void set_verbosity (const StringArray &); -static void set_compress (const StringArray &); + do_straight(ptype); -static void set_field_index (const StringArray &); // undocumented + } + // + // done + // + +#ifdef WITH_PYTHON + GP.finalize(); +#endif + return (0); +} /////////////////////////////////////////////////////////////////////// +int ModeFrontEnd::run_multivar_pass2(const StringArray & Argv, const MultiVarData &mvd, + bool has_union, + ShapeData &f_merge, ShapeData &o_merge, int field_index) +{ + Processing_t ptype = MULTIVAR_PASS2; + mlog << Debug(1) << "Running mode front end " << stype(ptype) << "\n"; + //Argv.dump(cout, 0); -int mode_frontend(const StringArray & Argv) + if ( mode_exec ) { delete mode_exec; mode_exec = 0; } -{ + mode_exec = new ModeExecutive; + compress_level = -1; // // Process the command line arguments // -mode_exec = new ModeExecutive; + process_command_line(Argv, true); + mode_exec->init_multivar(mvd._ftype, mvd._otype); + + 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); + + // for multivar pass2, 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() -> " + << "Logic includes union '||' along with 'merge_flag=THRESH' " + << ". This can lead to bad results\n\n"; + } + + // + // set up data access using inputs + // + mode_exec->setup_fcst_obs_data(mvd); + + // + // run the mode algorithm + // + + if ( conf.quilt ) { + + do_quilt(ptype); -process_command_line(Argv); + } else { + do_straight(ptype, mvd, f_merge, o_merge); + } // - // Process the forecast and observation files + // done // -ModeConfInfo & conf = mode_exec->engine.conf_info; +#ifdef WITH_PYTHON + GP.finalize(); +#endif + return (0); +} + -if ( field_index >= 0 ) conf.set_field_index(field_index); +/////////////////////////////////////////////////////////////////////// -mode_exec->setup_fcst_obs_data(); +int ModeFrontEnd::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) +{ + Processing_t ptype = MULTIVAR_SUPER; + mlog << Debug(1) << "Running mode front end " << stype(ptype) << "\n"; + //Argv.dump(cout, 0); -if (compress_level >= 0) conf.nc_info.set_compress_level(compress_level); + if ( mode_exec ) { delete mode_exec; mode_exec = 0; } + mode_exec = new ModeExecutive; + compress_level = -1; -if ( conf.quilt ) { + // + // Process the command line arguments + // - do_quilt(); + process_command_line(Argv, true); + mode_exec->init_multivar(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() -> " + << "Logic includes union '||' along with 'merge_flag=THRESH' " + << ". This can lead to bad results\n\n"; + } + + // + // set up data access using inputs + // + mode_exec->setup_fcst_obs_data(f_super, o_super, grid); -} else { + // + // run the mode algorithm + // - do_straight(); + if ( conf.quilt ) { -} + do_quilt(ptype); + + } else { -// mode_exec.clear(); + do_straight(ptype, f_merge, o_merge); + + } // // done @@ -130,10 +244,75 @@ if ( conf.quilt ) { #ifdef WITH_PYTHON GP.finalize(); #endif + return (0); +} + +/////////////////////////////////////////////////////////////////////// + + +void ModeFrontEnd::do_straight(Processing_t ptype, const MultiVarData &mvd, + ShapeData &f_merge, ShapeData &o_merge) + +{ + if (ptype != MULTIVAR_PASS2) { + + mlog << Error + << "\n\n " + << program_name + << ": called MULTIVAR_PASS2 method with " + << stype(ptype) << "\n\n"; + exit ( 1 ); -if ( mode_exec ) { delete mode_exec; mode_exec = 0; } + } + + 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) { + mlog << Error + << "\n\n " + << program_name + << ": multiple convolution radii and thresholds not implemented in multivar mode\n\n"; + + exit ( 1 ); + } + + + + int index; + + mode_exec->clear_internal_r_index(); -return ( 0 ); + 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->process_output(true, false, &mvd); + } + + mode_exec->clear_internal_r_index(); + + // + // done + // + + return; } @@ -141,44 +320,60 @@ return ( 0 ); /////////////////////////////////////////////////////////////////////// -void do_straight() +void ModeFrontEnd::do_straight(Processing_t ptype) { -const ModeConfInfo & conf = mode_exec->engine.conf_info; + const ModeConfInfo & conf = mode_exec->engine.conf_info; -const int NCT = conf.n_conv_threshs(); -const int NCR = conf.n_conv_radii(); + const int NCT = conf.n_conv_threshs(); + const int NCR = conf.n_conv_radii(); -if ( NCT != NCR ) { + if ( NCT != NCR ) { - mlog << Error - << "\n\n " - << program_name - << ": all convolution radius and threshold arrays must have the same number of elements!\n\n"; + mlog << Error + << "\n\n " + << program_name + << ": all convolution radius and threshold arrays must have the same number of elements!\n\n"; - exit ( 1 ); + exit ( 1 ); -} + } -int index; + if (NCT > 1 && ptype != SINGLE_VAR) { + mlog << Error + << "\n\n " + << program_name + << ": multiple convolution radii and thresholds not implemented in multivar mode\n\n"; -for (index=0; indexdo_conv_thresh(index, index); + int index; - mode_exec->do_match_merge(); + mode_exec->clear_internal_r_index(); - mode_exec->process_output(); + for (index=0; indexdo_conv_thresh(index, index, ptype == MULTIVAR_PASS1_MERGE, + ptype == MULTIVAR_PASS2, ptype == MULTIVAR_SUPER); + if (ptype == SINGLE_VAR) { + + mode_exec->do_match_merge(); + mode_exec->process_output(false, false); + } + } + mode_exec->clear_internal_r_index(); + // // done // -return; + return; } @@ -186,32 +381,66 @@ return; /////////////////////////////////////////////////////////////////////// -void do_quilt() +void ModeFrontEnd::do_straight(Processing_t ptype, + ShapeData &f_merge, ShapeData &o_merge) { -int t_index, r_index; // indices into the convolution threshold and radius arrays + const ModeConfInfo & conf = mode_exec->engine.conf_info; + const int NCT = conf.n_conv_threshs(); + const int NCR = conf.n_conv_radii(); -for (r_index=0; r_index<(mode_exec->n_conv_radii()); ++r_index) { + if ( NCT != NCR ) { - for (t_index=0; t_index<(mode_exec->n_conv_threshs()); ++t_index) { + mlog << Error + << "\n\n " + << program_name + << ": all convolution radius and threshold arrays must have the same number of elements!\n\n"; - mode_exec->do_conv_thresh(r_index, t_index); + exit ( 1 ); - mode_exec->do_match_merge(); + } - mode_exec->process_output(); + 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; + 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) { + + mode_exec->do_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->clear_internal_r_index(); + // // done // -return; + return; } @@ -219,75 +448,181 @@ return; /////////////////////////////////////////////////////////////////////// -void process_command_line(const StringArray & argv) +void ModeFrontEnd::do_quilt(Processing_t ptype) + +{ + if (ptype != SINGLE_VAR) { + mlog << Error + << program_name << ": quilting not yet implemented for multivar mode \n\n"; + + exit ( 1 ); + } + + + int t_index, r_index; // indices into the convolution threshold and radius arrays + + + mode_exec->clear_internal_r_index(); + + for (r_index=0; r_index<(mode_exec->n_conv_radii()); ++r_index) { + + for (t_index=0; t_index<(mode_exec->n_conv_threshs()); ++t_index) { + + mode_exec->do_conv_thresh(r_index, t_index); + + mode_exec->do_match_merge(); + + if (ptype == SINGLE_VAR) { + mode_exec->process_output(); + } + } + } + + mode_exec->clear_internal_r_index(); + + // + // done + // + + return; + +} + +/////////////////////////////////////////////////////////////////////// + +MultiVarData *ModeFrontEnd::get_multivar_data() {return mode_exec->get_multivar_data(); } + +/////////////////////////////////////////////////////////////////////// + +void ModeFrontEnd::addMultivarMergePass1(MultiVarData *mvdi) { + return mode_exec->addMultivarMergePass1(mvdi); +} +/////////////////////////////////////////////////////////////////////// + +void ModeFrontEnd::process_command_line(const StringArray & argv, bool ismultivar) +{ 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 + // + // 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 + // + // 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(); + + if (ismultivar) { // - // add for mode multivar ... undocumented + // Check for error. There should be 1 argument left: + // config filename // + if(cline.n() != 1) singlevar_usage(); // wrong need multivar usage - cline.add(set_field_index, "-field_index", 1); - - // Parse the command line - cline.parse(); + // + // Store the input forecast and observation file names, placeholders + // + mode_exec->fcst_file = "not set"; + mode_exec->obs_file = "not set"; + mode_exec->match_config_file = cline[0]; - // Check for error. There should be three arguments left: - // forecast, observation, and config filenames - if(cline.n() != 3) singlevar_usage(); + } else { + // + // Check for error. There should be three arguments left: + // forecast, observation, and config filenames + // + if(cline.n() != 3) singlevar_usage(); - // Store the input forecast and observation file names - mode_exec->fcst_file = cline[0]; - mode_exec->obs_file = cline[1]; - mode_exec->match_config_file = cline[2]; + // + // Store the input forecast and observation file names + // + mode_exec->fcst_file = cline[0]; + mode_exec->obs_file = cline[1]; + mode_exec->match_config_file = cline[2]; - mode_exec->init(); + } +} - return; +/////////////////////////////////////////////////////////////////////// +string ModeFrontEnd::stype(Processing_t t) +{ + 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; + } + return s; } + /////////////////////////////////////////////////////////////////////// -void set_config_merge_file(const StringArray & a) +void ModeFrontEnd::set_config_merge_file(const StringArray & a) { mode_exec->merge_config_file = a[0]; } //////////////////////////////////////////////////////////////////////// -void set_outdir(const StringArray & a) +void ModeFrontEnd::set_outdir(const StringArray & a) { mode_exec->out_dir = a[0]; } //////////////////////////////////////////////////////////////////////// -void set_logfile(const StringArray & a) +void ModeFrontEnd::set_logfile(const StringArray & a) { ConcatString filename; @@ -298,41 +633,18 @@ void set_logfile(const StringArray & a) //////////////////////////////////////////////////////////////////////// -void set_verbosity(const StringArray & a) +void ModeFrontEnd::set_verbosity(const StringArray & a) { - mlog.set_verbosity_level(atoi(a[0].c_str())); + mlog.set_verbosity_level(atoi(a[0].c_str())); } //////////////////////////////////////////////////////////////////////// -void set_compress(const StringArray & a) { - compress_level = atoi(a[0].c_str()); -} - -//////////////////////////////////////////////////////////////////////// - - -void set_field_index(const StringArray & a) - +void ModeFrontEnd::set_compress(const StringArray & a) { - -field_index = atoi(a[0].c_str()); - -if ( field_index < 0 ) { - - mlog << Error - << program_name << ": bad index value ... " - << field_index << "\n\n"; - - exit ( 1 ); - -} - -return; - + compress_level = atoi(a[0].c_str()); } - //////////////////////////////////////////////////////////////////////// diff --git a/src/tools/core/mode/mode_frontend.h b/src/tools/core/mode/mode_frontend.h new file mode 100644 index 0000000000..31d7ad5de3 --- /dev/null +++ b/src/tools/core/mode/mode_frontend.h @@ -0,0 +1,83 @@ +// ** 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_FRONTEND_H__ +#define __MODE_FRONTEND_H__ + + +//////////////////////////////////////////////////////////////////////// + + +#include +#include "mode_exec.h" +#include "string_array.h" +#include "multivar_data.h" + +class ModeFrontEnd { + + private: + + public: + + typedef enum {SINGLE_VAR, MULTIVAR_PASS1, MULTIVAR_PASS1_MERGE, MULTIVAR_PASS2, MULTIVAR_SUPER} Processing_t; + + ModeFrontEnd(); + ~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); + + // 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); + + // multivar superobject interface, 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); + + // single var mode, or multivar pass1 + void do_straight (Processing_t ptype); + + // multivar pass2 + void do_straight (Processing_t ptype, const MultiVarData &mvd, + ShapeData &f_merge, ShapeData &o_merge); + + // multivar super, no intensities + void do_straight (Processing_t ptype, + ShapeData &f_merge, ShapeData &o_merge); + + + MultiVarData *get_multivar_data(); + void addMultivarMergePass1(MultiVarData *mvdi); + + void process_command_line(const StringArray &, bool is_multivar); + + static string stype(Processing_t t); + + static void set_config_merge_file (const StringArray &); + static void set_outdir (const StringArray &); + static void set_logfile (const StringArray &); + static void set_verbosity (const StringArray &); + static void set_compress (const StringArray &); + +}; + + +#endif /* __MODE_FRONT_END_H__ */ + + +///////////////////////////////////////////////////////////////////////// diff --git a/src/tools/core/mode/mode_multivar.cc b/src/tools/core/mode/mode_multivar.cc deleted file mode 100644 index 4d9eb51c37..0000000000 --- a/src/tools/core/mode/mode_multivar.cc +++ /dev/null @@ -1,329 +0,0 @@ -// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* -// ** 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 -// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* - - -/////////////////////////////////////////////////////////////////////// - - -using namespace std; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mode_usage.h" -#include "mode_exec.h" - -#ifdef WITH_PYTHON -#include "global_python.h" -#endif - - -/////////////////////////////////////////////////////////////////////// -// -// Create output files using the following naming convention: -// -// mode_YYYYMMDDI_FHH_HHA.ps/.txt -// -// Where I indicates initilization time, L indicates lead time, -// and A indicates accumulation time. -// -/////////////////////////////////////////////////////////////////////// - - -extern const char * const program_name; - -static ModeExecutive mode_exec; // gotta make this global ... not sure why - - -/////////////////////////////////////////////////////////////////////// - - -static const char * default_out_dir = "."; - -static int compress_level = -1; - -static int field_index = -1; - - -/////////////////////////////////////////////////////////////////////// - - -static void do_quilt (); -static void do_straight (); - -static void process_command_line(int, char **); - -static void set_config_merge_file (const StringArray &); -static void set_outdir (const StringArray &); -static void set_logfile (const StringArray &); -static void set_verbosity (const StringArray &); -static void set_compress (const StringArray &); - -static void set_field_index (const StringArray &); // undocumented - - -/////////////////////////////////////////////////////////////////////// - - -int main_multivar(int argc, char * argv []) - -{ - - // - // Process the command line arguments - // - -process_command_line(argc, argv); - - // - // Process the forecast and observation files - // - -ModeConfInfo & conf = mode_exec.engine.conf_info; - -if ( field_index >= 0 ) conf.set_field_index(field_index); - -mode_exec.setup_fcst_obs_data(); - -if (compress_level >= 0) conf.nc_info.set_compress_level(compress_level); - - -if ( conf.quilt ) { - - do_quilt(); - -} else { - - do_straight(); - -} - -mode_exec.clear(); - - // - // done - // - -#ifdef WITH_PYTHON - GP.finalize(); -#endif - -return ( 0 ); - -} - - -/////////////////////////////////////////////////////////////////////// - - -void do_straight() - -{ - -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 ); - -} - -int index; - -for (index=0; index shoule never be called!\n\n"; + mlog << Error << "\n\n ModePsFile::ModePsFile(const ModePsFile &) -> shoule never be called!\n\n"; -exit ( 1 ); + exit ( 1 ); } @@ -101,9 +101,9 @@ ModePsFile & ModePsFile::operator=(const ModePsFile &) { -mlog << Error << "\n\n ModePsFile::operator=(const ModePsFile &) -> should never be called!\n\n"; + mlog << Error << "\n\n ModePsFile::operator=(const ModePsFile &) -> should never be called!\n\n"; -exit ( 1 ); + exit ( 1 ); } @@ -115,32 +115,32 @@ void ModePsFile::mpsf_init_from_scratch() { -Engine = (ModeFuzzyEngine *) 0; + Engine = (ModeFuzzyEngine *) 0; -ConfInfo = (ModeConfInfo *) 0; + ConfInfo = (ModeConfInfo *) 0; -grid = (Grid *) 0; + grid = (Grid *) 0; -MetDataDir = replace_path("MET_BASE"); + MetDataDir = replace_path("MET_BASE"); -PageWidth = default_PageWidth; -PageHeight = default_PageHeight; + PageWidth = default_PageWidth; + PageHeight = default_PageHeight; -Hmargin = default_Hmargin; -Vmargin = default_Vmargin; + Hmargin = default_Hmargin; + Vmargin = default_Vmargin; -TextSep = default_TextSep; + TextSep = default_TextSep; -text_y = 0.0; + text_y = 0.0; -FcstFillColor = default_fcst_fill; -ObsFillColor = default_obs_fill; + FcstFillColor = default_fcst_fill; + ObsFillColor = default_obs_fill; // // done // -return; + return; } @@ -152,48 +152,48 @@ void ModePsFile::set(ModeFuzzyEngine & e, const Grid & g, double data_min, doubl { -double dmin, dmax; + double dmin, dmax; -Engine = &e; + Engine = &e; -grid = &g; + grid = &g; -DataMin = data_min; -DataMax = data_max; + DataMin = data_min; + DataMax = data_max; -ConfInfo = &(e.conf_info); + ConfInfo = &(e.conf_info); -SmallPane.set_lrbt(Hmargin, 450.0, 270.0, 720.0); + SmallPane.set_lrbt(Hmargin, 450.0, 270.0, 720.0); -LargePane.set_lrbt(Hmargin, PageWidth - 3.0*Hmargin, Vmargin, PageHeight - 4.0*Vmargin); + LargePane.set_lrbt(Hmargin, PageWidth - 3.0*Hmargin, Vmargin, PageHeight - 4.0*Vmargin); -set_xy_box(); + set_xy_box(); -set_postscript_dims(); + set_postscript_dims(); // // set MetDataDir with the config file value // -MetDataDir = ConfInfo->met_data_dir; + MetDataDir = ConfInfo->met_data_dir; // // load the forecast and obs raw colortables // -ConcatString s; + ConcatString s; - s = replace_path(ConfInfo->Fcst->raw_pi.color_table.c_str()); + s = replace_path(ConfInfo->Fcst->raw_pi.color_table.c_str()); -mlog << Debug(1) << "Loading forecast raw color table: " << s << "\n"; + mlog << Debug(1) << "Loading forecast raw color table: " << s << "\n"; - FcstRawCtable.read(s.c_str()); + FcstRawCtable.read(s.c_str()); - s = replace_path(ConfInfo->Obs->raw_pi.color_table.c_str()); + s = replace_path(ConfInfo->Obs->raw_pi.color_table.c_str()); -mlog << Debug(1) << "Loading observation raw color table: " << s << "\n"; + mlog << Debug(1) << "Loading observation raw color table: " << s << "\n"; - ObsRawCtable.read(s.c_str()); + ObsRawCtable.read(s.c_str()); // // If the forecast and observation fields are the same and if the range @@ -201,68 +201,68 @@ mlog << Debug(1) << "Loading observation raw color table: " << s << "\n"; // data_min and data_max values // -if ( (ConfInfo->Fcst->var_info->name_attr() == ConfInfo->Obs->var_info->name_attr()) && - is_eq( FcstRawCtable.data_min (bad_data_double), 0.0) && - is_eq( FcstRawCtable.data_max (bad_data_double), 1.0) && - is_eq( ObsRawCtable.data_min (bad_data_double), 0.0) && - is_eq( ObsRawCtable.data_max (bad_data_double), 1.0) ) { + if ( (ConfInfo->Fcst->var_info->name_attr() == ConfInfo->Obs->var_info->name_attr()) && + is_eq( FcstRawCtable.data_min (bad_data_double), 0.0) && + is_eq( FcstRawCtable.data_max (bad_data_double), 1.0) && + is_eq( ObsRawCtable.data_min (bad_data_double), 0.0) && + is_eq( ObsRawCtable.data_max (bad_data_double), 1.0) ) { - FcstRawCtable.rescale (DataMin, DataMax, bad_data_double); - ObsRawCtable.rescale (DataMin, DataMax, bad_data_double); + FcstRawCtable.rescale (DataMin, DataMax, bad_data_double); + ObsRawCtable.rescale (DataMin, DataMax, bad_data_double); -} else { + } else { - // - // Otherwise, if the range of either colortable is [0, 1], rescale - // the field using the min/max values in the field - // + // + // Otherwise, if the range of either colortable is [0, 1], rescale + // the field using the min/max values in the field + // - if ( is_eq(FcstRawCtable.data_min(bad_data_double), 0.0) && - is_eq(FcstRawCtable.data_max(bad_data_double), 1.0) ) { + if ( is_eq(FcstRawCtable.data_min(bad_data_double), 0.0) && + is_eq(FcstRawCtable.data_max(bad_data_double), 1.0) ) { - e.fcst_raw->data.data_range(dmin, dmax); + e.fcst_raw->data.data_range(dmin, dmax); - FcstRawCtable.rescale(dmin, dmax, bad_data_double); + FcstRawCtable.rescale(dmin, dmax, bad_data_double); - } + } - if ( is_eq(ObsRawCtable.data_min(bad_data_double), 0.0) && - is_eq(ObsRawCtable.data_max(bad_data_double), 1.0) ) { + if ( is_eq(ObsRawCtable.data_min(bad_data_double), 0.0) && + is_eq(ObsRawCtable.data_max(bad_data_double), 1.0) ) { e.obs_raw->data.data_range(dmin, dmax); ObsRawCtable.rescale(dmin, dmax, bad_data_double); - } + } -} + } // // If the fcst_raw_plot_min or fcst_raw_plot_max value is set in the // config file, rescale the forecast colortable to the requested range // -if ( !is_eq(ConfInfo->Fcst->raw_pi.plot_min, 0.0) || - !is_eq(ConfInfo->Fcst->raw_pi.plot_max, 0.0) ) { + if ( !is_eq(ConfInfo->Fcst->raw_pi.plot_min, 0.0) || + !is_eq(ConfInfo->Fcst->raw_pi.plot_max, 0.0) ) { - FcstRawCtable.rescale(ConfInfo->Fcst->raw_pi.plot_min, - ConfInfo->Fcst->raw_pi.plot_max, - bad_data_double); + FcstRawCtable.rescale(ConfInfo->Fcst->raw_pi.plot_min, + ConfInfo->Fcst->raw_pi.plot_max, + bad_data_double); -} + } // // If the obs_raw_plot_min or obs_raw_plot_max value is set in the // config file, rescale the observation colortable to the requested range // -if ( !is_eq(ConfInfo->Obs->raw_pi.plot_min, 0.0) || - !is_eq(ConfInfo->Obs->raw_pi.plot_max, 0.0) ) { + if ( !is_eq(ConfInfo->Obs->raw_pi.plot_min, 0.0) || + !is_eq(ConfInfo->Obs->raw_pi.plot_max, 0.0) ) { - ObsRawCtable.rescale(ConfInfo->Obs->raw_pi.plot_min, - ConfInfo->Obs->raw_pi.plot_max, - bad_data_double); -} + ObsRawCtable.rescale(ConfInfo->Obs->raw_pi.plot_min, + ConfInfo->Obs->raw_pi.plot_max, + bad_data_double); + } // // Set the fill colors. If a fill value is not specified in the range @@ -270,17 +270,17 @@ if ( !is_eq(ConfInfo->Obs->raw_pi.plot_min, 0.0) || // color specified in the color table. // -if ( (bad_data_double >= FcstRawCtable.data_min()) && - (bad_data_double <= FcstRawCtable.data_max()) ) FcstFillColor = FcstRawCtable.nearest(bad_data_double); + if ( (bad_data_double >= FcstRawCtable.data_min()) && + (bad_data_double <= FcstRawCtable.data_max()) ) FcstFillColor = FcstRawCtable.nearest(bad_data_double); -if ( (bad_data_double >= ObsRawCtable.data_min()) && - (bad_data_double <= ObsRawCtable.data_max()) ) ObsFillColor = ObsRawCtable.nearest(bad_data_double); + if ( (bad_data_double >= ObsRawCtable.data_min()) && + (bad_data_double <= ObsRawCtable.data_max()) ) ObsFillColor = ObsRawCtable.nearest(bad_data_double); // // done // -return; + return; } @@ -297,41 +297,41 @@ void ModePsFile::set_xy_box() // If not set, reset the xy_bb to the entire grid. // -if(ConfInfo->plot_valid_flag == 0) { + if(ConfInfo->plot_valid_flag == 0) { - XY_box.set_llwh(0.0, 0.0, grid->nx(), grid->ny()); + XY_box.set_llwh(0.0, 0.0, grid->nx(), grid->ny()); - return; + return; -} + } // // Compute the x/y bounding box for valid data in each field // -double L, R, B, T; -Box fcst_xy_bb, obs_xy_bb; + double L, R, B, T; + Box fcst_xy_bb, obs_xy_bb; -fcst_xy_bb = valid_xy_bb(Engine->fcst_raw, *grid); - obs_xy_bb = valid_xy_bb(Engine->obs_raw, *grid); + fcst_xy_bb = valid_xy_bb(Engine->fcst_raw, *grid); + obs_xy_bb = valid_xy_bb(Engine->obs_raw, *grid); // // Compute the x/y bounding box as the union of the // fcst and obs x/y bounding boxes // -L = min(fcst_xy_bb.left(), obs_xy_bb.left()); -B = min(fcst_xy_bb.bottom(), obs_xy_bb.bottom()); -R = max(fcst_xy_bb.right(), obs_xy_bb.right()); -T = max(fcst_xy_bb.top(), obs_xy_bb.top()); + L = min(fcst_xy_bb.left(), obs_xy_bb.left()); + B = min(fcst_xy_bb.bottom(), obs_xy_bb.bottom()); + R = max(fcst_xy_bb.right(), obs_xy_bb.right()); + T = max(fcst_xy_bb.top(), obs_xy_bb.top()); -XY_box.set_lrbt(L, R, B, T); + XY_box.set_lrbt(L, R, B, T); // // done // -return; + return; } @@ -343,9 +343,9 @@ void ModePsFile::choose_font(int _font_number, double _font_size) { - PSfile::choose_font_with_dir(_font_number, _font_size, MetDataDir.c_str()); + PSfile::choose_font_with_dir(_font_number, _font_size, MetDataDir.c_str()); -return; + return; } @@ -357,15 +357,15 @@ void ModePsFile::set_color(const Color & c) { -double R, G, B; + double R, G, B; -R = (c.red())/255.0; -G = (c.green())/255.0; -B = (c.blue())/255.0; + R = (c.red())/255.0; + G = (c.green())/255.0; + B = (c.blue())/255.0; -setrgbcolor(R, G, B); + setrgbcolor(R, G, B); -return; + return; } @@ -381,9 +381,9 @@ void ModePsFile::gridxy_to_pagexy(double x_grid, double y_grid, double & x_page, // This routine depends on the View_box having been already set // -::gridxy_to_pagexy(*grid, XY_box, x_grid, y_grid, x_page, y_page, View_box); + ::gridxy_to_pagexy(*grid, XY_box, x_grid, y_grid, x_page, y_page, View_box); -return; + return; } @@ -395,23 +395,23 @@ void ModePsFile::set_view(double y_ll, double y_ur, double x_cen) { -double L, R, B, T; -double mag, W; + double L, R, B, T; + double mag, W; -B = y_ll; -T = y_ur; + B = y_ll; + T = y_ur; -mag = (T - B)/(XY_box.height()); + mag = (T - B)/(XY_box.height()); -W = mag*(XY_box.width()); + W = mag*(XY_box.width()); -L = x_cen - 0.5*W; -R = x_cen + 0.5*W; + L = x_cen - 0.5*W; + R = x_cen + 0.5*W; -View_box.set_lrbt(L, R, B, T); + View_box.set_lrbt(L, R, B, T); -return; + return; } @@ -423,34 +423,34 @@ void ModePsFile::set_postscript_dims() { -const int nx = nint(XY_box.width()); -const int ny = nint(XY_box.height()); -double grid_ar, sm_plot_ar, lg_plot_ar; + const int nx = nint(XY_box.width()); + const int ny = nint(XY_box.height()); + double grid_ar, sm_plot_ar, lg_plot_ar; -grid_ar = ((double) nx)/ny; -sm_plot_ar = (SmallPane.width()/2.0)/(SmallPane.height()/3.0); -lg_plot_ar = (LargePane.width()/1.0)/(LargePane.height()/2.0); + grid_ar = ((double) nx)/ny; + sm_plot_ar = (SmallPane.width()/2.0)/(SmallPane.height()/3.0); + lg_plot_ar = (LargePane.width()/1.0)/(LargePane.height()/2.0); -if(grid_ar > sm_plot_ar) SmallPlotHeight = SmallPane.height()/3.0*sm_plot_ar/grid_ar; -else SmallPlotHeight = SmallPane.height()/3.0; + if(grid_ar > sm_plot_ar) SmallPlotHeight = SmallPane.height()/3.0*sm_plot_ar/grid_ar; + else SmallPlotHeight = SmallPane.height()/3.0; -if(grid_ar > lg_plot_ar) LargePlotHeight = LargePane.height()/2.0*lg_plot_ar/grid_ar; -else LargePlotHeight = LargePane.height()/2.0; + if(grid_ar > lg_plot_ar) LargePlotHeight = LargePane.height()/2.0*lg_plot_ar/grid_ar; + else LargePlotHeight = LargePane.height()/2.0; -Htab_1 = SmallPane.left() + SmallPane.width()/4.0; -Htab_2 = SmallPane.left() + SmallPane.width()/4.0 * 3.0; -Htab_3 = SmallPane.right() + TextSep; + Htab_1 = SmallPane.left() + SmallPane.width()/4.0; + Htab_2 = SmallPane.left() + SmallPane.width()/4.0 * 3.0; + Htab_3 = SmallPane.right() + TextSep; -Vtab_1 = SmallPane.top() - SmallPlotHeight; -Vtab_2 = Vtab_1 - SmallPlotHeight; -Vtab_3 = Vtab_2 - SmallPlotHeight; + Vtab_1 = SmallPane.top() - SmallPlotHeight; + Vtab_2 = Vtab_1 - SmallPlotHeight; + Vtab_3 = Vtab_2 - SmallPlotHeight; // // done // -return; + return; } @@ -462,7 +462,7 @@ void ModePsFile::outline_box(const Box & b, const double linewidth) { -gsave(); + gsave(); setlinewidth(linewidth); @@ -476,10 +476,10 @@ gsave(); closepath(); stroke(); -grestore(); + grestore(); -return; + return; } @@ -491,9 +491,9 @@ void ModePsFile::outline_view() { -outline_box(View_box, L_thin); + outline_box(View_box, L_thin); -return; + return; } @@ -505,7 +505,7 @@ void ModePsFile::fill_box(const Box & b, const Color & c) { -gsave(); + gsave(); set_color(c); @@ -519,10 +519,10 @@ gsave(); closepath(); fill(); -grestore(); + grestore(); -return; + return; } @@ -530,51 +530,59 @@ return; //////////////////////////////////////////////////////////////////////// -void ModePsFile::make_plot() +void ModePsFile::make_plot(bool isMultivarSuper) { -const MergeType fcst_merge_flag = ConfInfo->Fcst->merge_flag; -const MergeType obs_merge_flag = ConfInfo->Obs->merge_flag; -ConcatString s; + const MergeType fcst_merge_flag = ConfInfo->Fcst->merge_flag; + const MergeType obs_merge_flag = ConfInfo->Obs->merge_flag; + ConcatString s; -s << cs_erase - << "MODE: " << ConfInfo->Fcst->var_info->name_attr() << " at " - << ConfInfo->Fcst->var_info->level_attr() << " vs " - << ConfInfo->Obs->var_info->name_attr() << " at " - << ConfInfo->Obs->var_info->level_attr(); + if (isMultivarSuper) { + s << cs_erase + << "MODE: " << ConfInfo->fcst_multivar_name.c_str() << " at " + << ConfInfo->fcst_multivar_level.c_str() << " vs " + << ConfInfo->obs_multivar_name.c_str() << " at " + << ConfInfo->obs_multivar_level.c_str(); + } else { + s << cs_erase + << "MODE: " << ConfInfo->Fcst->var_info->name_attr() << " at " + << ConfInfo->Fcst->var_info->level_attr() << " vs " + << ConfInfo->Obs->var_info->name_attr() << " at " + << ConfInfo->Obs->var_info->level_attr(); + } - plot_engine(*Engine, FOEng, s.c_str()); + plot_engine(*Engine, FOEng, s.c_str()); -if ( (fcst_merge_flag == MergeType_Both) || (fcst_merge_flag == MergeType_Thresh) ) { + if ( (fcst_merge_flag == MergeType_Both) || (fcst_merge_flag == MergeType_Thresh) ) { - plot_threshold_merging(*Engine, "Forecast: Threshold Merging", 1); + plot_threshold_merging(*Engine, "Forecast: Threshold Merging", 1); -} + } -if ( (fcst_merge_flag == MergeType_Both) || (fcst_merge_flag == MergeType_Engine) ) { + if ( (fcst_merge_flag == MergeType_Both) || (fcst_merge_flag == MergeType_Engine) ) { - plot_engine(*(Engine->fcst_engine), FFEng, "Forecast: ModeFuzzyEngine Merging"); + plot_engine(*(Engine->fcst_engine), FFEng, "Forecast: ModeFuzzyEngine Merging"); -} + } -if ( (obs_merge_flag == MergeType_Both) || (obs_merge_flag == MergeType_Thresh) ) { + if ( (obs_merge_flag == MergeType_Both) || (obs_merge_flag == MergeType_Thresh) ) { - plot_threshold_merging(*Engine, "Observation: Threshold Merging", 0); + plot_threshold_merging(*Engine, "Observation: Threshold Merging", 0); -} + } -if ( (obs_merge_flag == MergeType_Both) || (obs_merge_flag == MergeType_Engine) ) { + if ( (obs_merge_flag == MergeType_Both) || (obs_merge_flag == MergeType_Engine) ) { - plot_engine(*(Engine->obs_engine), OOEng, "Observation: ModeFuzzyEngine Merging"); + plot_engine(*(Engine->obs_engine), OOEng, "Observation: ModeFuzzyEngine Merging"); -} + } // // done // -return; + return; } @@ -586,31 +594,31 @@ void ModePsFile::plot_threshold_merging (ModeFuzzyEngine & eng, const char * tit { -ShapeData merge_mask, merge_split, merge_shape; -Polyline poly; -int n_merge; -double v_tab; -const double h_tab_cen = PageWidth/2.0; + ShapeData merge_mask, merge_split, merge_shape; + Polyline poly; + int n_merge; + double v_tab; + const double h_tab_cen = PageWidth/2.0; -if ( fcst ) { + if ( fcst ) { - merge_mask = *(eng.fcst_conv); - merge_mask.threshold(eng.conf_info.Fcst->merge_thresh); + merge_mask = *(eng.fcst_conv); + merge_mask.threshold(eng.conf_info.Fcst->merge_thresh); -} else { + } else { - merge_mask = *(eng.obs_conv); - merge_mask.threshold(eng.conf_info.Obs->merge_thresh); + merge_mask = *(eng.obs_conv); + merge_mask.threshold(eng.conf_info.Obs->merge_thresh); -} + } -merge_split = split(merge_mask, n_merge); + merge_split = split(merge_mask, n_merge); -inc_pagenumber(); + inc_pagenumber(); -choose_font(31, 24.0); + choose_font(31, 24.0); -write_centered_text(1, 1, h_tab_cen, 752.0, 0.5, 0.5, title); + write_centered_text(1, 1, h_tab_cen, 752.0, 0.5, 0.5, title); //////////////////////////////////////////////////////////////////// // @@ -618,27 +626,27 @@ write_centered_text(1, 1, h_tab_cen, 752.0, 0.5, 0.5, title); // //////////////////////////////////////////////////////////////////// -v_tab = PageHeight - 3.0*Vmargin; + v_tab = PageHeight - 3.0*Vmargin; -set_view(v_tab - LargePlotHeight, v_tab, h_tab_cen); + set_view(v_tab - LargePlotHeight, v_tab, h_tab_cen); -if ( fcst ) { + if ( fcst ) { - comment("threshold merging page: fcst raw"); - render_ppm(eng, FOEng, *(eng.fcst_raw), fcst, 0); + comment("threshold merging page: fcst raw"); + render_ppm(eng, FOEng, *(eng.fcst_raw), fcst, 0); -} else { + } else { - comment("threshold merging page: obs raw"); - render_ppm(eng, FOEng, *(eng.obs_raw), fcst, 0); + comment("threshold merging page: obs raw"); + render_ppm(eng, FOEng, *(eng.obs_raw), fcst, 0); -} + } -outline_box(View_box, L_thin); + outline_box(View_box, L_thin); -draw_map( &(eng.conf_info.conf) ); + draw_map( &(eng.conf_info.conf) ); -draw_colorbar(fcst); + draw_colorbar(fcst); //////////////////////////////////////////////////////////////////// // @@ -646,35 +654,35 @@ draw_colorbar(fcst); // //////////////////////////////////////////////////////////////////// -v_tab -= LargePlotHeight; + v_tab -= LargePlotHeight; -set_view(v_tab - LargePlotHeight, v_tab, h_tab_cen); + set_view(v_tab - LargePlotHeight, v_tab, h_tab_cen); -if ( fcst ) { + if ( fcst ) { - comment("threshold merging page: fcst raw"); - render_ppm(eng, FOEng, *(eng.fcst_split), fcst, 2); + comment("threshold merging page: fcst raw"); + render_ppm(eng, FOEng, *(eng.fcst_split), fcst, 2); -} else { + } else { - comment("threshold merging page: obs split"); - render_ppm(eng, FOEng, *(eng.obs_split), fcst, 2); + comment("threshold merging page: obs split"); + render_ppm(eng, FOEng, *(eng.obs_split), fcst, 2); -} + } -outline_box(View_box, L_thin); + outline_box(View_box, L_thin); -draw_map( &(eng.conf_info.conf) ); + draw_map( &(eng.conf_info.conf) ); -draw_boundaries(merge_split, n_merge); + draw_boundaries(merge_split, n_merge); // // done // -showpage(); + showpage(); -return; + return; } @@ -686,46 +694,46 @@ void ModePsFile::draw_boundaries(ModeFuzzyEngine & eng, bool fcst) { -int i, j; + int i, j; // // Draw boundaries around each of the objects // -if ( fcst ) { + if ( fcst ) { - for (i=0; i<(eng.n_fcst); i++) { + for (i=0; i<(eng.n_fcst); i++) { - for (j=0; j<(eng.fcst_single[i].n_bdy); j++) { + for (j=0; j<(eng.fcst_single[i].n_bdy); j++) { - draw_polyline(eng.fcst_single[i].boundary[j], BoundaryColor, false); + draw_polyline(eng.fcst_single[i].boundary[j], BoundaryColor, false); + + } } + return; } - return; -} - // // obs // -for (i=0; i<(eng.n_obs); i++) { + for (i=0; i<(eng.n_obs); i++) { - for (j=0; j<(eng.obs_single[i].n_bdy); j++) { + for (j=0; j<(eng.obs_single[i].n_bdy); j++) { - draw_polyline(eng.obs_single[i].boundary[j], BoundaryColor, false); + draw_polyline(eng.obs_single[i].boundary[j], BoundaryColor, false); - } + } -} + } // // done // -return; + return; } @@ -737,25 +745,25 @@ void ModePsFile::draw_boundaries(ShapeData & split_dp, int n_shapes) { -int i; -Polyline poly; -ShapeData wd_shape; + int i; + Polyline poly; + ShapeData wd_shape; // // Draw boundary for each shape in the split field // -for (i=0; ilatlon_to_xy(lat, lon, grid_x_prev, grid_y_prev); + grid->latlon_to_xy(lat, lon, grid_x_prev, grid_y_prev); -} else { // Grid coordinates + } else { // Grid coordinates - grid_x_prev = poly.u[0]; - grid_y_prev = poly.v[0]; + grid_x_prev = poly.u[0]; + grid_y_prev = poly.v[0]; -} + } // // Convert the starting Grid x/y to page x,y and move to it // -gridxy_to_pagexy(grid_x_prev, grid_y_prev, page_x, page_y); + gridxy_to_pagexy(grid_x_prev, grid_y_prev, page_x, page_y); -moveto(page_x, page_y); + moveto(page_x, page_y); // // Loop through the vertices and back to the starting vertex // -for (i=1; ilatlon_to_xy(lat, lon, grid_x_cur, grid_y_cur); + grid->latlon_to_xy(lat, lon, grid_x_cur, grid_y_cur); - } else { // Grid coordinates + } else { // Grid coordinates - grid_x_cur = poly.u[i]; - grid_y_cur = poly.v[i]; + grid_x_cur = poly.u[i]; + grid_y_cur = poly.v[i]; - } + } - gridxy_to_pagexy(grid_x_cur, grid_y_cur, page_x, page_y); + gridxy_to_pagexy(grid_x_cur, grid_y_cur, page_x, page_y); - if ( ConfInfo->plot_gcarc_flag == 0 ) { + if ( ConfInfo->plot_gcarc_flag == 0 ) { - lineto(page_x, page_y); + lineto(page_x, page_y); - } else { + } else { - gc_arcto(*grid, XY_box, *this, grid_x_prev, grid_y_prev, grid_x_cur, grid_y_cur, 10, View_box); + gc_arcto(*grid, XY_box, *this, grid_x_prev, grid_y_prev, grid_x_cur, grid_y_cur, 10, View_box); - } + } // // Reset the previous Grid x,y to the current Grid x,y // - grid_x_prev = grid_x_cur; - grid_y_prev = grid_y_cur; + grid_x_prev = grid_x_cur; + grid_y_prev = grid_y_cur; -} // for i + } // for i -closepath(); -stroke(); + closepath(); + stroke(); -grestore(); + grestore(); // // done // -return; + return; } @@ -880,20 +888,20 @@ void ModePsFile::draw_map(MetConfig * config) { -if ( use_zlib ) begin_flate(); + if ( use_zlib ) begin_flate(); -gsave(); + gsave(); setlinewidth(L_thin); // ::draw_map(*grid, XY_box, *this, View_box, MapColor, MetDataDir); ::draw_map(*grid, XY_box, *this, View_box, config); -grestore(); + grestore(); -if ( use_zlib ) end_flate(); + if ( use_zlib ) end_flate(); -return; + return; } @@ -905,89 +913,89 @@ void ModePsFile::draw_colorbar(bool fcst) { -int i, n_colors; -char label[max_str_len]; -double bar_width, bar_height, x_ll, y_ll; -ColorTable * ct = (ColorTable *) 0; -Box b; -Color c; + int i, n_colors; + char label[max_str_len]; + double bar_width, bar_height, x_ll, y_ll; + ColorTable * ct = (ColorTable *) 0; + Box b; + Color c; // // Set up the pointer to the appropriate colortable // -ct = ( fcst ? (&FcstRawCtable) : (&ObsRawCtable) ); + ct = ( fcst ? (&FcstRawCtable) : (&ObsRawCtable) ); // // Get the number of colortable entries // -n_colors = ct->n_entries(); + n_colors = ct->n_entries(); // // Draw colorbar in the bottom right corner of the Bounding Box // -gsave(); -setlinewidth(L_thin); -choose_font(28, 8.0); + gsave(); + setlinewidth(L_thin); + choose_font(28, 8.0); -bar_width = Hmargin/2.0; -bar_height = (View_box.height())/n_colors; + bar_width = Hmargin/2.0; + bar_height = (View_box.height())/n_colors; -x_ll = View_box.right(); -y_ll = View_box.bottom(); + x_ll = View_box.right(); + y_ll = View_box.bottom(); -ColorTable & ctable = *ct; + ColorTable & ctable = *ct; -for (i=0; i 0) && (i%stride == 0) ) { + if ( (i > 0) && (i%stride == 0) ) { - // - // Choose the label format based on whether the colortable - // has been rescaled - // + // + // Choose the label format based on whether the colortable + // has been rescaled + // - if ( ctable.rescale_flag ) snprintf(label, sizeof(label), "%.2f", ctable[i].value_low()); - else snprintf(label, sizeof(label), "%g", ctable[i].value_low()); + if ( ctable.rescale_flag ) snprintf(label, sizeof(label), "%.2f", ctable[i].value_low()); + else snprintf(label, sizeof(label), "%g", ctable[i].value_low()); - write_centered_text(2, 1, x_ll + bar_width + 2.0, y_ll, 0.0, 0.5, label); - } + write_centered_text(2, 1, x_ll + bar_width + 2.0, y_ll, 0.0, 0.5, label); + } - y_ll += bar_height; + y_ll += bar_height; -} // for i + } // for i -grestore(); + grestore(); // // done // -return; + return; } @@ -999,110 +1007,110 @@ void ModePsFile::render_ppm(ModeFuzzyEngine & eng, EngineType eng_type, const Sh { -RenderInfo render_info; -Ppm image; -int x, y, v_int; -double mag, v; -Color c; -Color fill_color; -ColorTable *ct = (ColorTable *) 0; -const int L = nint(XY_box.left()); -const int B = nint(XY_box.bottom()); + RenderInfo render_info; + Ppm image; + int x, y, v_int; + double mag, v; + Color c; + Color fill_color; + ColorTable *ct = (ColorTable *) 0; + const int L = nint(XY_box.left()); + const int B = nint(XY_box.bottom()); // // Set up pointers to the appropriate colortable and fill color values // -if ( eng_type == FFEng ) { + if ( eng_type == FFEng ) { - ct = &FcstRawCtable; - fill_color = FcstFillColor; + ct = &FcstRawCtable; + fill_color = FcstFillColor; -} else if ( eng_type == OOEng ) { + } else if ( eng_type == OOEng ) { - ct = &ObsRawCtable; - fill_color = ObsFillColor; + ct = &ObsRawCtable; + fill_color = ObsFillColor; -} else { // eng_type == FOEng + } else { // eng_type == FOEng - if ( fcst ) { + if ( fcst ) { - ct = &FcstRawCtable; - fill_color = FcstFillColor; + ct = &FcstRawCtable; + fill_color = FcstFillColor; - } else { + } else { - ct = &ObsRawCtable; - fill_color = ObsFillColor; + ct = &ObsRawCtable; + fill_color = ObsFillColor; - } + } -} + } // // Convert the ShapeData object to PPM // -image.set_size_xy((int) (XY_box.width()), (int) (XY_box.height())); + image.set_size_xy((int) (XY_box.width()), (int) (XY_box.height())); -for(x=L; x<(XY_box.right()); x++) { + for(x=L; x<(XY_box.right()); x++) { - for(y=B; y<(XY_box.top()); y++) { + for(y=B; y<(XY_box.top()); y++) { - v = wd.data(x, y); + v = wd.data(x, y); - v_int = nint(v); + v_int = nint(v); - if ( split == 1 ) { // Single object field + if ( split == 1 ) { // Single object field // // Should be no bad data left at this point // - if ( is_bad_data(v) ) c = fill_color; - else if ( v_int == 0 ) c = white; - else if ( v_int > 0 && fcst ) c = eng.fcst_color[v_int - 1]; - else if ( v_int > 0 && !fcst ) c = eng.obs_color[v_int - 1]; + if ( is_bad_data(v) ) c = fill_color; + else if ( v_int == 0 ) c = white; + else if ( v_int > 0 && fcst ) c = eng.fcst_color[v_int - 1]; + else if ( v_int > 0 && !fcst ) c = eng.obs_color[v_int - 1]; - } else if ( split == 2 ) { // Cluster object field + } else if ( split == 2 ) { // Cluster object field // // Should be no bad data left at this point // - if ( is_bad_data (v) ) c = fill_color; - else if ( v_int == 0 ) c = white; - else c = BoundaryColor; + if ( is_bad_data (v) ) c = fill_color; + else if ( v_int == 0 ) c = white; + else c = BoundaryColor; - } else { // Raw data field + } else { // Raw data field - if ( is_bad_data(v) ) c = fill_color; - else c = ct->nearest(v); + if ( is_bad_data(v) ) c = fill_color; + else c = ct->nearest(v); - } + } - image.putxy(c, x - L, y - B); + image.putxy(c, x - L, y - B); - } // end for y + } // end for y -} // end for x + } // end for x -mag = View_box.width()/XY_box.width(); + mag = View_box.width()/XY_box.width(); -render_info.set_ll(View_box.left(), View_box.bottom()); -render_info.set_mag(mag); -render_info.set_color(); -// render_info.add_filter(RunLengthEncode); -render_info.add_filter(FlateEncode); -render_info.add_filter(ASCII85Encode); + render_info.set_ll(View_box.left(), View_box.bottom()); + render_info.set_mag(mag); + render_info.set_color(); + // render_info.add_filter(RunLengthEncode); + render_info.add_filter(FlateEncode); + render_info.add_filter(ASCII85Encode); -render(*this, image, render_info); + render(*this, image, render_info); // // done // -return; + return; } @@ -1114,76 +1122,76 @@ void ModePsFile::draw_convex_hulls(ModeFuzzyEngine & eng, bool fcst, bool id_fla { -int i, j; -double grid_x, grid_y, page_x, page_y; -Polyline poly; -Color c; -char label[max_str_len]; + int i, j; + double grid_x, grid_y, page_x, page_y; + Polyline poly; + Color c; + char label[max_str_len]; -gsave(); + gsave(); -setlinewidth(0.0); + setlinewidth(0.0); // // Draw convex hulls around collection of shapes // -for (i=0; idata.nx(); + const int data_ny = wd_ptr->data.ny(); -const int data_nx = wd_ptr->data.nx(); -const int data_ny = wd_ptr->data.ny(); + for(x=0; xis_valid_xy(x, y)) { - if(wd_ptr->is_valid_xy(x, y)) { + if(x < L) L = x; + if(x > R) R = x; - if(x < L) L = x; - if(x > R) R = x; + if(y < B) B = y; + if(y > T) T = y; - if(y < B) B = y; - if(y > T) T = y; + } } } -} - -bb.set_lrbt(L, R, B, T); + bb.set_lrbt(L, R, B, T); -return ( bb ); + return ( bb ); } diff --git a/src/tools/core/mode/mode_ps_file.h b/src/tools/core/mode/mode_ps_file.h index 92995066a2..a34ec83622 100644 --- a/src/tools/core/mode/mode_ps_file.h +++ b/src/tools/core/mode/mode_ps_file.h @@ -49,141 +49,141 @@ enum EngineType { class ModePsFile : public PSfile { - private: + private: - ModePsFile(const ModePsFile &); - ModePsFile & operator=(const ModePsFile &); + ModePsFile(const ModePsFile &); + ModePsFile & operator=(const ModePsFile &); - protected: + protected: - void mpsf_init_from_scratch(); + void mpsf_init_from_scratch(); - void mpsf_assign(const ModePsFile &); + void mpsf_assign(const ModePsFile &); - void set_xy_box(); + void set_xy_box(); - void set_postscript_dims(); + void set_postscript_dims(); - void set_view(double y_ll, double y_ur, double x_cen); + void set_view(double y_ll, double y_ur, double x_cen); - void plot_engine (ModeFuzzyEngine &, EngineType, const char * title); - void plot_threshold_merging (ModeFuzzyEngine &, const char * title , bool fcst); + void plot_engine (ModeFuzzyEngine &, EngineType, const char * title); + void plot_threshold_merging (ModeFuzzyEngine &, const char * title , bool fcst); - void do_page_1 (ModeFuzzyEngine &, EngineType, const char * title); - void do_page_1_FOEng (ModeFuzzyEngine &, EngineType, const char * title); - void do_page_1_other (ModeFuzzyEngine &, EngineType, const char * title); + void do_page_1 (ModeFuzzyEngine &, EngineType, const char * title); + void do_page_1_FOEng (ModeFuzzyEngine &, EngineType, const char * title); + void do_page_1_other (ModeFuzzyEngine &, EngineType, const char * title); - void do_fcst_enlarge_page (ModeFuzzyEngine &, EngineType, const char * title); - void do_obs_enlarge_page (ModeFuzzyEngine &, EngineType, const char * title); - void do_overlap_page (ModeFuzzyEngine &, EngineType, const char * title); - void do_cluster_page (ModeFuzzyEngine &, EngineType, const char * title); + void do_fcst_enlarge_page (ModeFuzzyEngine &, EngineType, const char * title); + void do_obs_enlarge_page (ModeFuzzyEngine &, EngineType, const char * title); + void do_overlap_page (ModeFuzzyEngine &, EngineType, const char * title); + void do_cluster_page (ModeFuzzyEngine &, EngineType, const char * title); - void draw_boundaries(ModeFuzzyEngine &, bool fcst); - void draw_boundaries(ShapeData &, int n_shapes); + void draw_boundaries(ModeFuzzyEngine &, bool fcst); + void draw_boundaries(ShapeData &, int n_shapes); - void draw_polyline(Polyline &, const Color &, bool latlon); + void draw_polyline(Polyline &, const Color &, bool latlon); - void draw_convex_hulls(ModeFuzzyEngine & eng, bool fcst, bool id_flag); + void draw_convex_hulls(ModeFuzzyEngine & eng, bool fcst, bool id_flag); - void plot_simple_ids(ModeFuzzyEngine &, bool fcst); + void plot_simple_ids(ModeFuzzyEngine &, bool fcst); - void render_ppm(ModeFuzzyEngine &, EngineType, const ShapeData &, bool fcst, int split); + void render_ppm(ModeFuzzyEngine &, EngineType, const ShapeData &, bool fcst, int split); - void draw_colorbar(bool); + void draw_colorbar(bool); - void draw_map(MetConfig *); + void draw_map(MetConfig *); - void wct0(double x, double y, const char *); - void wct5(double x, double y, const char *); + void wct0(double x, double y, const char *); + void wct5(double x, double y, const char *); - ModeFuzzyEngine * Engine; // not allocated - ModeConfInfo * ConfInfo; // not allocated - const Grid * grid; // not allocated + ModeFuzzyEngine * Engine; // not allocated + ModeConfInfo * ConfInfo; // not allocated + const Grid * grid; // not allocated - ConcatString MetDataDir; + ConcatString MetDataDir; - ConcatString FcstString; - ConcatString ObsString; + ConcatString FcstString; + ConcatString ObsString; - ConcatString FcstShortString; - ConcatString ObsShortString; + ConcatString FcstShortString; + ConcatString ObsShortString; - ColorTable FcstRawCtable; - ColorTable ObsRawCtable; + ColorTable FcstRawCtable; + ColorTable ObsRawCtable; - Color FcstFillColor; - Color ObsFillColor; + Color FcstFillColor; + Color ObsFillColor; - double PageWidth; - double PageHeight; + double PageWidth; + double PageHeight; - double Hmargin; - double Vmargin; + double Hmargin; + double Vmargin; - double TextSep; + double TextSep; - double text_y; + double text_y; - double DataMin; - double DataMax; + double DataMin; + double DataMax; - double Htab_1; - double Htab_2; - double Htab_3; + double Htab_1; + double Htab_2; + double Htab_3; - double Vtab_1; - double Vtab_2; - double Vtab_3; + double Vtab_1; + double Vtab_2; + double Vtab_3; - double SmallPlotHeight; - double LargePlotHeight; + double SmallPlotHeight; + double LargePlotHeight; - Box LargePane; - Box SmallPane; + Box LargePane; + Box SmallPane; - Box XY_box; - Box View_box; + Box XY_box; + Box View_box; - public: + public: - ModePsFile(); - ModePsFile(const char *); - ~ModePsFile(); + ModePsFile(); + ModePsFile(const char *); + ~ModePsFile(); - // - // set stuff - // + // + // set stuff + // - void set (ModeFuzzyEngine &, const Grid &, double data_min, double data_max); + void set (ModeFuzzyEngine &, const Grid &, double data_min, double data_max); - // - // get stuff - // + // + // get stuff + // - // - // do stuff - // + // + // do stuff + // - void make_plot(); + void make_plot(bool isMultivarSuper=false); - using PSfile::outline_box; + using PSfile::outline_box; - void outline_box (const Box &, const double linewidth); - void outline_view(); - void fill_box (const Box &, const Color &); + void outline_box (const Box &, const double linewidth); + void outline_view(); + void fill_box (const Box &, const Color &); - void gridxy_to_pagexy(double x_grid, double y_grid, double & x_page, double & y_page) const; + void gridxy_to_pagexy(double x_grid, double y_grid, double & x_page, double & y_page) const; - void set_color(const Color &); + void set_color(const Color &); - void choose_font(int, double); // uses MetDataDir + void choose_font(int, double); // uses MetDataDir - void nextline(); + void nextline(); }; diff --git a/src/tools/core/mode/mode_singlevar.cc b/src/tools/core/mode/mode_singlevar.cc deleted file mode 100644 index 7c36f6f865..0000000000 --- a/src/tools/core/mode/mode_singlevar.cc +++ /dev/null @@ -1,329 +0,0 @@ -// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* -// ** 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 -// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* - - -//////////////////////////////////////////////////////////////////////// - - -using namespace std; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mode_usage.h" -#include "mode_exec.h" - -#ifdef WITH_PYTHON -#include "global_python.h" -#endif - - -/////////////////////////////////////////////////////////////////////// -// -// Create output files using the following naming convention: -// -// mode_YYYYMMDDI_FHH_HHA.ps/.txt -// -// Where I indicates initilization time, L indicates lead time, -// and A indicates accumulation time. -// -/////////////////////////////////////////////////////////////////////// - - -extern const char * const program_name; - -static ModeExecutive mode_exec; // gotta make this global ... not sure why - - -/////////////////////////////////////////////////////////////////////// - - -static const char * default_out_dir = "."; - -static int compress_level = -1; - -static int field_index = -1; - - -/////////////////////////////////////////////////////////////////////// - - -static void do_quilt (); -static void do_straight (); - -static void process_command_line(int, char **); - -static void set_config_merge_file (const StringArray &); -static void set_outdir (const StringArray &); -static void set_logfile (const StringArray &); -static void set_verbosity (const StringArray &); -static void set_compress (const StringArray &); - -static void set_field_index (const StringArray &); // undocumented - - -/////////////////////////////////////////////////////////////////////// - - -int main_singlevar(int argc, char * argv []) - -{ - - // - // Process the command line arguments - // - -process_command_line(argc, argv); - - // - // Process the forecast and observation files - // - -ModeConfInfo & conf = mode_exec.engine.conf_info; - -if ( field_index >= 0 ) conf.set_field_index(field_index); - -mode_exec.setup_fcst_obs_data(); - -if (compress_level >= 0) conf.nc_info.set_compress_level(compress_level); - - -if ( conf.quilt ) { - - do_quilt(); - -} else { - - do_straight(); - -} - -mode_exec.clear(); - - // - // done - // - -#ifdef WITH_PYTHON - GP.finalize(); -#endif - -return ( 0 ); - -} - - -/////////////////////////////////////////////////////////////////////// - - -void do_straight() - -{ - -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 ); - -} - -int index; - -for (index=0; index +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "multivar_data.h" +#include "vx_regrid.h" +#include "vx_shapedata.h" + +//////////////////////////////////////////////////////////////////////// + + +static void populate_bool_plane(const string &name, const int * buf, const int nx, const int ny, + BoolPlane & bp_out); + +static void _debug_shape_examine(const string &name, const ShapeData &sd, int nx, int ny); + + +void MultiVarData1::set_fcst_obj(ShapeData *sd) +{ + if (_fcst_obj_sd) { + delete _fcst_obj_sd; + } + _fcst_obj_sd = new ShapeData(*sd); + + if (_fcst_obj_data) { + delete _fcst_obj_data; + } + _fcst_obj_data = _fill_int_array(sd); +} + +void MultiVarData1::set_fcst_raw(ShapeData *sd) +{ + if (_fcst_raw_data) { + delete _fcst_raw_data; + } + _fcst_raw_data = _fill_float_array(sd); + +} + +void MultiVarData1::set_obs_obj(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); + +} + +void MultiVarData1::set_fcst_shapedata(const ShapeData &sd) +{ + if (_Fcst_sd) delete _Fcst_sd; + _Fcst_sd = new ShapeData(sd); +} + +void MultiVarData1::set_obs_shapedata(const ShapeData &sd) +{ + if (_Obs_sd) delete _Obs_sd; + _Obs_sd = new ShapeData(sd); +} + +void MultiVarData1::objects_from_arrays(bool do_clusters, + BoolPlane & fcst_out, + BoolPlane & obs_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); +} + +void MultiVarData1::print(const string &fname, const string &oname) 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); + } else { + mlog << Debug(2) << n << " is empty\n"; + } +} + + +int *MultiVarData1::_fill_int_array(ShapeData *sd) +{ + int *ret = new int [_nx*_ny]; + for (int x=0; x<_nx; ++x) { + for (int y=0; y<_ny; ++y) { + int n = DefaultTO.two_to_one(_nx, _ny, x, y); + if (sd->is_nonzero(x,y) ) { + ret[n] = nint(sd->data(x, y)); + } else { + ret[n] = bad_data_int; + } + } + } + return ret; +} + +float *MultiVarData1::_fill_float_array(ShapeData *sd) +{ + float *ret = new float [_nx*_ny]; + for (int x=0; x<_nx; ++x) { + for (int y=0; y<_ny; ++y) { + int n = DefaultTO.two_to_one(_nx, _ny, x, y); + ret[n] = sd->data(x, y); + } + } + return ret; +} + +void MultiVarData1::_print_summary(const string &name, int *data, const ShapeData &sd) const +{ + vector values; + for (int i=0; i<_nx*_ny; ++i) { + if (data[i] > 0) { + if (find(values.begin(), values.end(), data[i]) == values.end()) { + values.push_back(data[i]); + } + } + } + mlog << Debug(4) << name << " has " << values.size() << " unique values\n"; + _debug_shape_examine(name, sd, _nx, _ny); +} + +MultiVarData::MultiVarData() : + _simple(0), + _merge(0), + _f_name("notset"), + _o_name("notset"), + _nx(0), _ny(0), + _grid(0), + _ftype(FileType_None), + _otype(FileType_None) +{ +} + + +MultiVarData::~MultiVarData() +{ + _clear(); +} + +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() + << "\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, + double data_min, double data_max) +{ + _clear(); + _f_name = fname; + _o_name = oname; + _nx = grid.nx(); + _ny = grid.ny(); + _grid = new Grid(grid); + _ftype = ftype; + _otype = otype; + _funits = funits; + _ounits = ounits; + _flevel = flevel; + _olevel = olevel; + _data_min = data_min; + _data_max = data_max; + _simple = new MultiVarData1(_nx, _ny, "Simple"); + _merge = new MultiVarData1(_nx, _ny, "Merge"); +} + + +void MultiVarData::set_fcst_obj(ShapeData *sd, bool simple) +{ + if (simple) { + _simple->set_fcst_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); + } +} + +void MultiVarData::set_obs_obj(ShapeData *sd, bool simple) +{ + if (simple) { + _simple->set_obs_obj(sd); + } else { + _merge->set_obs_obj(sd); + } +} + +void MultiVarData::set_obs_raw(ShapeData *sd, bool simple) +{ + if (simple) { + _simple->set_obs_raw(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); + } +} + +void MultiVarData::set_obs_shapedata(const ShapeData &sd, bool simple) +{ + if (simple) { + _simple->set_obs_shapedata(sd); + } else { + _merge->set_obs_shapedata(sd); + } +} + +const ShapeData *MultiVarData::fcst_shapedata_ptr(bool simple) const +{ + if (simple) { + return _simple->_Fcst_sd; + } else { + return _merge->_Fcst_sd; + } +} + +const ShapeData *MultiVarData::obs_shapedata_ptr(bool simple) const +{ + if (simple) { + return _simple->_Obs_sd; + } else { + return _merge->_Obs_sd; + } +} + +//////////////////////////////////////////////////////////////////////// + + +void MultiVarData::objects_from_arrays(bool do_clusters, + bool simple, + BoolPlane & fcst_out, + BoolPlane & obs_out) +{ + if (simple) { + _simple->objects_from_arrays(do_clusters, fcst_out, obs_out); + } else { + _merge->objects_from_arrays(do_clusters, fcst_out, obs_out); + } +} + + +//////////////////////////////////////////////////////////////////////// + + + +void MultiVarData::print(void) const +{ + _simple->print(_f_name, _o_name); + _merge->print(_f_name, _o_name); +} + + +//////////////////////////////////////////////////////////////////////// + + +void MultiVarData::_clear() +{ + if (_simple) { + delete _simple; + _simple = 0; + } + if (_merge) { + delete _merge; + _merge = 0; + } + if (_grid) { + delete _grid; + _grid = 0; + } + _nx = _ny = 0; + _ftype = FileType_None; + _otype = FileType_None; +} + + +//////////////////////////////////////////////////////////////////////// + + +void populate_bool_plane(const string &name, const int * buf, const int nx, const int ny, BoolPlane & bp_out) + +{ + + int x, y, n, k; + bool tf; + double nyes=0.0; + double ntotal = (double)(nx*ny); + bp_out.set_size(nx, ny); + + for (x=0; x 0 ); + if (tf) ++nyes; + bp_out.put(tf, x, y); + + } // for y + + } // for x + + mlog << Debug(4) << " Bool plane for " << name << " has " << nyes << " true values\n"; + + return; + +} + + +//////////////////////////////////////////////////////////////////////// + + +static void _debug_shape_examine(const string &name, const ShapeData &sd, int nx, int ny) +{ + vector values; + vector count; + for (int x=0; x::iterator vi; + vi = find(values.begin(), values.end(), v); + if (vi == values.end()) { + values.push_back(v); + count.push_back(1); + } else { + int ii = vi - values.begin(); + count[ii] = count[ii] + 1; + } + } + } + for (size_t i=0; i +#include +#include "shapedata.h" +#include "vx_grid.h" +#include "data_file_type.h" +#include "two_d_array.h" + +class MultiVarData1 { + + private: + + int *_fill_int_array(ShapeData *sd); + float *_fill_float_array(ShapeData *sd); + void _print_summary(const string &name, int *data, const ShapeData &sd) const; + + public: + + inline MultiVarData1(int nx, int ny, const string &name) : + _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) + {} + + 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; + } + + 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 objects_from_arrays(bool do_clusters, + BoolPlane & fcst_out, + BoolPlane & obs_out); + void print(const string &fname, const string &oname) const; + + 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; + int _nx, _ny; +}; + +class MultiVarData { + + private: + + void _clear(); + + public: + + MultiVarData(); + ~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, + 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 print(void) const; + + + MultiVarData1 *_simple; + MultiVarData1 *_merge; + string _f_name; + string _o_name; + int _nx, _ny; + Grid *_grid; + GrdFileType _ftype; + GrdFileType _otype; + string _funits, _ounits; + string _flevel, _olevel; + 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 2d62fb3dc4..087311dd67 100644 --- a/src/tools/core/mode/multivar_frontend.cc +++ b/src/tools/core/mode/multivar_frontend.cc @@ -10,19 +10,10 @@ //////////////////////////////////////////////////////////////////////// -static const char fcst_super_nc_filename [] = "f_super.nc"; -static const char obs_super_nc_filename [] = "o_super.nc"; - static const char mode_default_config [] = "MET_BASE/config/MODEConfig_default"; -static const char super_object_var_name [] = "super"; - static const int dir_creation_mode = 0755; -static const float on_value = (float) 100.0; -static const float off_value = (float) 0.0; - - //////////////////////////////////////////////////////////////////////// @@ -39,6 +30,7 @@ using namespace std; #include #include +#include #include @@ -56,7 +48,8 @@ using namespace std; #include "combine_boolplanes.h" #include "objects_from_netcdf.h" #include "parse_file_list.h" - +#include "mode_frontend.h" +#include "multivar_data.h" using namespace netCDF; @@ -64,12 +57,6 @@ using namespace netCDF; //////////////////////////////////////////////////////////////////////// -extern int mode_frontend(const StringArray &); - - -//////////////////////////////////////////////////////////////////////// - - extern const char * const program_name; @@ -77,6 +64,8 @@ static const char sep [] = "==================================================== static const char tab [] = " "; +// this is hardwired for the multivar case, at least for now + static const bool do_clusters = false; static ModeConfInfo config; @@ -95,260 +84,271 @@ static void set_outdir (const StringArray &); 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); -static void read_config(const string & filename); - -static void run_command(const ConcatString & command); - -static void process_command_line(const StringArray &); +static ConcatString set_multivar_dir(); -static void write_output_nc_file(const char * path, const MetNcFile &, const BoolPlane &); +static MultiVarData *create_simple_objects(int j, int n_files, + const string &fcst_filename, const string &obs_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 process_superobjects(ShapeData &f_result, ShapeData &o_result, + ShapeData &f_merge, ShapeData &o_merge, + int nx, int ny, const ConcatString &dir, + GrdFileType ftype, GrdFileType otype, const Grid &grid, bool has_union); +static void mask_data(const string &name, int nx, int ny, const BoolPlane &mask, DataPlane &data); +static void mask_data_super(const string &name, int nx, int ny, DataPlane &data); -int multivar_frontend(const StringArray & Argv) - -{ - -const int Argc = Argv.n(); +static void read_config(const string & filename); -if ( Argc < 4 ) multivar_usage(); +static void process_command_line(const StringArray &); -int j; -StringArray fcst_filenames; -StringArray obs_filenames; -ConcatString dir; +static int _mkdir(const char *dir); +static void _debug_shape_examine(string &name, const ShapeData &sd, int nx, int ny); -process_command_line(Argv); +//////////////////////////////////////////////////////////////////////// -read_config(config_file); -if ( config.fcst_multivar_logic.empty() ) { +int multivar_frontend(const StringArray & Argv) - mlog << Error << "\n" << program_name - << ": fcst multivar logic not specified!\n\n"; +{ - exit ( 1 ); + const int Argc = Argv.n(); -} + if ( Argc < 4 ) multivar_usage(); + int j, n_files; + StringArray fcst_filenames; + StringArray obs_filenames; + BoolCalc f_calc, o_calc ; -if ( config.obs_multivar_logic.empty() ) { + process_command_line(Argv); - mlog << Error << "\n" << program_name - << ": obs multivar logic not specified!\n\n"; + read_config(config_file); - exit ( 1 ); + multivar_consistency_checks(fcst_filenames, obs_filenames, f_calc, o_calc, n_files); -} + bool has_union = f_calc.has_union() || o_calc.has_union(); - // - // make sure the multivar logic programs are in the config file - // + mlog << Debug(2) << "\n" << sep << "\n"; -fcst_filenames = parse_ascii_file_list(fcst_fof.c_str()); - obs_filenames = parse_ascii_file_list(obs_fof.c_str()); + ConcatString dir = set_multivar_dir(); -if ( fcst_filenames.n() != obs_filenames.n() ) { + // + // do the individual mode runs which produce everything needed to create + // super objects (stored in 'mvd') (both simple and 'merge'). + // - mlog << Error << "\n" << program_name - << ": number of fcst and obs files should be the same!\n\n"; + vector mvd; - exit ( 1 ); + for (j=0; j 0) { + mvd[0]->checkFileTypeConsistency(*mvdi, j); + } + mvd.push_back(mvdi); + mvdi->print(); -const int n_files = fcst_filenames.n(); -ConcatString mode_args; -ConcatString command; -StringArray a, nc_files, mode_argv; -int status; -char junk [256]; + } // for j -mlog << Debug(2) << "\n" << sep << "\n"; + mlog << Debug(2) << "\n finished with individual mode runs " << "\n" << sep << "\n"; // - // check for no inputs + // set the BoolPlane values using the mvd content // -if ( n_files == 0 ) { + 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 << Error << "\n" << program_name - << ": no input forecast files to process!\n\n"; - - exit ( 1 ); + bool simple = true; + for (j=0; jobjects_from_arrays(do_clusters, simple, f_simple_plane[j], o_simple_plane[j]); + } -} + simple = false; + for (j=0; jobjects_from_arrays(do_clusters, simple, f_merge_plane[j], o_merge_plane[j]); + } // - // do the individual mode runs + // combine the objects into super-objects // -for (j=0; j 0 ) dir << outdir << '/'; + 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); - snprintf(junk, sizeof(junk), "%02d", j); - dir << junk; + // might need this for a super object pass, so grab the values + GrdFileType ftype = mvd[0]->_ftype; + GrdFileType otype = mvd[0]->_otype; - if ( ! directory_exists(dir.c_str()) ) { - - mlog << Debug(2) - << program_name << ": creating output directory \"" - << dir << "\"\n\n"; - - status = mkdir(dir.c_str(), dir_creation_mode); - - if ( status < 0 ) { + // might need this for a super passs, so store locally + Grid grid = *(mvd[0]->_grid); - mlog << Error << "\n" << program_name - << ": unable to create output directory \"" - << dir << "\"\n\n"; - exit ( 1 ); + // create ShapeData objects using something from mvd as a template + // shape data with 1's or bad + 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 " + << "empty multivar intensity array, setting to all FALSE \n\n"; + + for (int i=0; i 0 ) dir << outdir; // - // should be 3 arguments left + // test to see of the output directory for this + // mode runs exists, and if not, create it // + if ( ! directory_exists(dir.c_str()) ) { - fcst_fof = cline[0]; - obs_fof = cline[1]; -config_file = cline[2]; + mlog << Debug(2) + << program_name << ": creating output directory \"" + << dir << "\"\n\n"; + status = _mkdir(dir.c_str()); -return; + if ( status < 0 ) { -} + mlog << Error << "\n" << program_name + << ": unable to create output directory \"" + << dir << "\"\n\n"; + exit ( 1 ); + } + } + return dir; +} //////////////////////////////////////////////////////////////////////// - -void write_output_nc_file(const char * path, const MetNcFile & met, const BoolPlane & bp) - +MultiVarData *create_simple_objects(int j, int n_files, const string &fcst_filename, + const string &obs_filename, + const ConcatString &dir) { + ConcatString command; + StringArray a, mode_argv; -NcFile nc; -int x, y, n; -float * data = 0; -const Grid & grid = met.grid; + // + // build the command for running mode + // -mlog << Debug(1) - << "Creating NetCDF Output file: " << path << "\n"; + mode_argv.clear(); + mode_argv.add(mode_path); + mode_argv.add(fcst_filename); + mode_argv.add(obs_filename); + mode_argv.add(config_file); -nc.open(string(path), NcFile::replace, NcFile::classic); + command << cs_erase + << mode_path << ' ' + << fcst_filename << ' ' + << obs_filename << ' ' + << config_file; - // load the data + mode_argv.add("-v"); + char junk [256]; + snprintf(junk, sizeof(junk), "%d", mlog.verbosity_level()); + mode_argv.add(junk); -data = new float [(grid.nx())*(grid.ny())]; + mode_argv.add("-outdir"); + mode_argv.add(dir); -NcDim lat_dim; -NcDim lon_dim; -NcVar var; -const int nx = grid.nx(); -const int ny = grid.ny(); -vector vdim(2); + command << " -v " << mlog.verbosity_level(); + command << " -outdir " << dir; + // + // run the pass1 portions of mode, which creates simple objects + // -for (x=0; xrun(mode_argv, ModeFrontEnd::MULTIVAR_PASS1, j, n_files); + MultiVarData *mvdi = frontend->get_multivar_data(); + delete frontend; - for (y=0; yrun(mode_argv, ModeFrontEnd::MULTIVAR_PASS1_MERGE, j, n_files); + frontend->addMultivarMergePass1(mvdi); + delete frontend; - if ( bp(x, y) ) data[n] = on_value; - else data[n] = off_value; + return mvdi; +} - } // for x +//////////////////////////////////////////////////////////////////////// + +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) +{ + // mask the input data to be valid only inside the simple super objects + + mask_data("Fcst", nx, ny, f_result, mvd._simple->_Fcst_sd->data); + mask_data("Obs", nx, ny, o_result, mvd._simple->_Obs_sd->data); -} // for x + StringArray mode_argv; + char junk [256]; // - // add global attributes and projection information + // build the command for running mode // + mode_argv.clear(); + mode_argv.add(mode_path); + mode_argv.add(config_file); + mode_argv.add("-v"); + snprintf(junk, sizeof(junk), "%d", mlog.verbosity_level()); + mode_argv.add(junk); + mode_argv.add("-outdir"); + mode_argv.add(dir); -write_netcdf_global(&nc, path, program_name); + mlog << Debug(1) << "Running filtered mode \n\n"; - // - // add dimensions and write projection info - // + ModeFrontEnd *frontend = new ModeFrontEnd; + int status = frontend->run_multivar_pass2(mode_argv, mvd, has_union, f_merge, o_merge, j); + delete frontend; +} + +//////////////////////////////////////////////////////////////////////// -write_netcdf_proj(&nc, grid, lat_dim, lon_dim); +void process_superobjects(ShapeData &f_result, ShapeData &o_result, + ShapeData &f_merge, ShapeData &o_merge, + int nx, int ny, const ConcatString &dir, + GrdFileType ftype, GrdFileType otype, const Grid &grid, + bool has_union) +{ + StringArray mode_argv; + char junk [256]; // - // variable + // build the command for running mode // + mode_argv.clear(); + mode_argv.add(mode_path); + mode_argv.add(config_file); + mode_argv.add("-v"); + snprintf(junk, sizeof(junk), "%d", mlog.verbosity_level()); + mode_argv.add(junk); + mode_argv.add("-outdir"); + mode_argv.add(dir); + // mode_argv.add("-field_index"); + // snprintf(junk, sizeof(junk), "%d", j); + // mode_argv.add(junk); -vdim[0] = lat_dim; -vdim[1] = lon_dim; + mlog << Debug(1) << "Running superobject mode \n\n"; -var = nc.addVar(string(super_object_var_name), ncFloat, vdim); + // set the data to 0 inside superobjects and missing everywhere else -var.putVar(data); + mask_data_super("FcstSimple", nx, ny, f_result.data); + mask_data_super("ObsSimple", nx, ny, o_result.data); + - // - // done - // + ModeFrontEnd *frontend = new ModeFrontEnd; + int status = frontend->run_super(mode_argv, f_result, o_result, + f_merge, o_merge, ftype, otype, grid, has_union); + delete frontend; +} + +//////////////////////////////////////////////////////////////////////// + +void mask_data(const string &name, int nx, int ny, const BoolPlane &bp, DataPlane &data) +{ + + if (nx != data.nx() || ny != data.ny()) { + mlog << Error << "\n" << program_name << ":" << name + << " :dimensions don't match " << nx << " " << ny + << " " << data.nx() << " " << data.ny() << "\n\n"; + + exit( 1 ); + } + + int nmasked=0, nkeep=0; + + for (int x=0; x values; + vector count; + for (int x=0; x::iterator vi; + vi = find(values.begin(), values.end(), v); + if (vi == values.end()) { + values.push_back(v); + count.push_back(1); + } else { + int ii = vi - values.begin(); + count[ii] = count[ii] + 1; + } + } + } + for (size_t i=0; i 0 ); + for (y=0; y 0 ); + if (tf) ++nyes; + bp_out.put(tf, x, y); + } // for y + } // for x + mlog << Debug(1) << nyes/ntotal << " of the data was true\n"; -return; + return; } diff --git a/src/tools/core/mode/objects_from_netcdf.h b/src/tools/core/mode/objects_from_netcdf.h index 08be4d1b0e..173939ab04 100644 --- a/src/tools/core/mode/objects_from_netcdf.h +++ b/src/tools/core/mode/objects_from_netcdf.h @@ -23,12 +23,16 @@ //////////////////////////////////////////////////////////////////////// - // - // grabs the objects from a MODE output netcdf file - // +// +// grabs the objects from a MODE output netcdf file +// //////////////////////////////////////////////////////////////////////// +/* extern void objects_from_arrays(bool do_clusters, */ +/* int *fcst_objects, int *obs_objects, int nx, int ny, */ +/* BoolPlane & fcst_out, */ +/* BoolPlane & obs_out); */ extern void objects_from_netcdf(const char * netcdf_filename, diff --git a/src/tools/core/mode/obs_enlarge_page.cc b/src/tools/core/mode/obs_enlarge_page.cc index 15e9ebf4c9..983adad0ba 100644 --- a/src/tools/core/mode/obs_enlarge_page.cc +++ b/src/tools/core/mode/obs_enlarge_page.cc @@ -26,8 +26,8 @@ void ModePsFile::do_obs_enlarge_page(ModeFuzzyEngine & eng, EngineType eng_type, { -double Vtab; -const double Htab_cen = PageWidth/2.0; + double Vtab; + const double Htab_cen = PageWidth/2.0; ///////////////////////////////////////////////////////////////// // @@ -35,11 +35,11 @@ const double Htab_cen = PageWidth/2.0; // ///////////////////////////////////////////////////////////////// -inc_pagenumber(); + inc_pagenumber(); -choose_font(31, 24.0); -write_centered_text(1, 1, Htab_cen, 752.0, 0.5, 0.5, title); -write_centered_text(1, 1, Htab_cen, 722.0, 0.5, 0.5, ObsString.c_str()); + choose_font(31, 24.0); + write_centered_text(1, 1, Htab_cen, 752.0, 0.5, 0.5, title); + write_centered_text(1, 1, Htab_cen, 722.0, 0.5, 0.5, ObsString.c_str()); ///////////////////////////////////////////////////////////////// // @@ -47,13 +47,13 @@ write_centered_text(1, 1, Htab_cen, 722.0, 0.5, 0.5, ObsString.c_str()); // ///////////////////////////////////////////////////////////////// -Vtab = PageHeight - 4.0*Vmargin; -set_view(Vtab - LargePlotHeight, Vtab, Htab_cen); -comment("obs enlarge page: obs raw"); -render_ppm(eng, eng_type, *(eng.obs_raw), 0, 0); -outline_view(); -draw_map( &(eng.conf_info.conf) ); -draw_colorbar(false); + Vtab = PageHeight - 4.0*Vmargin; + set_view(Vtab - LargePlotHeight, Vtab, Htab_cen); + comment("obs enlarge page: obs raw"); + render_ppm(eng, eng_type, *(eng.obs_raw), 0, 0); + outline_view(); + draw_map( &(eng.conf_info.conf) ); + draw_colorbar(false); ///////////////////////////////////////////////////////////////// // @@ -61,13 +61,13 @@ draw_colorbar(false); // ///////////////////////////////////////////////////////////////// -Vtab -= LargePlotHeight; -set_view(Vtab - LargePlotHeight, Vtab, Htab_cen); -comment("obs enlarge page: obs split"); -render_ppm(eng, eng_type, *(eng.obs_split), 0, 1); -outline_view(); -draw_map( &(eng.conf_info.conf) ); -draw_convex_hulls(eng, 0, 0); + Vtab -= LargePlotHeight; + set_view(Vtab - LargePlotHeight, Vtab, Htab_cen); + comment("obs enlarge page: obs split"); + render_ppm(eng, eng_type, *(eng.obs_split), 0, 1); + outline_view(); + draw_map( &(eng.conf_info.conf) ); + draw_convex_hulls(eng, 0, 0); ///////////////////////////////////////////////////////////////// // @@ -75,8 +75,8 @@ draw_convex_hulls(eng, 0, 0); // ///////////////////////////////////////////////////////////////// -showpage(); + showpage(); -return; + return; } diff --git a/src/tools/core/mode/overlap_page.cc b/src/tools/core/mode/overlap_page.cc index 94885cf3b4..7c0c26bdaa 100644 --- a/src/tools/core/mode/overlap_page.cc +++ b/src/tools/core/mode/overlap_page.cc @@ -27,9 +27,9 @@ void ModePsFile::do_overlap_page(ModeFuzzyEngine & eng, EngineType eng_type, con { -double Vtab; -const double Htab_cen = PageWidth/2.0; -ConcatString tmp_str; + double Vtab; + const double Htab_cen = PageWidth/2.0; + ConcatString tmp_str; ///////////////////////////////////////////////////////////////// // @@ -37,7 +37,7 @@ ConcatString tmp_str; // ///////////////////////////////////////////////////////////////// -inc_pagenumber(); + inc_pagenumber(); ///////////////////////////////////////////////////////////////// // @@ -45,19 +45,19 @@ inc_pagenumber(); // ///////////////////////////////////////////////////////////////// -Vtab = PageHeight - 2.0*Vmargin; -set_view(Vtab - LargePlotHeight, Vtab, Htab_cen); + Vtab = PageHeight - 2.0*Vmargin; + set_view(Vtab - LargePlotHeight, Vtab, Htab_cen); -tmp_str << cs_erase << FcstString << " Objects with " << ObsString << " Outlines"; -choose_font(31, 24.0); -write_centered_text(1, 1, Htab_cen, View_box.top() + TextSep/2.0, - 0.5, 0.5, tmp_str.c_str()); + tmp_str << cs_erase << FcstString << " Objects with " << ObsString << " Outlines"; + choose_font(31, 24.0); + write_centered_text(1, 1, Htab_cen, View_box.top() + TextSep/2.0, + 0.5, 0.5, tmp_str.c_str()); -comment("overlap page: fcst objects with obs boundaries"); -render_ppm(eng, eng_type, *(eng.fcst_split), 1, 1); -outline_view(); -draw_map( &(eng.conf_info.conf) ); -draw_boundaries(eng, 0); + comment("overlap page: fcst objects with obs boundaries"); + render_ppm(eng, eng_type, *(eng.fcst_split), 1, 1); + outline_view(); + draw_map( &(eng.conf_info.conf) ); + draw_boundaries(eng, 0); ///////////////////////////////////////////////////////////////// // @@ -65,19 +65,19 @@ draw_boundaries(eng, 0); // ///////////////////////////////////////////////////////////////// -Vtab = Vtab - LargePlotHeight - 2.0*Vmargin; -set_view(Vtab - LargePlotHeight, Vtab, Htab_cen); + Vtab = Vtab - LargePlotHeight - 2.0*Vmargin; + set_view(Vtab - LargePlotHeight, Vtab, Htab_cen); -tmp_str << cs_erase << ObsString << " Objects with " << FcstString << " Outlines"; -choose_font(31, 24.0); -write_centered_text(1, 1, Htab_cen, View_box.top() + TextSep/2.0, - 0.5, 0.5, tmp_str.c_str()); + tmp_str << cs_erase << ObsString << " Objects with " << FcstString << " Outlines"; + choose_font(31, 24.0); + write_centered_text(1, 1, Htab_cen, View_box.top() + TextSep/2.0, + 0.5, 0.5, tmp_str.c_str()); -comment("overlap page: obs objects with fcst boundaries"); -render_ppm(eng, eng_type, *(eng.obs_split), 0, 1); -outline_view(); -draw_map( &(eng.conf_info.conf) ); -draw_boundaries(eng, 1); + comment("overlap page: obs objects with fcst boundaries"); + render_ppm(eng, eng_type, *(eng.obs_split), 0, 1); + outline_view(); + draw_map( &(eng.conf_info.conf) ); + draw_boundaries(eng, 1); ///////////////////////////////////////////////////////////////// // @@ -85,9 +85,9 @@ draw_boundaries(eng, 1); // ///////////////////////////////////////////////////////////////// -showpage(); + showpage(); -return; + return; } diff --git a/src/tools/core/mode/page_1.cc b/src/tools/core/mode/page_1.cc index d03fa2f1ff..bd7a1ee74f 100644 --- a/src/tools/core/mode/page_1.cc +++ b/src/tools/core/mode/page_1.cc @@ -42,14 +42,14 @@ void ModePsFile::do_page_1(ModeFuzzyEngine & eng, EngineType eng_type, const cha { -int j; -const int buf_len = 1024; -char junk[buf_len + 1]; -ConcatString label, thresh_str; -ConcatString tmp1_str, tmp2_str, tmp3_str; -int i, mon, day, yr, hr, minute, sec; -unixtime t; -const char *method_name = "ModePsFile::do_page_1()"; + int j; + const int buf_len = 1024; + char junk[buf_len + 1]; + ConcatString label, thresh_str; + ConcatString tmp1_str, tmp2_str, tmp3_str; + int i, mon, day, yr, hr, minute, sec; + unixtime t; + const char *method_name = "ModePsFile::do_page_1()"; //////////////////////////////////////////////////////////////////// // @@ -57,21 +57,21 @@ const char *method_name = "ModePsFile::do_page_1()"; // //////////////////////////////////////////////////////////////////// -inc_pagenumber(); + inc_pagenumber(); -set_family(ff_Palatino); + set_family(ff_Palatino); -setlinecap(1); -setlinejoin(1); + setlinecap(1); + setlinejoin(1); -choose_font(31, 24.0); + choose_font(31, 24.0); -write_centered_text(1, 1, 306.0, 752.0, 0.5, 0.5, title); + write_centered_text(1, 1, 306.0, 752.0, 0.5, 0.5, title); -choose_font(31, 18.0); + choose_font(31, 18.0); -write_centered_text(1, 1, Htab_1, 727.0, 0.5, 0.5, FcstString.c_str()); -write_centered_text(1, 1, Htab_2, 727.0, 0.5, 0.5, ObsString.c_str()); + write_centered_text(1, 1, Htab_1, 727.0, 0.5, 0.5, FcstString.c_str()); + write_centered_text(1, 1, Htab_2, 727.0, 0.5, 0.5, ObsString.c_str()); //////////////////////////////////////////////////////////////////// // @@ -79,11 +79,11 @@ write_centered_text(1, 1, Htab_2, 727.0, 0.5, 0.5, ObsString.c_str()); // //////////////////////////////////////////////////////////////////// -set_view(Vtab_1, Vtab_1 + SmallPlotHeight, Htab_1); -comment("fcst raw"); -render_ppm( eng, eng_type, *(eng.fcst_raw), 1, 0); -outline_view(); -draw_map( &(eng.conf_info.conf) ); + set_view(Vtab_1, Vtab_1 + SmallPlotHeight, Htab_1); + comment("fcst raw"); + render_ppm( eng, eng_type, *(eng.fcst_raw), 1, 0); + outline_view(); + draw_map( &(eng.conf_info.conf) ); //////////////////////////////////////////////////////////////////// // @@ -91,11 +91,11 @@ draw_map( &(eng.conf_info.conf) ); // //////////////////////////////////////////////////////////////////// -set_view(Vtab_1, Vtab_1 + SmallPlotHeight, Htab_2); -comment("obs raw"); -render_ppm(eng, eng_type, *(eng.obs_raw), 0, 0); -outline_view(); -draw_map( &(eng.conf_info.conf) ); + set_view(Vtab_1, Vtab_1 + SmallPlotHeight, Htab_2); + comment("obs raw"); + render_ppm(eng, eng_type, *(eng.obs_raw), 0, 0); + outline_view(); + draw_map( &(eng.conf_info.conf) ); //////////////////////////////////////////////////////////////////// // @@ -103,12 +103,12 @@ draw_map( &(eng.conf_info.conf) ); // //////////////////////////////////////////////////////////////////// -set_view(Vtab_2, Vtab_2 + SmallPlotHeight, Htab_1); -comment("fcst split"); -render_ppm(eng, eng_type, *(eng.fcst_split), 1, 1); -outline_view(); -draw_map( &(eng.conf_info.conf) ); -draw_convex_hulls(eng, 1, 0); + set_view(Vtab_2, Vtab_2 + SmallPlotHeight, Htab_1); + comment("fcst split"); + render_ppm(eng, eng_type, *(eng.fcst_split), 1, 1); + outline_view(); + draw_map( &(eng.conf_info.conf) ); + draw_convex_hulls(eng, 1, 0); //////////////////////////////////////////////////////////////////// // @@ -116,12 +116,12 @@ draw_convex_hulls(eng, 1, 0); // //////////////////////////////////////////////////////////////////// -set_view(Vtab_2, Vtab_2 + SmallPlotHeight, Htab_2); -comment("obs split"); -render_ppm(eng, eng_type, *eng.obs_split, 0, 1); -outline_view(); -draw_map( &(eng.conf_info.conf) ); -draw_convex_hulls(eng, 0, 0); + set_view(Vtab_2, Vtab_2 + SmallPlotHeight, Htab_2); + comment("obs split"); + render_ppm(eng, eng_type, *eng.obs_split, 0, 1); + outline_view(); + draw_map( &(eng.conf_info.conf) ); + draw_convex_hulls(eng, 0, 0); //////////////////////////////////////////////////////////////////// // @@ -129,10 +129,10 @@ draw_convex_hulls(eng, 0, 0); // //////////////////////////////////////////////////////////////////// -set_view(Vtab_3, Vtab_3 + SmallPlotHeight, Htab_1); -outline_view(); -draw_map( &(eng.conf_info.conf) ); -plot_simple_ids(eng, 1); + set_view(Vtab_3, Vtab_3 + SmallPlotHeight, Htab_1); + outline_view(); + draw_map( &(eng.conf_info.conf) ); + plot_simple_ids(eng, 1); //////////////////////////////////////////////////////////////////// // @@ -140,10 +140,10 @@ plot_simple_ids(eng, 1); // //////////////////////////////////////////////////////////////////// -set_view(Vtab_3, Vtab_3 + SmallPlotHeight, Htab_2); -outline_view(); -draw_map( &(eng.conf_info.conf) ); -plot_simple_ids(eng, 0); + set_view(Vtab_3, Vtab_3 + SmallPlotHeight, Htab_2); + outline_view(); + draw_map( &(eng.conf_info.conf) ); + plot_simple_ids(eng, 0); //////////////////////////////////////////////////////////////////// // @@ -151,81 +151,81 @@ plot_simple_ids(eng, 0); // //////////////////////////////////////////////////////////////////// -choose_font(31, 11.0); + choose_font(31, 11.0); -setlinewidth(0.2); + setlinewidth(0.2); -text_y = 727.0 - 1.5*TextSep; + text_y = 727.0 - 1.5*TextSep; -TableHelper t0; -double x; -int r, c, n; -int bad_count; -double table_width = 130.0; + TableHelper t0; + double x; + int r, c, n; + int bad_count; + double table_width = 130.0; -n = (eng.n_fcst)*(eng.n_obs); + n = (eng.n_fcst)*(eng.n_obs); -if ( n > max_interest_rows ) n = max_interest_rows; + if ( n > max_interest_rows ) n = max_interest_rows; -t0.set(*this, n + 1, 3); + t0.set(*this, n + 1, 3); -for (j=0; j<(t0.nrows()); ++j) t0.set_row_height(j, 15.0); + for (j=0; j<(t0.nrows()); ++j) t0.set_row_height(j, 15.0); -t0.set_col_width(2, 50.0); -t0.set_col_width(0, 0.5*(table_width - t0.col_width(2))); -t0.set_col_width(1, t0.col_width(0)); + t0.set_col_width(2, 50.0); + t0.set_col_width(0, 0.5*(table_width - t0.col_width(2))); + t0.set_col_width(1, t0.col_width(0)); -t0.set_pin(Htab_3, Vtab_1 + SmallPlotHeight + TextSep, 0.0, 1.0); + t0.set_pin(Htab_3, Vtab_1 + SmallPlotHeight + TextSep, 0.0, 1.0); -t0.fill_row(0, light_green); + t0.fill_row(0, light_green); -bad_count = 0; + bad_count = 0; -for(i=0; ivar_info->name_attr().c_str()); -t1.write_xy1_to_cell(2, 2, dx, dy, 0.0, 0.0, eng.conf_info.Obs->var_info->name_attr().c_str()); + t1.write_xy1_to_cell(2, 1, dx, dy, 0.0, 0.0, eng.conf_info.Fcst->var_info->name_attr().c_str()); + t1.write_xy1_to_cell(2, 2, dx, dy, 0.0, 0.0, eng.conf_info.Obs->var_info->name_attr().c_str()); // // Level Name // -nextline(); + nextline(); -t1.write_xy1_to_cell(3, 1, dx, dy, 0.0, 0.0, eng.conf_info.Fcst->var_info->level_attr().c_str()); -t1.write_xy1_to_cell(3, 2, dx, dy, 0.0, 0.0, eng.conf_info.Obs->var_info->level_attr().c_str()); + t1.write_xy1_to_cell(3, 1, dx, dy, 0.0, 0.0, eng.conf_info.Fcst->var_info->level_attr().c_str()); + t1.write_xy1_to_cell(3, 2, dx, dy, 0.0, 0.0, eng.conf_info.Obs->var_info->level_attr().c_str()); // // Units // -nextline(); + nextline(); -t1.write_xy1_to_cell(4, 1, dx, dy, 0.0, 0.0, eng.conf_info.Fcst->var_info->units_attr().c_str()); -t1.write_xy1_to_cell(4, 2, dx, dy, 0.0, 0.0, eng.conf_info.Obs->var_info->units_attr().c_str()); + t1.write_xy1_to_cell(4, 1, dx, dy, 0.0, 0.0, eng.conf_info.Fcst->var_info->units_attr().c_str()); + t1.write_xy1_to_cell(4, 2, dx, dy, 0.0, 0.0, eng.conf_info.Obs->var_info->units_attr().c_str()); // // Initialization Time // -t = eng.fcst_raw->data.valid() - eng.fcst_raw->data.lead(); + t = eng.fcst_raw->data.valid() - eng.fcst_raw->data.lead(); -unix_to_mdyhms(t, mon, day, yr, hr, minute, sec); + unix_to_mdyhms(t, mon, day, yr, hr, minute, sec); -snprintf(junk, sizeof(junk), "%04d %02d %02d", yr, mon, day); + snprintf(junk, sizeof(junk), "%04d %02d %02d", yr, mon, day); -t1.write_xy1_to_cell(5, 1, dx, dy, 0.0, 0.0, junk); + t1.write_xy1_to_cell(5, 1, dx, dy, 0.0, 0.0, junk); -snprintf(junk, sizeof(junk), "%02d:%.02d:%02d", hr, minute, sec); + snprintf(junk, sizeof(junk), "%02d:%.02d:%02d", hr, minute, sec); -t1.write_xy1_to_cell(6, 1, dx, dy, 0.0, 0.0, junk); + t1.write_xy1_to_cell(6, 1, dx, dy, 0.0, 0.0, junk); -t = eng.obs_raw->data.valid() - eng.obs_raw->data.lead(); + t = eng.obs_raw->data.valid() - eng.obs_raw->data.lead(); -unix_to_mdyhms(t, mon, day, yr, hr, minute, sec); + unix_to_mdyhms(t, mon, day, yr, hr, minute, sec); -snprintf(junk, sizeof(junk), "%04d %02d %02d", yr, mon, day); -t1.write_xy1_to_cell(5, 2, dx, dy, 0.0, 0.0, junk); -snprintf(junk, sizeof(junk), "%02d:%02d:%02d", hr, minute, sec); -t1.write_xy1_to_cell(6, 2, dx, dy, 0.0, 0.0, junk); -text_y -= 2.0*TextSep; + snprintf(junk, sizeof(junk), "%04d %02d %02d", yr, mon, day); + t1.write_xy1_to_cell(5, 2, dx, dy, 0.0, 0.0, junk); + snprintf(junk, sizeof(junk), "%02d:%02d:%02d", hr, minute, sec); + t1.write_xy1_to_cell(6, 2, dx, dy, 0.0, 0.0, junk); + text_y -= 2.0*TextSep; // // Valid time // -t = eng.fcst_raw->data.valid(); + t = eng.fcst_raw->data.valid(); -unix_to_mdyhms(t, mon, day, yr, hr, minute, sec); + unix_to_mdyhms(t, mon, day, yr, hr, minute, sec); -snprintf(junk, sizeof(junk), "%04d %02d %02d", yr, mon, day); + snprintf(junk, sizeof(junk), "%04d %02d %02d", yr, mon, day); -t1.write_xy1_to_cell(7, 1, dx, dy, 0.0, 0.0, junk); + t1.write_xy1_to_cell(7, 1, dx, dy, 0.0, 0.0, junk); -snprintf(junk, sizeof(junk), "%02d:%02d:%02d", hr, minute, sec); + snprintf(junk, sizeof(junk), "%02d:%02d:%02d", hr, minute, sec); -t1.write_xy1_to_cell(8, 1, dx, dy, 0.0, 0.0, junk); + t1.write_xy1_to_cell(8, 1, dx, dy, 0.0, 0.0, junk); -t = eng.obs_raw->data.valid(); + t = eng.obs_raw->data.valid(); -unix_to_mdyhms(t, mon, day, yr, hr, minute, sec); + unix_to_mdyhms(t, mon, day, yr, hr, minute, sec); -snprintf(junk, sizeof(junk), "%04d %02d %02d", yr, mon, day); + snprintf(junk, sizeof(junk), "%04d %02d %02d", yr, mon, day); -t1.write_xy1_to_cell(7, 2, dx, dy, 0.0, 0.0, junk); + t1.write_xy1_to_cell(7, 2, dx, dy, 0.0, 0.0, junk); -snprintf(junk, sizeof(junk), "%02d:%02d:%02d", hr, minute, sec); + snprintf(junk, sizeof(junk), "%02d:%02d:%02d", hr, minute, sec); -t1.write_xy1_to_cell(8, 2, dx, dy, 0.0, 0.0, junk); + t1.write_xy1_to_cell(8, 2, dx, dy, 0.0, 0.0, junk); -text_y -= 2.0*TextSep; + text_y -= 2.0*TextSep; // // Accumulation time // -m_strncpy(junk, sec_to_hhmmss_colon(eng.fcst_raw->data.accum()).c_str(), - buf_len, method_name, "fcst_raw->data.accum()"); -t1.write_xy1_to_cell(9, 1, dx, dy, 0.0, 0.0, junk); + m_strncpy(junk, sec_to_hhmmss_colon(eng.fcst_raw->data.accum()).c_str(), + buf_len, method_name, "fcst_raw->data.accum()"); + t1.write_xy1_to_cell(9, 1, dx, dy, 0.0, 0.0, junk); -m_strncpy(junk, sec_to_hhmmss_colon(eng.obs_raw->data.accum()).c_str(), - buf_len, method_name, "obs_raw->data.accum()"); -t1.write_xy1_to_cell(9, 2, dx, dy, 0.0, 0.0, junk); -nextline(); + m_strncpy(junk, sec_to_hhmmss_colon(eng.obs_raw->data.accum()).c_str(), + buf_len, method_name, "obs_raw->data.accum()"); + t1.write_xy1_to_cell(9, 2, dx, dy, 0.0, 0.0, junk); + nextline(); //////////////////////////////////////////////////////////////////// // @@ -428,140 +428,140 @@ nextline(); // //////////////////////////////////////////////////////////////////// -choose_font(31, 11.0); + choose_font(31, 11.0); -nextline(); + nextline(); -Htab_a = Htab_1 - 0.5*View_box.width(); -Htab_b = Htab_a + 8.0*TextSep; -Htab_c = Htab_a + 11.0*TextSep; + Htab_a = Htab_1 - 0.5*View_box.width(); + Htab_b = Htab_a + 8.0*TextSep; + Htab_c = Htab_a + 11.0*TextSep; -TableHelper t2; + TableHelper t2; -t2.set(*this, 6, 3); + t2.set(*this, 6, 3); -for (j=0; j<(t2.nrows()); ++j) t2.set_row_height(j, 15.0); + for (j=0; j<(t2.nrows()); ++j) t2.set_row_height(j, 15.0); -t2.set_col_width(0, 135.0); -t2.set_col_width(1, 0.5*(t1.width() - t2.col_width(0))); -t2.set_col_width(2, t2.col_width(1)); + t2.set_col_width(0, 135.0); + t2.set_col_width(1, 0.5*(t1.width() - t2.col_width(0))); + t2.set_col_width(2, t2.col_width(1)); -t2.set_pin(t1.left(), t1.bottom() - 15.0, 0.0, 1.0); + t2.set_pin(t1.left(), t1.bottom() - 15.0, 0.0, 1.0); -r = 1; + r = 1; -for (j=0; j<(t2.nrows()); ++j) { + for (j=0; j<(t2.nrows()); ++j) { - if ( j%2 ) t2.fill_cell(j, 0, blue2); - else t2.fill_cell(j, 0, blue1); + if ( j%2 ) t2.fill_cell(j, 0, blue2); + else t2.fill_cell(j, 0, blue1); -} + } -t2.fill_cell(r, 1, light_gray); t2.fill_cell(r, 2, light_gray); r+=2; -t2.fill_cell(r, 1, light_gray); t2.fill_cell(r, 2, light_gray); // r+=2; + t2.fill_cell(r, 1, light_gray); t2.fill_cell(r, 2, light_gray); r+=2; + t2.fill_cell(r, 1, light_gray); t2.fill_cell(r, 2, light_gray); // r+=2; -r = 0; + r = 0; -line(t2.left(), t2.row_bottom(r), t2.right(), t2.row_bottom(r)); ++r; -line(t2.left(), t2.row_bottom(r), t2.right(), t2.row_bottom(r)); ++r; -line(t2.left(), t2.row_bottom(r), t2.right(), t2.row_bottom(r)); ++r; -line(t2.left(), t2.row_bottom(r), t2.right(), t2.row_bottom(r)); ++r; -line(t2.left(), t2.row_bottom(r), t2.right(), t2.row_bottom(r)); ++r; + line(t2.left(), t2.row_bottom(r), t2.right(), t2.row_bottom(r)); ++r; + line(t2.left(), t2.row_bottom(r), t2.right(), t2.row_bottom(r)); ++r; + line(t2.left(), t2.row_bottom(r), t2.right(), t2.row_bottom(r)); ++r; + line(t2.left(), t2.row_bottom(r), t2.right(), t2.row_bottom(r)); ++r; + line(t2.left(), t2.row_bottom(r), t2.right(), t2.row_bottom(r)); ++r; -c = 0; + c = 0; -line(t2.col_right(c), t2.top(), t2.col_right(c), t2.bottom()); ++c; + line(t2.col_right(c), t2.top(), t2.col_right(c), t2.bottom()); ++c; -line(t2.col_right(c), t2.top(), t2.col_right(c), t2.row_top(t2.nrows() - 1)); ++c; + line(t2.col_right(c), t2.top(), t2.col_right(c), t2.row_top(t2.nrows() - 1)); ++c; -t2.outline_table(0.2, black); + t2.outline_table(0.2, black); -bold(); + bold(); -r = 0; + r = 0; -c = 0; + c = 0; -t2.write_xy1_to_cell(r++, c, dx, dy, 0.0, 0.0, "Centroid/Boundary"); -t2.write_xy1_to_cell(r++, c, dx, dy, 0.0, 0.0, "Convex Hull/Angle"); -t2.write_xy1_to_cell(r++, c, dx, dy, 0.0, 0.0, "Aspect/Area"); -t2.write_xy1_to_cell(r++, c, dx, dy, 0.0, 0.0, "Int Area/Curvature"); -t2.write_xy1_to_cell(r++, c, dx, dy, 0.0, 0.0, "Complexity/Intensity"); -t2.write_xy1_to_cell(r++, c, dx, dy, 0.0, 0.0, "Total Interest Thresh"); + t2.write_xy1_to_cell(r++, c, dx, dy, 0.0, 0.0, "Centroid/Boundary"); + t2.write_xy1_to_cell(r++, c, dx, dy, 0.0, 0.0, "Convex Hull/Angle"); + t2.write_xy1_to_cell(r++, c, dx, dy, 0.0, 0.0, "Aspect/Area"); + t2.write_xy1_to_cell(r++, c, dx, dy, 0.0, 0.0, "Int Area/Curvature"); + t2.write_xy1_to_cell(r++, c, dx, dy, 0.0, 0.0, "Complexity/Intensity"); + t2.write_xy1_to_cell(r++, c, dx, dy, 0.0, 0.0, "Total Interest Thresh"); // // Centroid and Boundary Distance Weights // -roman(); + roman(); -r = 0; + r = 0; -snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.centroid_dist_wt); -t2.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); + snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.centroid_dist_wt); + t2.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); -snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.boundary_dist_wt); -t2.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); -++r; -nextline(); + snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.boundary_dist_wt); + t2.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); + ++r; + nextline(); // // Convex Hull Distance and Angle Difference Weights // -snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.convex_hull_dist_wt); -t2.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); + snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.convex_hull_dist_wt); + t2.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); -snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.angle_diff_wt); -t2.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); -++r; -nextline(); + snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.angle_diff_wt); + t2.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); + ++r; + nextline(); // // Aspect Ratio Difference and Area Ratio Weights // -snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.aspect_diff_wt); -t2.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); + snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.aspect_diff_wt); + t2.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); -snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.area_ratio_wt); -t2.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); -++r; -nextline(); + snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.area_ratio_wt); + t2.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); + ++r; + nextline(); // // Intesection Over Minimum Area Weights and Curvature Ratio Weights // -snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.int_area_ratio_wt); -t2.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); + snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.int_area_ratio_wt); + t2.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); -snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.curvature_ratio_wt); -t2.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); -++r; -nextline(); + snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.curvature_ratio_wt); + t2.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); + ++r; + nextline(); // // Complexity Ratio and Intensity Ratio Weights // -snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.complexity_ratio_wt); -t2.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); + snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.complexity_ratio_wt); + t2.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); -snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.inten_perc_ratio_wt); -t2.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); -++r; -nextline(); + snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.inten_perc_ratio_wt); + t2.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); + ++r; + nextline(); // // Total Interest Threshold // -snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.total_interest_thresh); + snprintf(junk, sizeof(junk), "%.2f", eng.conf_info.total_interest_thresh); -t2.write_xy1_to_cell(r, 2, 0.0, dy, 0.5, 0.0, junk); + t2.write_xy1_to_cell(r, 2, 0.0, dy, 0.5, 0.0, junk); -nextline(); + nextline(); //////////////////////////////////////////////////////////////////// // @@ -569,19 +569,19 @@ nextline(); // //////////////////////////////////////////////////////////////////// -choose_font(31, 11.0); + choose_font(31, 11.0); -text_y = Vtab_3 - 1.0*TextSep; -Htab_a = Htab_2 - 0.5*View_box.width(); -Htab_b = Htab_a + 5.0*TextSep; -Htab_c = Htab_a + 10.0*TextSep; + text_y = Vtab_3 - 1.0*TextSep; + Htab_a = Htab_2 - 0.5*View_box.width(); + Htab_b = Htab_a + 5.0*TextSep; + Htab_c = Htab_a + 10.0*TextSep; -if ( eng_type == FOEng ) do_page_1_FOEng (eng, eng_type, title); -else do_page_1_other (eng, eng_type, title); + if ( eng_type == FOEng ) do_page_1_FOEng (eng, eng_type, title); + else do_page_1_other (eng, eng_type, title); -showpage(); + showpage(); -return; + return; } @@ -593,332 +593,332 @@ void ModePsFile::do_page_1_FOEng(ModeFuzzyEngine & eng, EngineType eng_type, con { -int j, r; -char junk[1024]; -ConcatString label, thresh_str; -ConcatString tmp1_str, tmp2_str, tmp3_str; -double v; -double x, y; -TableHelper t; -const double w = 240.0; + int j, r; + char junk[1024]; + ConcatString label, thresh_str; + ConcatString tmp1_str, tmp2_str, tmp3_str; + double v; + double x, y; + TableHelper t; + const double w = 240.0; -t.set(*this, 15, 3); + t.set(*this, 15, 3); -for (j=0; j<(t.nrows()); ++j) t.set_row_height(j, 15.0); + for (j=0; j<(t.nrows()); ++j) t.set_row_height(j, 15.0); -t.set_col_width(0, 100.0); -t.set_col_width(1, 0.5*(w - t.col_width(0))); -t.set_col_width(2, t.col_width(1)); + t.set_col_width(0, 100.0); + t.set_col_width(1, 0.5*(w - t.col_width(0))); + t.set_col_width(2, t.col_width(1)); -t.set_pin(Htab_a, Vtab_3 - 2.0, 0.0, 1.0); + t.set_pin(Htab_a, Vtab_3 - 2.0, 0.0, 1.0); -for (j=1; j<(t.nrows()); ++j) { + for (j=1; j<(t.nrows()); ++j) { - if ( j%2 ) t.fill_cell(j, 0, blue1); - else t.fill_cell(j, 0, blue2); + if ( j%2 ) t.fill_cell(j, 0, blue1); + else t.fill_cell(j, 0, blue2); -} + } -t.fill_cell(0, 1, light_green); -t.fill_cell(0, 2, light_green); + t.fill_cell(0, 1, light_green); + t.fill_cell(0, 2, light_green); -t.fill_cell(0, 0, dark_gray); + t.fill_cell(0, 0, dark_gray); -for (j=2; j<(t.nrows()); j+=2) { + for (j=2; j<(t.nrows()); j+=2) { - t.fill_cell(j, 1, light_gray); - t.fill_cell(j, 2, light_gray); + t.fill_cell(j, 1, light_gray); + t.fill_cell(j, 2, light_gray); -} + } -for (j=0; j<(t.nrows() - 1); ++j) { + for (j=0; j<(t.nrows() - 1); ++j) { - y = t.row_bottom(j); + y = t.row_bottom(j); - line(t.left(), y, t.right(), y); + line(t.left(), y, t.right(), y); -} + } -x = t.col_right(0); + x = t.col_right(0); -line(x, t.top(), x, t.bottom()); + line(x, t.top(), x, t.bottom()); -x = t.col_right(1); + x = t.col_right(1); -line(x, t.top(), x, t.row_bottom(4)); + line(x, t.top(), x, t.row_bottom(4)); -line(x, t.row_bottom(5), x, t.row_bottom(7)); + line(x, t.row_bottom(5), x, t.row_bottom(7)); -line(x, t.row_bottom(8), x, t.row_bottom(13)); + line(x, t.row_bottom(8), x, t.row_bottom(13)); -t.outline_table(0.2, black); + t.outline_table(0.2, black); -bold(); + bold(); -t.write_xy1_to_cell(0, 1, dx, dy, 0.0, 0.0, FcstString.c_str()); -t.write_xy1_to_cell(0, 2, dx, dy, 0.0, 0.0, ObsString.c_str()); + t.write_xy1_to_cell(0, 1, dx, dy, 0.0, 0.0, FcstString.c_str()); + t.write_xy1_to_cell(0, 2, dx, dy, 0.0, 0.0, ObsString.c_str()); -j = 1; + j = 1; -t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Mask M/G/P"); -t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Conv Radius"); -t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Conv Thresh"); -t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Obj Filters"); -t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Inten Perc"); -t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Merge Thresh"); -t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Merging"); -t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Matching"); -t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Simple/M/U"); -t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Area"); -t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Area M/U"); -t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Cluster"); -t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "MMI"); -t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "MMI (F+O)"); + t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Mask M/G/P"); + t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Conv Radius"); + t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Conv Thresh"); + t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Obj Filters"); + t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Inten Perc"); + t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Merge Thresh"); + t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Merging"); + t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Matching"); + t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Simple/M/U"); + t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Area"); + t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Area M/U"); + t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "Cluster"); + t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "MMI"); + t.write_xy1_to_cell(j++, 0, dx, dy, 0.0, 0.0, "MMI (F+O)"); // // Field name // -nextline(); - -r = 1; - -roman(); - - // - // Mask missing, grid, and polyline Flags - // - // write_centered_text(1, 1, Htab_a, text_y, 0.0, 0.5, "Mask M/G/P:"); - if(eng.conf_info.mask_missing_flag == FieldType_Both || - eng.conf_info.mask_missing_flag == FieldType_Fcst) tmp1_str = "on"; - else tmp1_str = "off"; - if(eng.conf_info.mask_grid_flag == FieldType_Both || - eng.conf_info.mask_grid_flag == FieldType_Fcst) tmp2_str = "on"; - else tmp2_str = "off"; - if(eng.conf_info.mask_grid_flag == FieldType_Both || - eng.conf_info.mask_grid_flag == FieldType_Fcst) tmp3_str = "on"; - else tmp3_str = "off"; - label << cs_erase << tmp1_str << '/' << tmp2_str << '/' << tmp3_str; - t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, label.c_str()); - - if(eng.conf_info.mask_missing_flag == FieldType_Both || - eng.conf_info.mask_missing_flag == FieldType_Obs) tmp1_str = "on"; - else tmp1_str = "off"; - if(eng.conf_info.mask_grid_flag == FieldType_Both || - eng.conf_info.mask_grid_flag == FieldType_Obs) tmp2_str = "on"; - else tmp2_str = "off"; - if(eng.conf_info.mask_grid_flag == FieldType_Both || - eng.conf_info.mask_grid_flag == FieldType_Obs) tmp3_str = "on"; - else tmp3_str = "off"; - label << cs_erase << tmp1_str << '/' << tmp2_str << '/' << tmp3_str; - t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, label.c_str()); - - ++r; - nextline(); - - // - // Convolution Radius - // - snprintf(junk, sizeof(junk), "%d", eng.conf_info.Fcst->conv_radius); - t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); - - snprintf(junk, sizeof(junk), "%d", eng.conf_info.Obs->conv_radius); - t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); - - ++r; - nextline(); - - // - // Convolution Threshold - // - thresh_str = eng.conf_info.Fcst->conv_thresh.get_str(2); - t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, thresh_str.c_str()); - - thresh_str = eng.conf_info.Obs->conv_thresh.get_str(2); - t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, thresh_str.c_str()); - - ++r; - nextline(); - - // - // Object Filters - // - - snprintf(junk, sizeof(junk), "%i", (int) eng.conf_info.Fcst->filter_attr_map.size()); - t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); - - snprintf(junk, sizeof(junk), "%i", (int) eng.conf_info.Obs->filter_attr_map.size()); - t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); - - ++r; - nextline(); - - // - // Intensity Percentile - // - - if(nint(eng.conf_info.inten_perc_value) == 101) label = "mean"; - else if(nint(eng.conf_info.inten_perc_value) == 102) label = "sum"; - else { - snprintf(junk, sizeof(junk), "p%d", eng.conf_info.inten_perc_value); - label = junk; - } - t.write_xy1_to_cell(r, 2, 0.0, dy, 0.5, 0.0, label.c_str()); + nextline(); + + r = 1; + + roman(); + + // + // Mask missing, grid, and polyline Flags + // + // write_centered_text(1, 1, Htab_a, text_y, 0.0, 0.5, "Mask M/G/P:"); + if(eng.conf_info.mask_missing_flag == FieldType_Both || + eng.conf_info.mask_missing_flag == FieldType_Fcst) tmp1_str = "on"; + else tmp1_str = "off"; + if(eng.conf_info.mask_grid_flag == FieldType_Both || + eng.conf_info.mask_grid_flag == FieldType_Fcst) tmp2_str = "on"; + else tmp2_str = "off"; + if(eng.conf_info.mask_grid_flag == FieldType_Both || + eng.conf_info.mask_grid_flag == FieldType_Fcst) tmp3_str = "on"; + else tmp3_str = "off"; + label << cs_erase << tmp1_str << '/' << tmp2_str << '/' << tmp3_str; + t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, label.c_str()); + + if(eng.conf_info.mask_missing_flag == FieldType_Both || + eng.conf_info.mask_missing_flag == FieldType_Obs) tmp1_str = "on"; + else tmp1_str = "off"; + if(eng.conf_info.mask_grid_flag == FieldType_Both || + eng.conf_info.mask_grid_flag == FieldType_Obs) tmp2_str = "on"; + else tmp2_str = "off"; + if(eng.conf_info.mask_grid_flag == FieldType_Both || + eng.conf_info.mask_grid_flag == FieldType_Obs) tmp3_str = "on"; + else tmp3_str = "off"; + label << cs_erase << tmp1_str << '/' << tmp2_str << '/' << tmp3_str; + t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, label.c_str()); + + ++r; + nextline(); + + // + // Convolution Radius + // + snprintf(junk, sizeof(junk), "%d", eng.conf_info.Fcst->conv_radius); + t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); + + snprintf(junk, sizeof(junk), "%d", eng.conf_info.Obs->conv_radius); + t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); + + ++r; + nextline(); + + // + // Convolution Threshold + // + thresh_str = eng.conf_info.Fcst->conv_thresh.get_str(2); + t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, thresh_str.c_str()); + + thresh_str = eng.conf_info.Obs->conv_thresh.get_str(2); + t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, thresh_str.c_str()); + + ++r; + nextline(); + + // + // Object Filters + // + + snprintf(junk, sizeof(junk), "%i", (int) eng.conf_info.Fcst->filter_attr_map.size()); + t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); + + snprintf(junk, sizeof(junk), "%i", (int) eng.conf_info.Obs->filter_attr_map.size()); + t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); + + ++r; + nextline(); - ++r; - nextline(); + // + // Intensity Percentile + // - // - // Merge Threshold - // + if(nint(eng.conf_info.inten_perc_value) == 101) label = "mean"; + else if(nint(eng.conf_info.inten_perc_value) == 102) label = "sum"; + else { + snprintf(junk, sizeof(junk), "p%d", eng.conf_info.inten_perc_value); + label = junk; + } + t.write_xy1_to_cell(r, 2, 0.0, dy, 0.5, 0.0, label.c_str()); - thresh_str = eng.conf_info.Fcst->merge_thresh.get_str(2); - t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, thresh_str.c_str()); + ++r; + nextline(); - thresh_str = eng.conf_info.Obs->merge_thresh.get_str(2); - t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, thresh_str.c_str()); + // + // Merge Threshold + // - ++r; - nextline(); + thresh_str = eng.conf_info.Fcst->merge_thresh.get_str(2); + t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, thresh_str.c_str()); - ///////////////////////////////////////////////////////////////// - // - // Matching/Merging Criteria - // - ///////////////////////////////////////////////////////////////// + thresh_str = eng.conf_info.Obs->merge_thresh.get_str(2); + t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, thresh_str.c_str()); - // - // Merging flag - // + ++r; + nextline(); - if(eng.conf_info.Fcst->merge_flag == MergeType_Thresh) label = "thresh"; - else if(eng.conf_info.Fcst->merge_flag == MergeType_Engine) label = "engine"; - else if(eng.conf_info.Fcst->merge_flag == MergeType_Both) label = "thresh/engine"; - else label = "none"; - t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, label.c_str()); + ///////////////////////////////////////////////////////////////// + // + // Matching/Merging Criteria + // + ///////////////////////////////////////////////////////////////// - if(eng.conf_info.Obs->merge_flag == MergeType_Thresh) label = "thresh"; - else if(eng.conf_info.Obs->merge_flag == MergeType_Engine) label = "engine"; - else if(eng.conf_info.Obs->merge_flag == MergeType_Both) label = "thresh/engine"; - else label = "none"; - t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, label.c_str()); + // + // Merging flag + // - ++r; - nextline(); + if(eng.conf_info.Fcst->merge_flag == MergeType_Thresh) label = "thresh"; + else if(eng.conf_info.Fcst->merge_flag == MergeType_Engine) label = "engine"; + else if(eng.conf_info.Fcst->merge_flag == MergeType_Both) label = "thresh/engine"; + else label = "none"; + t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, label.c_str()); - // - // Matching scheme - // + if(eng.conf_info.Obs->merge_flag == MergeType_Thresh) label = "thresh"; + else if(eng.conf_info.Obs->merge_flag == MergeType_Engine) label = "engine"; + else if(eng.conf_info.Obs->merge_flag == MergeType_Both) label = "thresh/engine"; + else label = "none"; + t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, label.c_str()); - if(eng.conf_info.match_flag == MatchType_MergeBoth) label = "match/merge"; - else if(eng.conf_info.match_flag == MatchType_MergeFcst) label = "match/fcst merge"; - else if(eng.conf_info.match_flag == MatchType_NoMerge) label = "match/no merge"; - else label = "none"; - t.write_xy1_to_cell(r, 2, 0.0, dy, 0.5, 0.0, label.c_str()); + ++r; + nextline(); - ++r; - nextline(); + // + // Matching scheme + // - ///////////////////////////////////////////////////////////////// - // - // Object Counts and Areas - // - ///////////////////////////////////////////////////////////////// + if(eng.conf_info.match_flag == MatchType_MergeBoth) label = "match/merge"; + else if(eng.conf_info.match_flag == MatchType_MergeFcst) label = "match/fcst merge"; + else if(eng.conf_info.match_flag == MatchType_NoMerge) label = "match/no merge"; + else label = "none"; + t.write_xy1_to_cell(r, 2, 0.0, dy, 0.5, 0.0, label.c_str()); - // - // Simple objects counts (Matched Simples/Unmatched Simples) - // + ++r; + nextline(); - snprintf(junk, sizeof(junk), "%i/%i/%i", eng.n_fcst, - eng.get_matched_fcst(0), eng.get_unmatched_fcst(0)); - t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); + ///////////////////////////////////////////////////////////////// + // + // Object Counts and Areas + // + ///////////////////////////////////////////////////////////////// - snprintf(junk, sizeof(junk), "%i/%i/%i", eng.n_obs, - eng.get_matched_obs(0), eng.get_unmatched_obs(0)); - t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); + // + // Simple objects counts (Matched Simples/Unmatched Simples) + // - ++r; - nextline(); + snprintf(junk, sizeof(junk), "%i/%i/%i", eng.n_fcst, + eng.get_matched_fcst(0), eng.get_unmatched_fcst(0)); + t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); - // - // Area counts - // + snprintf(junk, sizeof(junk), "%i/%i/%i", eng.n_obs, + eng.get_matched_obs(0), eng.get_unmatched_obs(0)); + t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); - snprintf(junk, sizeof(junk), "%d", eng.get_matched_fcst(1) + eng.get_unmatched_fcst(1)); - t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); + ++r; + nextline(); - snprintf(junk, sizeof(junk), "%d", eng.get_matched_obs(1) + eng.get_unmatched_obs(1)); - t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); + // + // Area counts + // - ++r; - nextline(); + snprintf(junk, sizeof(junk), "%d", eng.get_matched_fcst(1) + eng.get_unmatched_fcst(1)); + t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); - // - // Area counts (Matched Simple/Unmatched Simples) - // + snprintf(junk, sizeof(junk), "%d", eng.get_matched_obs(1) + eng.get_unmatched_obs(1)); + t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); - snprintf(junk, sizeof(junk), "%i/%i", - eng.get_matched_fcst(1), eng.get_unmatched_fcst(1)); - t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); + ++r; + nextline(); - snprintf(junk, sizeof(junk), "%i/%i", - eng.get_matched_obs(1), eng.get_unmatched_obs(1)); - t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); + // + // Area counts (Matched Simple/Unmatched Simples) + // - ++r; - nextline(); + snprintf(junk, sizeof(junk), "%i/%i", + eng.get_matched_fcst(1), eng.get_unmatched_fcst(1)); + t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); - // - // Cluster object counts - // + snprintf(junk, sizeof(junk), "%i/%i", + eng.get_matched_obs(1), eng.get_unmatched_obs(1)); + t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); - snprintf(junk, sizeof(junk), "%i", eng.collection.n_sets); - t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); + ++r; + nextline(); - snprintf(junk, sizeof(junk), "%i", eng.collection.n_sets); - t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); + // + // Cluster object counts + // + + snprintf(junk, sizeof(junk), "%i", eng.collection.n_sets); + t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); + + snprintf(junk, sizeof(junk), "%i", eng.collection.n_sets); + t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); - ++r; - nextline(); + ++r; + nextline(); - ///////////////////////////////////////////////////////////////// - // - // Interest Values - // - ///////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + // + // Interest Values + // + ///////////////////////////////////////////////////////////////// - // - // Median of Maximum Interest Values - // + // + // Median of Maximum Interest Values + // - v = interest_percentile(eng, 50.0, 1); - snprintf(junk, sizeof(junk), "%.4f", v); - t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); + v = interest_percentile(eng, 50.0, 1); + snprintf(junk, sizeof(junk), "%.4f", v); + t.write_xy1_to_cell(r, 1, dx, dy, 0.0, 0.0, junk); - v = interest_percentile(eng, 50.0, 2); - snprintf(junk, sizeof(junk), "%.4f", v); - t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); + v = interest_percentile(eng, 50.0, 2); + snprintf(junk, sizeof(junk), "%.4f", v); + t.write_xy1_to_cell(r, 2, dx, dy, 0.0, 0.0, junk); - ++r; - nextline(); + ++r; + nextline(); - // - // Median of Maximum Interest Values - // + // + // Median of Maximum Interest Values + // - v = interest_percentile(eng, 50.0, 3); - snprintf(junk, sizeof(junk), "%.4f", v); - t.write_xy1_to_cell(r, 2, 0.0, dy, 0.5, 0.0, junk); + v = interest_percentile(eng, 50.0, 3); + snprintf(junk, sizeof(junk), "%.4f", v); + t.write_xy1_to_cell(r, 2, 0.0, dy, 0.5, 0.0, junk); - ++r; - nextline(); + ++r; + nextline(); // // done // -return; + return; } @@ -928,101 +928,101 @@ void ModePsFile::do_page_1_other(ModeFuzzyEngine & eng, EngineType eng_type, con { -int j, c; -char junk[1024]; -TableHelper t; -const int simple_row = 1; -const int cluster_row = 2; -const int area_row = 3; -const int fcst_col = 1; -const int obs_col = 2; + int j, c; + char junk[1024]; + TableHelper t; + const int simple_row = 1; + const int cluster_row = 2; + const int area_row = 3; + const int fcst_col = 1; + const int obs_col = 2; -t.set(*this, 4, 3); + t.set(*this, 4, 3); -for (j=0; j<(t.nrows()); ++j) t.set_row_height(j, 15.0); + for (j=0; j<(t.nrows()); ++j) t.set_row_height(j, 15.0); -t.set_col_width(0, 50.0); -t.set_col_width(1, 60.0); -t.set_col_width(2, 60.0); + t.set_col_width(0, 50.0); + t.set_col_width(1, 60.0); + t.set_col_width(2, 60.0); -t.set_pin(Htab_a, table_bottom, 0.0, 0.0); + t.set_pin(Htab_a, table_bottom, 0.0, 0.0); -t.fill_row(0, light_green); -t.fill_col(0, blue1); -t.fill_cell(0, 0, dark_gray); + t.fill_row(0, light_green); + t.fill_col(0, blue1); + t.fill_cell(0, 0, dark_gray); -t.draw_skeleton(0.2); -t.outline_table(0.2, black); + t.draw_skeleton(0.2); + t.outline_table(0.2, black); - text_y -= 12.0*TextSep; + text_y -= 12.0*TextSep; - // - // Field name - // - t.write_xy1_to_cell(0, fcst_col, 0.5*(t.col_width(fcst_col)), dy, 0.5, 0.0, FcstString.c_str()); - t.write_xy1_to_cell(0, obs_col, 0.5*(t.col_width(fcst_col)), dy, 0.5, 0.0, ObsString.c_str()); - nextline(); + // + // Field name + // + t.write_xy1_to_cell(0, fcst_col, 0.5*(t.col_width(fcst_col)), dy, 0.5, 0.0, FcstString.c_str()); + t.write_xy1_to_cell(0, obs_col, 0.5*(t.col_width(fcst_col)), dy, 0.5, 0.0, ObsString.c_str()); + nextline(); - ///////////////////////////////////////////////////////////////// - // - // Object Counts and Areas - // - ///////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + // + // Object Counts and Areas + // + ///////////////////////////////////////////////////////////////// - // - // Simple objects counts - // + // + // Simple objects counts + // - bold(); - t.write_xy1_to_cell(simple_row, 0, dx, dy, 0.0, 0.0, "Simple"); - t.write_xy1_to_cell(cluster_row, 0, dx, dy, 0.0, 0.0, "Cluster"); - t.write_xy1_to_cell(area_row, 0, dx, dy, 0.0, 0.0, "Area"); - roman(); - snprintf(junk, sizeof(junk), "%d", eng.n_fcst); - c = fcst_col; - t.write_xy1_to_cell(simple_row, c, t.col_width(c) - 5.0, dy, 1.0, 0.0, junk); + bold(); + t.write_xy1_to_cell(simple_row, 0, dx, dy, 0.0, 0.0, "Simple"); + t.write_xy1_to_cell(cluster_row, 0, dx, dy, 0.0, 0.0, "Cluster"); + t.write_xy1_to_cell(area_row, 0, dx, dy, 0.0, 0.0, "Area"); + roman(); + snprintf(junk, sizeof(junk), "%d", eng.n_fcst); + c = fcst_col; + t.write_xy1_to_cell(simple_row, c, t.col_width(c) - 5.0, dy, 1.0, 0.0, junk); - snprintf(junk, sizeof(junk), "%d", eng.n_obs); - c = obs_col; - t.write_xy1_to_cell(simple_row, c, t.col_width(c) - 5.0, dy, 1.0, 0.0, junk); + snprintf(junk, sizeof(junk), "%d", eng.n_obs); + c = obs_col; + t.write_xy1_to_cell(simple_row, c, t.col_width(c) - 5.0, dy, 1.0, 0.0, junk); - nextline(); + nextline(); - // - // Area counts - // + // + // Area counts + // - snprintf(junk, sizeof(junk), "%d", eng.get_matched_fcst(1) + eng.get_unmatched_fcst(1)); - c = fcst_col; - t.write_xy1_to_cell(area_row, c, t.col_width(c) - 5.0, dy, 1.0, 0.0, junk); + snprintf(junk, sizeof(junk), "%d", eng.get_matched_fcst(1) + eng.get_unmatched_fcst(1)); + c = fcst_col; + t.write_xy1_to_cell(area_row, c, t.col_width(c) - 5.0, dy, 1.0, 0.0, junk); - snprintf(junk, sizeof(junk), "%d", eng.get_matched_obs(1) + eng.get_unmatched_obs(1)); - c = obs_col; - t.write_xy1_to_cell(area_row, c, t.col_width(c) - 5.0, dy, 1.0, 0.0, junk); + snprintf(junk, sizeof(junk), "%d", eng.get_matched_obs(1) + eng.get_unmatched_obs(1)); + c = obs_col; + t.write_xy1_to_cell(area_row, c, t.col_width(c) - 5.0, dy, 1.0, 0.0, junk); - nextline(); + nextline(); - // - // Cluster object counts - // + // + // Cluster object counts + // - snprintf(junk, sizeof(junk), "%d", eng.collection.n_sets); - c = fcst_col; - t.write_xy1_to_cell(cluster_row, c, t.col_width(c) - 5.0, dy, 1.0, 0.0, junk); + snprintf(junk, sizeof(junk), "%d", eng.collection.n_sets); + c = fcst_col; + t.write_xy1_to_cell(cluster_row, c, t.col_width(c) - 5.0, dy, 1.0, 0.0, junk); - snprintf(junk, sizeof(junk), "%d", eng.collection.n_sets); - c = obs_col; - t.write_xy1_to_cell(cluster_row, c, t.col_width(c) - 5.0, dy, 1.0, 0.0, junk); + snprintf(junk, sizeof(junk), "%d", eng.collection.n_sets); + c = obs_col; + t.write_xy1_to_cell(cluster_row, c, t.col_width(c) - 5.0, dy, 1.0, 0.0, junk); - nextline(); + nextline(); // // done // -return; + return; } diff --git a/src/tools/core/mode/plot_engine.cc b/src/tools/core/mode/plot_engine.cc index 811ceb6c8f..eb1125b7ca 100644 --- a/src/tools/core/mode/plot_engine.cc +++ b/src/tools/core/mode/plot_engine.cc @@ -23,11 +23,11 @@ using namespace std; //////////////////////////////////////////////////////////////////////// - // - // Flag value of 2 indicates that both fcst and obs should be enlarged - // Flag value of 1 indicates that only the fcst should be enlarged - // Flag value of 0 indicates that only the obs should be enlarged - // +// +// Flag value of 2 indicates that both fcst and obs should be enlarged +// Flag value of 1 indicates that only the fcst should be enlarged +// Flag value of 0 indicates that only the obs should be enlarged +// void ModePsFile::plot_engine(ModeFuzzyEngine & eng, EngineType eng_type, const char * title) @@ -38,51 +38,51 @@ void ModePsFile::plot_engine(ModeFuzzyEngine & eng, EngineType eng_type, const c // setup fcst & obs strings // -if ( eng_type == FOEng ) { // Plot forecast versus observation + if ( eng_type == FOEng ) { // Plot forecast versus observation - FcstString = "Forecast"; - FcstShortString = "Fcst"; - ObsString = "Observation"; - ObsShortString = "Obs"; + FcstString = "Forecast"; + FcstShortString = "Fcst"; + ObsString = "Observation"; + ObsShortString = "Obs"; -} else if ( eng_type == FFEng ) { // Plot forecast versus forecast + } else if ( eng_type == FFEng ) { // Plot forecast versus forecast - FcstString = "Forecast"; - FcstShortString = "Fcst"; - ObsString = "Forecast"; - ObsShortString = "Fcst"; + FcstString = "Forecast"; + FcstShortString = "Fcst"; + ObsString = "Forecast"; + ObsShortString = "Fcst"; -} else if ( eng_type == OOEng ) { // Plot observation versus observation + } else if ( eng_type == OOEng ) { // Plot observation versus observation - FcstString = "Observation"; - FcstShortString = "Obs"; - ObsString = "Observation"; - ObsShortString = "Obs"; + FcstString = "Observation"; + FcstShortString = "Obs"; + ObsString = "Observation"; + ObsShortString = "Obs"; -} + } // // do pages // -do_page_1(eng, eng_type, title); + do_page_1(eng, eng_type, title); -if ( (eng_type == FOEng) || (eng_type == FFEng) ) do_fcst_enlarge_page(eng, eng_type, title); + if ( (eng_type == FOEng) || (eng_type == FFEng) ) do_fcst_enlarge_page(eng, eng_type, title); -if ( (eng_type == FOEng) || (eng_type == OOEng) ) do_obs_enlarge_page(eng, eng_type, title); + if ( (eng_type == FOEng) || (eng_type == OOEng) ) do_obs_enlarge_page(eng, eng_type, title); -if ( eng_type == FOEng ) { + if ( eng_type == FOEng ) { - do_overlap_page(eng, eng_type, title); - do_cluster_page(eng, eng_type, title); + do_overlap_page(eng, eng_type, title); + do_cluster_page(eng, eng_type, title); -} + } // // done // -return; + return; }