diff --git a/docs/Users_Guide/mode.rst b/docs/Users_Guide/mode.rst index 6088e993ea..5de97252c1 100644 --- a/docs/Users_Guide/mode.rst +++ b/docs/Users_Guide/mode.rst @@ -121,6 +121,10 @@ When regridding to the FCST or OBS field (e.g. to_grid = FCST), the first field "file_type" can be set independently for each input in multivariate mode. If not set for an input, MET uses file names and file content to determine the type. +In multivariate mode, with quilt=**FALSE**, for all inputs the number of forecast and observation convolution radii and thresholds must all match. One configuration of MODE will be run for each group of settings in those lists. + +In multivariate mode, with quilt=**TRUE**, for all inputs the number of forecast and observation convolution radii must match and the number of forecast and observation convolution thresholds must match. When each input has N radii and M thresholds, NxM configurations of MODE will be run. + When setting a threshold to a percentile, some choices require both an observation input and a forecast input. When this is the case, it's assumed the indices match, so for example if forecast input 1 has such a percentile setting, then observation input 1 will be used to compute the percentile. Percentiles in which this will happen are: * SFP in an observation input. @@ -319,7 +323,7 @@ The **conv_radius** entry defines the radius of the circular convolution applied The **conv_thresh** entry specifies the threshold values to be applied to the convolved field to define objects. By default, objects are defined using a convolution threshold of 5.0. Multiple convolution thresholds may be specified as an array (e.g. **conv_thresh = [ >=5.0, >=10.0, >=15.0 ];)**. -Multiple convolution radii and thresholds and processed using the logic defined by the **quilt** entry. +Multiple convolution radii and thresholds are processed using the logic defined by the **quilt** entry. The logic specific to multivariate mode is described in the multivariate mode section above. The **vld_thresh** entry must be set between 0 and 1. When performing the circular convolution step if the proportion of bad data values in the convolution area is greater than or equal to this threshold, the resulting convolved value will be bad data. If the proportion is less than this threshold, the convolution will be performed on only the valid data. By default, the **vld_thresh** is set to 0.5. diff --git a/src/libcode/vx_shapedata/engine.cc b/src/libcode/vx_shapedata/engine.cc index ffaba59145..0809afd999 100644 --- a/src/libcode/vx_shapedata/engine.cc +++ b/src/libcode/vx_shapedata/engine.cc @@ -602,7 +602,6 @@ void ModeFuzzyEngine::do_fcst_convolution() { if(!need_fcst_conv) return; r = conf_info.Fcst->conv_radius; - *fcst_conv = *fcst_raw; mlog << Debug(3) << "Applying circular convolution of radius " @@ -645,7 +644,6 @@ void ModeFuzzyEngine::do_obs_convolution() { if(!need_obs_conv) return; r = conf_info.Obs->conv_radius; - *obs_conv = *obs_raw; mlog << Debug(3) << "Applying circular convolution of radius " diff --git a/src/libcode/vx_shapedata/mode_conf_info.cc b/src/libcode/vx_shapedata/mode_conf_info.cc index 080365c757..73970d8531 100644 --- a/src/libcode/vx_shapedata/mode_conf_info.cc +++ b/src/libcode/vx_shapedata/mode_conf_info.cc @@ -74,11 +74,11 @@ void ModeConfInfo::init_from_scratch() Field_Index_f = 0; Field_Index_o = 0; - fcst_array = 0; - obs_array = 0; + fcst_array = nullptr; + obs_array = nullptr; - fcst_array = 0; - obs_array = 0; + fcst_array = nullptr; + obs_array = nullptr; clear(); @@ -115,8 +115,8 @@ void ModeConfInfo::assign( const ModeConfInfo &m) complexity_ratio_wt = m.complexity_ratio_wt; inten_perc_ratio_wt = m.inten_perc_ratio_wt; - fcst_array = 0; - Fcst = 0; + fcst_array = nullptr; + Fcst = nullptr; if (N_fields_f > 0) { fcst_array = new Mode_Field_Info[N_fields_f]; for (int i=0; i 0) { obs_array = new Mode_Field_Info[N_fields_o]; for (int i=0; ilookup_int(conf_key_shift_right); if (field_index == 0) { @@ -643,11 +634,8 @@ void ModeConfInfo::process_config_fcst(GrdFileType ftype, int field_index) void ModeConfInfo::process_config_obs(GrdFileType otype, int field_index) { - int j, k, n; - Dictionary * obs_dict = (Dictionary *) nullptr; - - obs_dict = conf.lookup_dictionary(conf_key_obs); + Dictionary * obs_dict = conf.lookup_dictionary(conf_key_obs); shift_right = obs_dict->lookup_int(conf_key_shift_right); if (field_index == 0) { @@ -688,7 +676,8 @@ void ModeConfInfo::config_set_all_percentile_thresholds(const std::vector fcst_freq, obs_freq; + vector fcst_freq; + vector obs_freq; // indices (common to forecast and obs) that require both inputs (fcst and obs) // which is either frequency bias, or sample obs with a forecast input, or sample fcst @@ -776,9 +765,8 @@ void ModeConfInfo::config_set_all_percentile_thresholds(const std::vectoris_array() ) { - int j, k; - const DictionaryEntry * e = 0; + const DictionaryEntry * e = nullptr; const Dictionary & D = *field; - if (data_type == ModeDataType::Traditional) { - // traditional mode, extra test - if ( (N_fields_f > 0) && (N != N_fields_f) ) { - mlog << Error - << "\nModeConfInfo::read_fields() -> fcst and obs dictionaries have different number of entries in traditional mode" - << ", not allowed\n\n"; - exit ( 1 ); + // traditional mode, extra test + if ( (data_type == ModeDataType::Traditional) && + (N_fields_f > 0) && + (N != N_fields_f) ) { + mlog << Error + << "\nModeConfInfo::read_fields() -> fcst and obs dictionaries have different number of entries in traditional mode" + << ", not allowed\n\n"; + + exit ( 1 ); - } } if (_fo == 'F') { @@ -958,7 +944,7 @@ if ( field->is_array() ) { } else { N_fields_o = N; } - for (j=0; jdict(); -const int N = ( (field->is_array()) ? (field->n_entries()) : 1 ); - if ( field->is_array() ) { - const DictionaryEntry * e = 0; + const DictionaryEntry * e = nullptr; const Dictionary & D = *field; e = D[field_index]; @@ -1175,7 +1159,8 @@ void ModeConfInfo::set_perc_thresh(const DataPlane &f_dp, // // Sort the input arrays // - NumArray fsort, osort; + NumArray fsort; + NumArray osort; int nxy = f_dp.nx() * f_dp.ny(); fsort.extend(nxy); @@ -1276,7 +1261,7 @@ void ModeConfInfo::parse_nc_info() { -const DictionaryEntry * e = (const DictionaryEntry *) nullptr; +const DictionaryEntry * e = nullptr; e = conf.lookup(conf_key_nc_pairs_flag); @@ -1366,6 +1351,35 @@ void ModeConfInfo::set_conv_radius_by_index(int k) } +//////////////////////////////////////////////////////////////////////// + +void ModeConfInfo::set_obs_conv_radius_by_index(int k) + +{ + if ( (k < 0) || (k >= Obs->conv_radius_array.n_elements()) ) { + mlog << Error + << "\nModeConfInfo::set_conv_radius_by_index(int) -> " + << "range check error\n\n"; + exit ( 1 ); + } + Obs->conv_radius = Obs->conv_radius_array[k]; +} + + +//////////////////////////////////////////////////////////////////////// + +void ModeConfInfo::set_fcst_conv_radius_by_index(int k) + +{ + if ( (k < 0) || (k >= Fcst->conv_radius_array.n_elements()) ) { + mlog << Error + << "\nModeConfInfo::set_conv_radius_by_index(int) -> " + << "range check error\n\n"; + exit ( 1 ); + } + Fcst->conv_radius = Fcst->conv_radius_array[k]; +} + //////////////////////////////////////////////////////////////////////// @@ -1381,6 +1395,21 @@ void ModeConfInfo::set_conv_thresh(SingleThresh s) //////////////////////////////////////////////////////////////////////// + +void ModeConfInfo::set_fcst_conv_thresh(SingleThresh s) +{ + Fcst->conv_thresh = s; +} + +//////////////////////////////////////////////////////////////////////// + +void ModeConfInfo::set_obs_conv_thresh(SingleThresh s) +{ + Obs->conv_thresh = s; +} + +//////////////////////////////////////////////////////////////////////// + void ModeConfInfo::set_conv_radius(int r) { if (data_type != ModeDataType::MvMode_Obs) { @@ -1393,6 +1422,20 @@ void ModeConfInfo::set_conv_radius(int r) //////////////////////////////////////////////////////////////////////// +void ModeConfInfo::set_fcst_conv_radius(int r) +{ + Fcst->conv_radius = r; +} + +//////////////////////////////////////////////////////////////////////// + +void ModeConfInfo::set_obs_conv_radius(int r) +{ + Obs->conv_radius = r; +} + +//////////////////////////////////////////////////////////////////////// + void ModeConfInfo::set_conv_thresh_by_index(int k) { @@ -1421,14 +1464,43 @@ void ModeConfInfo::set_conv_thresh_by_index(int k) //////////////////////////////////////////////////////////////////////// -void ModeConfInfo::set_merge_thresh_by_index(int k) +void ModeConfInfo::set_obs_conv_thresh_by_index(int k) + { - if (data_type != ModeDataType::MvMode_Fcst) { - if ( Obs->need_merge_thresh () ) set_obs_merge_thresh_by_index (k); + if ( (k < 0) || (k >= Obs->conv_thresh_array.n_elements()) ) { + mlog << Error + << "\nModeConfInfo::set_conv_thresh_by_index(int) -> " + << "range check error\n\n"; + exit ( 1 ); } - if (data_type != ModeDataType::MvMode_Obs) { - if ( Fcst->need_merge_thresh () ) set_fcst_merge_thresh_by_index (k); + Obs->conv_thresh = Obs->conv_thresh_array[k]; +} + + +//////////////////////////////////////////////////////////////////////// + +void ModeConfInfo::set_fcst_conv_thresh_by_index(int k) + +{ + if ( (k < 0) || (k >= Fcst->conv_thresh_array.n_elements()) ) { + + mlog << Error + << "\nModeConfInfo::set_conv_thresh_by_index(int) -> " + << "range check error\n\n"; + exit ( 1 ); } + Fcst->conv_thresh = Fcst->conv_thresh_array[k]; +} + + +//////////////////////////////////////////////////////////////////////// + +void ModeConfInfo::set_merge_thresh_by_index(int k) +{ + if ( data_type != ModeDataType::MvMode_Fcst && + Obs->need_merge_thresh() ) set_obs_merge_thresh_by_index (k); + if ( data_type != ModeDataType::MvMode_Obs && + Fcst->need_merge_thresh() ) set_fcst_merge_thresh_by_index (k); } //////////////////////////////////////////////////////////////////////// @@ -1457,12 +1529,10 @@ void ModeConfInfo::set_fcst_merge_thresh_by_index(int k) void ModeConfInfo::set_conv_thresh_by_merge_index(int k) { - if (data_type != ModeDataType::MvMode_Fcst) { - if (Obs->need_merge_thresh()) set_obs_conv_thresh_by_merge_index (k); - } - if (data_type != ModeDataType::MvMode_Obs) { - if (Fcst->need_merge_thresh()) set_fcst_conv_thresh_by_merge_index (k); - } + if ( data_type != ModeDataType::MvMode_Fcst && + Obs->need_merge_thresh() ) set_obs_conv_thresh_by_merge_index (k); + if ( data_type != ModeDataType::MvMode_Obs && + Fcst->need_merge_thresh() ) set_fcst_conv_thresh_by_merge_index (k); } //////////////////////////////////////////////////////////////////////// @@ -1593,7 +1663,7 @@ GrdFileType ModeConfInfo::file_type_for_field(bool isFcst, int field_index) // look at the dictionary for the obs or forecast at index, with // parents - Dictionary * dict = (Dictionary *) nullptr; + Dictionary * dict = nullptr; if (isFcst) { dict = conf.lookup_dictionary(conf_key_fcst); } else { @@ -1688,7 +1758,7 @@ void ModeConfInfo::get_multivar_programs() { -Dictionary * dict = (Dictionary *) nullptr; +Dictionary * dict = nullptr; fcst_multivar_logic.clear(); obs_multivar_logic.clear(); @@ -1732,63 +1802,107 @@ void ModeConfInfo::check_multivar_not_implemented() } bool status = false; - if (quilt) { - mlog << Error - << "\nModeConfInfo::check_multivar_not_implemented():\n" - << " quilting not yet implemented for multivar mode\n\n"; - status = true; - } + + // All inputs must have the same number of convolution radii + // All inputs must have the same number of convolution thresholds + // Without quilting, the radii/thresh array lengths must be the same + + int nRForFcst = 0; + int nRForObs = 0; + int nTForFcst = 0; + int nTForObs = 0; for (int i=0; i 1 || fcst_array[i].merge_thresh_array.n() > 1) { + if (fcst_array[i].merge_flag == MergeType::Both || fcst_array[i].merge_flag == MergeType::Engine) + { + mlog << Error + << "\nModeConfInfo::check_multivar_not_implemented():\n" + << " merge_flag ENGINE or BOTH not implemented for multivariate mode\n\n"; + status = true; + } + if (i == 0) { + nTForFcst = fcst_array[i].conv_thresh_array.n(); + nRForFcst = fcst_array[i].conv_radius_array.n_elements(); + } + int nti = fcst_array[i].conv_thresh_array.n(); + int nri = fcst_array[i].conv_radius_array.n_elements(); + if (nti != nTForFcst || nri != nRForFcst) { + mlog << Error + << "\nModeConfInfo::check_multivar_not_implemented():\n" + << " Unequal array lengths for conv_thresh or conv_radii not allowed in multivariate mode\n\n"; + status = true; + } + if (fcst_array[i].merge_flag != MergeType::None) { + int nmi = fcst_array[i].merge_thresh_array.n(); + if (nmi != nTForFcst) { mlog << Error << "\nModeConfInfo::check_multivar_not_implemented():\n" - << " more than one conv_thresh or merge_thresh per input is not allowed in multivariate mode\n\n"; + << " Unequal array lengths for merge_thresh not allowed in multivariate mode\n\n"; status = true; - } + } } } for (int i=0; i 1 || obs_array[i].merge_thresh_array.n() > 1) { + if (obs_array[i].merge_flag == MergeType::Both || obs_array[i].merge_flag == MergeType::Engine) { + mlog << Error + << "\nModeConfInfo::check_multivar_not_implemented():\n" + << " merge_flag ENGINE or BOTH not implemented for multivariate mode\n\n"; + status = true; + break; + } + if (i == 0) { + nTForObs = obs_array[i].conv_thresh_array.n(); + nRForObs = obs_array[i].conv_radius_array.n_elements(); + } + int nti = obs_array[i].conv_thresh_array.n(); + int nri = obs_array[i].conv_radius_array.n_elements(); + if (nti != nTForObs || nri != nRForObs) { + mlog << Error + << "\nModeConfInfo::check_multivar_not_implemented():\n" + << " Unequal array lengths for conv_thresh or conv_radii not allowed in multivariate mode\n\n"; + status = true; + } + if (obs_array[i].merge_flag != MergeType::None) { + int nmi = obs_array[i].merge_thresh_array.n(); + if (nmi != nTForObs) { mlog << Error << "\nModeConfInfo::check_multivar_not_implemented():\n" - << " more than one conv_thresh or merge_thresh per input is not allowed in multivariate mode\n\n"; + << " Unequal array lengths for merge_thresh not allowed in multivariate mode\n\n"; status = true; - } + } } } - if (status) { + if (nTForObs != nTForFcst) { + mlog << Error + << "\nModeConfInfo::check_multivar_not_implemented():\n" + << " Obs convolution thresh/radius arrays must have the same number of elements as Fcst thresh/radius arrays\n\n"; + status = true; + } + if (nRForObs != nRForFcst) { mlog << Error - << "\nModeConfInfo::check_multivar_not_implemented:\n" - << " Some features not yet implemented in multivar mode\n\n"; + << "\nModeConfInfo::check_multivar_not_implemented():\n" + << " Obs convolution thresh/radius arrays must have the same number of elements as Fcst thresh/radius arrays\n\n"; + status = true; + } + if (!quilt && (nTForObs != nRForObs)) { + mlog << Error + << "\nModeConfInfo::check_multivar_not_implemented():\n" + << " Obs convolution thresh/radius arrays must have the same number of elements as Fcst thresh/radius arrays unless quilt=true\n\n"; + status = true; + } + + if (status) { exit ( 1 ); } } - //////////////////////////////////////////////////////////////////////// PercThreshType ModeConfInfo::perctype(const Mode_Field_Info &f) const { - PercThreshType pm=no_perc_thresh_type;; - PercThreshType pc=no_perc_thresh_type;; + PercThreshType pm=no_perc_thresh_type; + PercThreshType pc=no_perc_thresh_type; if (f.merge_thresh_array.n() > 0) { pm = f.merge_thresh_array[0].get_ptype(); } diff --git a/src/libcode/vx_shapedata/mode_conf_info.h b/src/libcode/vx_shapedata/mode_conf_info.h index 08f61ff3df..e4fe93e58f 100644 --- a/src/libcode/vx_shapedata/mode_conf_info.h +++ b/src/libcode/vx_shapedata/mode_conf_info.h @@ -262,17 +262,30 @@ class ModeConfInfo { void parse_nc_info (); - // might need addtional methods here for pass2 multivariate, if/when we allow more than 1 radius void set_conv_radius_by_index (int); - // might need addtional methods here for pass2 multivariate, if/when we allow more than 1 thresh + void set_obs_conv_radius_by_index (int); + void set_fcst_conv_radius_by_index (int); + void set_conv_thresh_by_index (int); + void set_obs_conv_thresh_by_index (int); + void set_fcst_conv_thresh_by_index (int); void set_conv_thresh(SingleThresh); + void set_fcst_conv_thresh(SingleThresh); + void set_obs_conv_thresh(SingleThresh); void set_conv_radius(int); + void set_fcst_conv_radius(int); + void set_obs_conv_radius(int); int n_conv_threshs () const; int n_conv_radii () const; + int n_conv_threshs_fcst () const; + int n_conv_radii_fcst () const; + + int n_conv_threshs_obs () const; + int n_conv_radii_obs () const; + int n_runs() const; // # threshs times # radii int n_fields_f() const; // should be 1 for traditional mode, >= 1 for muiltivar @@ -316,6 +329,7 @@ inline int ModeConfInfo::n_conv_radii() const { // this could break down if multivar mode relaxes // its limitations on number of radii (obs and fcst could be different) + // so far that is not the case. if (data_type == ModeDataType::MvMode_Obs) { return ( Obs->conv_radius_array.n_elements() ); @@ -324,10 +338,21 @@ inline int ModeConfInfo::n_conv_radii() const } } +inline int ModeConfInfo::n_conv_radii_fcst() const +{ + return ( Fcst->conv_radius_array.n_elements() ); +} + +inline int ModeConfInfo::n_conv_radii_obs() const +{ + return ( Obs->conv_radius_array.n_elements() ); +} + inline int ModeConfInfo::n_conv_threshs() const { // this could break down if multivar mode relaxes // its limitations on number of thresh (obs and fcst could be different) + // so far that is not the case. if (data_type == ModeDataType::MvMode_Obs) { return ( Obs->conv_thresh_array.n_elements() ); @@ -336,6 +361,16 @@ inline int ModeConfInfo::n_conv_threshs() const } } +inline int ModeConfInfo::n_conv_threshs_fcst() const +{ + return ( Fcst->conv_thresh_array.n_elements() ); +} + +inline int ModeConfInfo::n_conv_threshs_obs() const +{ + return ( Obs->conv_thresh_array.n_elements() ); +} + inline int ModeConfInfo::get_compression_level() { return conf.nc_compression(); } inline int ModeConfInfo::field_index_f() const { return Field_Index_f; } diff --git a/src/tools/core/mode/Makefile.am b/src/tools/core/mode/Makefile.am index 34bb6cc8dd..0fc2aabffd 100644 --- a/src/tools/core/mode/Makefile.am +++ b/src/tools/core/mode/Makefile.am @@ -22,6 +22,7 @@ mode_SOURCES = mode_usage.cc \ mode_ps_file.cc \ plot_engine.cc \ page_1.cc \ + simple_objects.cc \ fcst_enlarge_page.cc \ obs_enlarge_page.cc \ cluster_page.cc \ diff --git a/src/tools/core/mode/Makefile.in b/src/tools/core/mode/Makefile.in index 55999c4871..1837730adc 100644 --- a/src/tools/core/mode/Makefile.in +++ b/src/tools/core/mode/Makefile.in @@ -107,7 +107,7 @@ am_mode_OBJECTS = mode-mode_usage.$(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) \ + mode-simple_objects.$(OBJEXT) mode-fcst_enlarge_page.$(OBJEXT) \ mode-obs_enlarge_page.$(OBJEXT) mode-cluster_page.$(OBJEXT) \ mode-overlap_page.$(OBJEXT) mode-mode_exec.$(OBJEXT) mode_OBJECTS = $(am_mode_OBJECTS) @@ -145,7 +145,8 @@ am__depfiles_remade = ./$(DEPDIR)/mode-cluster_page.Po \ ./$(DEPDIR)/mode-objects_from_netcdf.Po \ ./$(DEPDIR)/mode-obs_enlarge_page.Po \ ./$(DEPDIR)/mode-overlap_page.Po ./$(DEPDIR)/mode-page_1.Po \ - ./$(DEPDIR)/mode-plot_engine.Po + ./$(DEPDIR)/mode-plot_engine.Po \ + ./$(DEPDIR)/mode-simple_objects.Po am__mv = mv -f AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -361,6 +362,7 @@ mode_SOURCES = mode_usage.cc \ mode_ps_file.cc \ plot_engine.cc \ page_1.cc \ + simple_objects.cc \ fcst_enlarge_page.cc \ obs_enlarge_page.cc \ cluster_page.cc \ @@ -515,6 +517,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode-overlap_page.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode-page_1.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode-plot_engine.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mode-simple_objects.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @@ -690,6 +693,20 @@ mode-page_1.obj: page_1.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-page_1.obj `if test -f 'page_1.cc'; then $(CYGPATH_W) 'page_1.cc'; else $(CYGPATH_W) '$(srcdir)/page_1.cc'; fi` +mode-simple_objects.o: simple_objects.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT mode-simple_objects.o -MD -MP -MF $(DEPDIR)/mode-simple_objects.Tpo -c -o mode-simple_objects.o `test -f 'simple_objects.cc' || echo '$(srcdir)/'`simple_objects.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mode-simple_objects.Tpo $(DEPDIR)/mode-simple_objects.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='simple_objects.cc' object='mode-simple_objects.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-simple_objects.o `test -f 'simple_objects.cc' || echo '$(srcdir)/'`simple_objects.cc + +mode-simple_objects.obj: simple_objects.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT mode-simple_objects.obj -MD -MP -MF $(DEPDIR)/mode-simple_objects.Tpo -c -o mode-simple_objects.obj `if test -f 'simple_objects.cc'; then $(CYGPATH_W) 'simple_objects.cc'; else $(CYGPATH_W) '$(srcdir)/simple_objects.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mode-simple_objects.Tpo $(DEPDIR)/mode-simple_objects.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='simple_objects.cc' object='mode-simple_objects.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-simple_objects.obj `if test -f 'simple_objects.cc'; then $(CYGPATH_W) 'simple_objects.cc'; else $(CYGPATH_W) '$(srcdir)/simple_objects.cc'; fi` + mode-fcst_enlarge_page.o: fcst_enlarge_page.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mode_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT mode-fcst_enlarge_page.o -MD -MP -MF $(DEPDIR)/mode-fcst_enlarge_page.Tpo -c -o mode-fcst_enlarge_page.o `test -f 'fcst_enlarge_page.cc' || echo '$(srcdir)/'`fcst_enlarge_page.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mode-fcst_enlarge_page.Tpo $(DEPDIR)/mode-fcst_enlarge_page.Po @@ -903,6 +920,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/mode-overlap_page.Po -rm -f ./$(DEPDIR)/mode-page_1.Po -rm -f ./$(DEPDIR)/mode-plot_engine.Po + -rm -f ./$(DEPDIR)/mode-simple_objects.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -964,6 +982,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/mode-overlap_page.Po -rm -f ./$(DEPDIR)/mode-page_1.Po -rm -f ./$(DEPDIR)/mode-plot_engine.Po + -rm -f ./$(DEPDIR)/mode-simple_objects.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/src/tools/core/mode/combine_boolplanes.cc b/src/tools/core/mode/combine_boolplanes.cc index 111964c94c..608cdff409 100644 --- a/src/tools/core/mode/combine_boolplanes.cc +++ b/src/tools/core/mode/combine_boolplanes.cc @@ -23,6 +23,7 @@ using namespace std; // void combine_boolplanes(const string &name, + int rIndex, int tIndex, const BoolPlane * bpa, const int n_planes, BoolCalc & calc, BoolPlane & bp_out) @@ -57,7 +58,7 @@ void combine_boolplanes(const string &name, } // for x - mlog << Debug(1) << name << " has " << nTrue << " superobject points.\n"; + mlog << Debug(1) << name << " has " << nTrue << " superobject points. rIndex[" << rIndex << "] tIndex[" << tIndex << "]\n"; // // done diff --git a/src/tools/core/mode/combine_boolplanes.h b/src/tools/core/mode/combine_boolplanes.h index 2a7c168628..987b1a8c49 100644 --- a/src/tools/core/mode/combine_boolplanes.h +++ b/src/tools/core/mode/combine_boolplanes.h @@ -35,6 +35,7 @@ extern void combine_boolplanes(const std::string &name, + int rIndex, int tIndex, const BoolPlane * array, const int n_planes, BoolCalc & calc, BoolPlane & bp_out); diff --git a/src/tools/core/mode/mode_exec.cc b/src/tools/core/mode/mode_exec.cc index db43b97ebe..081266cae6 100644 --- a/src/tools/core/mode/mode_exec.cc +++ b/src/tools/core/mode/mode_exec.cc @@ -202,11 +202,13 @@ void ModeExecutive::init_traditional(int n_files) /////////////////////////////////////////////////////////////////////// -void ModeExecutive::init_multivar_simple(int j, int n_files, ModeDataType dtype, +void ModeExecutive::init_multivar_simple(int rIndex, int tIndex, + int j, ModeDataType dtype, const ModeConfInfo &conf) { - R_index = T_index = 0; + R_index = rIndex; + T_index = tIndex; engine.conf_info = conf; // tell the engine which type of data it is @@ -214,8 +216,6 @@ void ModeExecutive::init_multivar_simple(int j, int n_files, ModeDataType dtype, engine.conf_info.set_field_index(j); - // engine.conf_info.nc_info.compress_level = engine.conf_info.get_compression_level(); - return; } @@ -236,8 +236,6 @@ void ModeExecutive::init_multivar_intensities(const ModeConfInfo &conf) // check one again for multivar problems engine.conf_info.check_multivar_not_implemented(); - // engine.conf_info.nc_info.compress_level = engine.conf_info.get_compression_level(); - return; } @@ -250,8 +248,10 @@ void ModeExecutive::setup_traditional_fcst_obs_data() { - // ShapeData fcst_sd, obs_sd; - double fmin, omin, fmax, omax; + double fmin; + double omin; + double fmax; + double omax; Fcst_sd.clear(); Obs_sd.clear(); @@ -441,7 +441,8 @@ void ModeExecutive::setup_multivar_fcst_data(const Grid &verification_grid, const ModeInputData &input) { - double fmin, fmax; + double fmin; + double fmax; Fcst_sd.clear(); Fcst_sd.data = input._dataPlane; @@ -504,8 +505,8 @@ void ModeExecutive::setup_multivar_obs_data(const Grid &verification_grid, const ModeInputData &input) { - // ShapeData fcst_sd, obs_sd; - double omin, omax; + double omin; + double omax; Obs_sd.clear(); @@ -570,7 +571,10 @@ void ModeExecutive::setup_multivar_obs_data(const Grid &verification_grid, void ModeExecutive::setup_multivar_fcst_obs_data_intensities(const MultiVarData &mvdf, const MultiVarData &mvdo) { - double fmin, fmax, omin, omax; + double fmin; + double fmax; + double omin; + double omax; bool simple = true; Fcst_sd = *(mvdf.shapedata_ptr(simple)); @@ -672,9 +676,11 @@ void ModeExecutive::setup_multivar_fcst_obs_data_super(const ShapeData &f_super, const ShapeData &o_super, const Grid &igrid) { - double fmin, omin, fmax, omax; + double fmin; + double omin; + double fmax; + double omax; - bool simple = true; Fcst_sd = f_super; Fcst_sd.debug_examine(); Obs_sd = o_super; @@ -772,8 +778,7 @@ void ModeExecutive::do_conv_thresh_traditional(const int r_index, const int t_in ModeConfInfo & conf = engine.conf_info; // note that we are assuming the same r_index and t_index for both forecasts - // and obs, which might not be true if mvmode were to allow >1 index - // (currently it does not) + // and obs R_index = r_index; T_index = t_index; @@ -814,18 +819,22 @@ void ModeExecutive::do_conv_thresh_traditional(const int r_index, const int t_in /////////////////////////////////////////////////////////////////////// -void ModeExecutive::do_conv_thresh_multivar_super() +void ModeExecutive::do_conv_thresh_multivar_super(int rIndexF, int tIndexF, + int, int) { ModeConfInfo & conf = engine.conf_info; - R_index = 0; - T_index = 0; + R_index = rIndexF; + T_index = tIndexF; SingleThresh s("ne-9999"); - conf.set_conv_thresh(s); - conf.set_conv_radius(0.0); - conf.set_merge_thresh_by_index(T_index); + conf.set_fcst_conv_thresh(s); + conf.set_fcst_conv_radius(0.0); + conf.set_fcst_merge_thresh(s); + conf.set_obs_conv_thresh(s); + conf.set_obs_conv_radius(0.0); + conf.set_obs_merge_thresh(s); // // Set up the engine with these raw fields @@ -855,17 +864,21 @@ void ModeExecutive::do_conv_thresh_multivar_super() /////////////////////////////////////////////////////////////////////// -void ModeExecutive::do_conv_thresh_multivar_intensity_compare() +void ModeExecutive::do_conv_thresh_multivar_intensity_compare(int rIndexF, int tIndexF, int rIndexO, int tIndexO) { ModeConfInfo & conf = engine.conf_info; - R_index = 0; - T_index = 0; + R_index = rIndexF; + T_index = tIndexF; - conf.set_conv_radius_by_index(R_index); - conf.set_conv_thresh_by_index(T_index); - conf.set_merge_thresh_by_index(T_index); + conf.set_obs_conv_radius_by_index(rIndexO); + conf.set_obs_conv_thresh_by_index(tIndexO); + conf.set_obs_merge_thresh_by_index(tIndexO); + + conf.set_fcst_conv_radius_by_index(rIndexF); + conf.set_fcst_conv_thresh_by_index(tIndexF); + conf.set_fcst_merge_thresh_by_index(tIndexF); // // Set up the engine with these raw fields @@ -893,39 +906,35 @@ void ModeExecutive::do_conv_thresh_multivar_intensity_compare() /////////////////////////////////////////////////////////////////////// -void ModeExecutive::do_conv_thresh_multivar_simple(Processing_t p) +void ModeExecutive::do_conv_thresh_multivar_simple(Processing_t p, int rIndex, int) { - ModeConfInfo & conf = engine.conf_info; - - R_index = 0; - T_index = 0; + bool obs = conf.data_type == ModeDataType::MvMode_Obs; + string what; + if (obs) { + what = "observation field"; + } else { + what = "forecast field"; + } + mlog << Debug(2) << "Identifying objects in the " << what << " for " << stype(p) << "\n"; if (p == MULTIVAR_SIMPLE_MERGE) { + conf.set_conv_radius_by_index(R_index); // need this because exec was killed after SIMPLE conf.set_conv_thresh_by_merge_index(T_index); } else if (p == MULTIVAR_SIMPLE) { - conf.set_conv_radius_by_index(0); - conf.set_conv_thresh_by_index(0); + conf.set_conv_radius_by_index(R_index); + conf.set_conv_thresh_by_index(T_index); } else { mlog << Error << "\nModeExecutive::do_conv_thresh_multivar_simple() -> " << "Wrong processing type input " << stype(p) << "\"\n\n"; exit(1); } - conf.set_merge_thresh_by_index(0); + conf.set_merge_thresh_by_index(T_index); // // Set up the engine with these raw fields // - - string what; - if (conf.data_type == ModeDataType::MvMode_Obs) { - what = "observation field"; - } else { - what = "forecast field"; - } - mlog << Debug(2) << "Identifying objects in the " << what << "...\n"; - engine.set(Fcst_sd, Obs_sd); // (ct_stats not needed for simple or merge, only one field) @@ -933,7 +942,7 @@ void ModeExecutive::do_conv_thresh_multivar_simple(Processing_t p) // done // - local_r_index = 0; + local_r_index = rIndex; return; @@ -1066,7 +1075,8 @@ void ModeExecutive::process_masks(ShapeData & fcst_sd, ShapeData & obs_sd) { - ShapeData grid_mask_sd, poly_mask_sd; + ShapeData grid_mask_sd; + ShapeData poly_mask_sd; ConcatString name; mlog << Debug(2) @@ -1123,7 +1133,8 @@ void ModeExecutive::process_fcst_masks(ShapeData & fcst_sd) { - ShapeData grid_mask_sd, poly_mask_sd; + ShapeData grid_mask_sd; + ShapeData poly_mask_sd; ConcatString name; mlog << Debug(3) << "Processing masking regions.\n"; @@ -1167,11 +1178,11 @@ void ModeExecutive::process_obs_masks(ShapeData & obs_sd) { - ShapeData grid_mask_sd, poly_mask_sd; + ShapeData grid_mask_sd; + ShapeData poly_mask_sd; ConcatString name; - mlog << Debug(2) - << "Processing masking regions.\n"; + mlog << Debug(3) << "Processing masking regions.\n"; // Parse the grid mask into a ShapeData object if(engine.conf_info.mask_grid_flag != FieldType::None) { @@ -1282,21 +1293,22 @@ void ModeExecutive::process_output_multivar_intensity_compare(const MultiVarData double fmax = mvdf->_data_max; double omin = mvdo->_data_min; double omax = mvdo->_data_max; - double data_min, data_max; - if (!is_bad_data(fmin) && !is_bad_data(omin)) data_min = min(fmin, omin); - else if(!is_bad_data(fmin) && is_bad_data(omin)) data_min = fmin; - else if( is_bad_data(fmin) && !is_bad_data(omin)) data_min = omin; - - if (!is_bad_data(fmax) && !is_bad_data(omax)) data_max = max(fmax, omax); - else if(!is_bad_data(fmax) && is_bad_data(omax)) data_max = fmax; - else if( is_bad_data(fmax) && !is_bad_data(omax)) data_max = omax; + double dmin; + double dmax; + if (!is_bad_data(fmin) && !is_bad_data(omin)) dmin = min(fmin, omin); + else if(!is_bad_data(fmin) && is_bad_data(omin)) dmin = fmin; + else if( is_bad_data(fmin) && !is_bad_data(omin)) dmin = omin; + + if (!is_bad_data(fmax) && !is_bad_data(omax)) dmax = max(fmax, omax); + else if(!is_bad_data(fmax) && is_bad_data(omax)) dmax = fmax; + else if( is_bad_data(fmax) && !is_bad_data(omax)) dmax = omax; set_raw_to_full(mvdf->_simple->_raw_data,mvdo->_simple->_raw_data, - mvdf->_nx, mvdf->_ny, data_min, data_max); + mvdf->_nx, mvdf->_ny, dmin, dmax); 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; @@ -1333,13 +1345,13 @@ void ModeExecutive::compute_ct_stats() { - int i, x, y; - ShapeData fcst_mask, obs_mask; + ShapeData fcst_mask; + ShapeData obs_mask; mlog << Debug(2) << "Computing contingency table statistics...\n"; - for(i=0; iis_bad_data(x, y) || @@ -1512,7 +1524,9 @@ void ModeExecutive::write_obj_stats() { - AsciiTable obj_at, fcst_merge_at, obs_merge_at; + AsciiTable obj_at; + AsciiTable fcst_merge_at; + AsciiTable obs_merge_at; ofstream out; ConcatString stat_file; @@ -1698,45 +1712,44 @@ void ModeExecutive::write_obj_netcdf(const ModeNcOutInfo & info) if ( info.all_false() ) return; - int n, x, y; ConcatString out_file; ConcatString s; const ConcatString fcst_thresh = engine.conf_info.Fcst->conv_thresh.get_str(5); const ConcatString obs_thresh = engine.conf_info.Obs->conv_thresh.get_str(5); - float *fcst_raw_data = (float *) nullptr; - float *fcst_obj_raw_data = (float *) nullptr; - int *fcst_obj_data = (int *) nullptr; - int *fcst_clus_data = (int *) nullptr; + float *fcst_raw_data = nullptr; + float *fcst_obj_raw_data = nullptr; + int *fcst_obj_data = nullptr; + int *fcst_clus_data = nullptr; - float *obs_raw_data = (float *) nullptr; - float *obs_obj_raw_data = (float *) nullptr; - int *obs_obj_data = (int *) nullptr; - int *obs_clus_data = (int *) nullptr; + float *obs_raw_data = nullptr; + float *obs_obj_raw_data = nullptr; + int *obs_obj_data = nullptr; + int *obs_clus_data = nullptr; - NcFile *f_out = (NcFile *) nullptr; + NcFile *f_out = nullptr; - NcDim lat_dim ; - NcDim lon_dim ; + NcDim lat_dim; + NcDim lon_dim; - NcDim fcst_thresh_dim ; - NcDim obs_thresh_dim ; + NcDim fcst_thresh_dim; + NcDim obs_thresh_dim; - NcVar fcst_raw_var ; - NcVar fcst_obj_raw_var ; - NcVar fcst_obj_var ; - NcVar fcst_clus_var ; + NcVar fcst_raw_var; + NcVar fcst_obj_raw_var; + NcVar fcst_obj_var; + NcVar fcst_clus_var; - NcVar obs_raw_var ; - NcVar obs_obj_raw_var ; - NcVar obs_obj_var ; - NcVar obs_clus_var ; + NcVar obs_raw_var; + NcVar obs_obj_raw_var; + NcVar obs_obj_var; + NcVar obs_clus_var; - NcVar fcst_radius_var ; - NcVar obs_radius_var ; + NcVar fcst_radius_var; + NcVar obs_radius_var; - NcVar fcst_thresh_var ; - NcVar obs_thresh_var ; + NcVar fcst_thresh_var; + NcVar obs_thresh_var; // // Create output NetCDF file name @@ -1943,11 +1956,11 @@ void ModeExecutive::write_obj_netcdf(const ModeNcOutInfo & info) } - for(x=0; xdata (x, y); - obs_raw_data[n] = engine.obs_raw->data (x, y); + fcst_raw_data[n] = (float) engine.fcst_raw->data (x, y); + obs_raw_data[n] = (float) 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); + fcst_obj_raw_data[n] = (float) 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)); @@ -1981,7 +1994,7 @@ void ModeExecutive::write_obj_netcdf(const ModeNcOutInfo & info) 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); + obs_obj_raw_data[n] = (float) 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)); @@ -2038,75 +2051,63 @@ void ModeExecutive::write_obj_netcdf(const ModeNcOutInfo & info) // Write the forecast and observation raw value variables // - if ( info.do_raw ) { - - if( !put_nc_data_with_dims(&fcst_raw_var, &fcst_raw_data[0], grid.ny(), grid.nx()) || - !put_nc_data_with_dims(&obs_raw_var, &obs_raw_data[0], grid.ny(), grid.nx()) ) { - - mlog << Error << "\nModeExecutive::write_obj_netcdf() -> " - << "error with the fcst_raw_var->put or obs_raw_var->put\n\n"; - exit(1); - } + if( info.do_raw && + (!put_nc_data_with_dims(&fcst_raw_var, &fcst_raw_data[0], grid.ny(), grid.nx()) || + !put_nc_data_with_dims(&obs_raw_var, &obs_raw_data[0], grid.ny(), grid.nx())) ) { + mlog << Error << "\nModeExecutive::write_obj_netcdf() -> " + << "error with the fcst_raw_var->put or obs_raw_var->put\n\n"; + exit(1); } - if ( info.do_object_raw ) { - - if( !put_nc_data_with_dims(&fcst_obj_raw_var, &fcst_obj_raw_data[0], grid.ny(), grid.nx()) || - !put_nc_data_with_dims(&obs_obj_raw_var, &obs_obj_raw_data[0], grid.ny(), grid.nx()) ) { - - mlog << Error << "\nModeExecutive::write_obj_netcdf() -> " - << "error with the fcst_obj_raw_var->put or obs_obj_raw_var->put\n\n"; - exit(1); - } + if ( info.do_object_raw && + (!put_nc_data_with_dims(&fcst_obj_raw_var, &fcst_obj_raw_data[0], grid.ny(), grid.nx()) || + !put_nc_data_with_dims(&obs_obj_raw_var, &obs_obj_raw_data[0], grid.ny(), grid.nx())) ) { + mlog << Error << "\nModeExecutive::write_obj_netcdf() -> " + << "error with the fcst_obj_raw_var->put or obs_obj_raw_var->put\n\n"; + exit(1); } // // Write the forecast and observation object ID variables // - if ( info.do_object_id ) { - - if( !put_nc_data_with_dims(&fcst_obj_var, &fcst_obj_data[0], grid.ny(), grid.nx()) || - !put_nc_data_with_dims(&obs_obj_var, &obs_obj_data[0], grid.ny(), grid.nx()) ) { - - mlog << Error << "\nModeExecutive::write_obj_netcdf() -> " - << "error with the fcst_obj_var->put or obs_obj_var->put\n\n"; - exit(1); - } + if ( info.do_object_id && + (!put_nc_data_with_dims(&fcst_obj_var, &fcst_obj_data[0], grid.ny(), grid.nx()) || + !put_nc_data_with_dims(&obs_obj_var, &obs_obj_data[0], grid.ny(), grid.nx())) ) { + mlog << Error << "\nModeExecutive::write_obj_netcdf() -> " + << "error with the fcst_obj_var->put or obs_obj_var->put\n\n"; + exit(1); } // // Write the forecast and observation cluster object ID variables // - if ( info.do_cluster_id ) { - - if( !put_nc_data_with_dims(&fcst_clus_var, &fcst_clus_data[0], grid.ny(), grid.nx()) || - !put_nc_data_with_dims(&obs_clus_var, &obs_clus_data[0], grid.ny(), grid.nx()) ) { - - mlog << Error << "\nModeExecutive::write_obj_netcdf() -> " - << "error with the fcst_clus_var->put or obs_clus_var->put\n\n"; - exit(1); - } + if ( info.do_cluster_id && + (!put_nc_data_with_dims(&fcst_clus_var, &fcst_clus_data[0], grid.ny(), grid.nx()) || + !put_nc_data_with_dims(&obs_clus_var, &obs_clus_data[0], grid.ny(), grid.nx())) ) { + mlog << Error << "\nModeExecutive::write_obj_netcdf() -> " + << "error with the fcst_clus_var->put or obs_clus_var->put\n\n"; + exit(1); } // // Delete allocated memory // - if (fcst_raw_data) { delete [] fcst_raw_data; fcst_raw_data = (float *) nullptr; } - if (fcst_obj_raw_data) { delete [] fcst_obj_raw_data; fcst_obj_raw_data = (float *) nullptr; } - if (fcst_obj_data) { delete [] fcst_obj_data; fcst_obj_data = (int *) nullptr; } - if (fcst_clus_data) { delete [] fcst_clus_data; fcst_clus_data = (int *) nullptr; } + if (fcst_raw_data) { delete [] fcst_raw_data; fcst_raw_data = nullptr; } + if (fcst_obj_raw_data) { delete [] fcst_obj_raw_data; fcst_obj_raw_data = nullptr; } + if (fcst_obj_data) { delete [] fcst_obj_data; fcst_obj_data = nullptr; } + if (fcst_clus_data) { delete [] fcst_clus_data; fcst_clus_data = nullptr; } - if (obs_raw_data) { delete [] obs_raw_data; obs_raw_data = (float *) nullptr; } - if (obs_obj_raw_data) { delete [] obs_obj_raw_data; obs_obj_raw_data = (float *) nullptr; } - if (obs_obj_data) { delete [] obs_obj_data; obs_obj_data = (int *) nullptr; } - if (obs_clus_data) { delete [] obs_clus_data; obs_clus_data = (int *) nullptr; } + if (obs_raw_data) { delete [] obs_raw_data; obs_raw_data = nullptr; } + if (obs_obj_raw_data) { delete [] obs_obj_raw_data; obs_obj_raw_data = nullptr; } + if (obs_obj_data) { delete [] obs_obj_data; obs_obj_data = nullptr; } + if (obs_clus_data) { delete [] obs_clus_data; obs_clus_data = nullptr; } // // Write out the values of the vertices of the polylines. @@ -2180,42 +2181,52 @@ void ModeExecutive::write_poly_netcdf(NcFile *f_out, ObjPolyType poly_type) { - int i, j, x, y, n_pts, n_poly; - double lat, lon; + int n_poly; + double lat; + double lon; - Polyline **poly = (Polyline **) nullptr; + Polyline **poly = nullptr; - int *poly_start = (int *) nullptr; - int *poly_npts = (int *) nullptr; - float *poly_lat = (float *) nullptr; - float *poly_lon = (float *) nullptr; - int *poly_x = (int *) nullptr; - int *poly_y = (int *) nullptr; + int *poly_start = nullptr; + int *poly_npts = nullptr; + float *poly_lat = nullptr; + float *poly_lon = nullptr; + int *poly_x = nullptr; + int *poly_y = nullptr; // Dimensions and variables for each object - NcDim obj_dim ; - NcVar obj_poly_start_var ; - NcVar obj_poly_npts_var ; + NcDim obj_dim; + NcVar obj_poly_start_var; + NcVar obj_poly_npts_var; // Dimensions and variables for each boundary point - NcDim poly_dim ; - NcVar poly_lat_var ; - NcVar poly_lon_var ; - NcVar poly_x_var ; - NcVar poly_y_var ; + NcDim poly_dim; + NcVar poly_lat_var; + NcVar poly_lon_var; + NcVar poly_x_var; + NcVar poly_y_var; // Dimension names - ConcatString obj_dim_name, poly_dim_name; + ConcatString obj_dim_name; + ConcatString poly_dim_name; // Variable names - ConcatString start_var_name, start_long_name; - ConcatString npts_var_name, npts_long_name; - ConcatString lat_var_name, lat_long_name; - ConcatString lon_var_name, lon_long_name; - ConcatString x_var_name, x_long_name; - ConcatString y_var_name, y_long_name; - ConcatString field_name, field_long; - ConcatString poly_name, poly_long; + ConcatString start_var_name; + ConcatString start_long_name; + ConcatString npts_var_name; + ConcatString npts_long_name; + ConcatString lat_var_name; + ConcatString lat_long_name; + ConcatString lon_var_name; + ConcatString lon_long_name; + ConcatString x_var_name; + ConcatString x_long_name; + ConcatString y_var_name; + ConcatString y_long_name; + ConcatString field_name; + ConcatString field_long; + ConcatString poly_name; + ConcatString poly_long; // Determine the number of polylines to be written // and set up strings @@ -2301,7 +2312,7 @@ void ModeExecutive::write_poly_netcdf(NcFile *f_out, ObjPolyType poly_type) poly = new Polyline * [n_poly]; // Point at the polyline to be written - for(i=0; in_points; + int n_pts = 0; + for(int i=0; in_points; // Define dimensions NcDim tmp_obj_dim = get_nc_dim(f_out, (string)obj_dim_name); @@ -2379,7 +2391,7 @@ void ModeExecutive::write_poly_netcdf(NcFile *f_out, ObjPolyType poly_type) // Store the points for each polyline // n_pts = 0; - for(i=0; in_points; - for(j=0; ju[j]); - y = nint(poly[i]->v[j]); + int x = nint(poly[i]->u[j]); + int y = nint(poly[i]->v[j]); poly_x[n_pts] = x; poly_y[n_pts] = y; // Convert to lat/lon and store them grid.xy_to_latlon(x, y, lat, lon); - poly_lat[n_pts] = lat; - poly_lon[n_pts] = -1.0*lon; + poly_lat[n_pts] = (float) lat; + poly_lon[n_pts] = -1.0 * ((float) lon); } } @@ -2460,7 +2472,7 @@ void ModeExecutive::write_ct_stats() AsciiTable cts_at; ofstream out; - int i, c; + int c; double v; ConcatString stat_file; @@ -2491,8 +2503,8 @@ void ModeExecutive::write_ct_stats() // Setup the AsciiTable to be used // cts_at.clear(); - i = n_mode_hdr_columns + n_mode_cts_columns; - cts_at.set_size(3, i); // Set table size + c = n_mode_hdr_columns + n_mode_cts_columns; + cts_at.set_size(3, c); // Set table size justify_mode_cols(cts_at); // Justify columns cts_at.set_precision( // Set the precision engine.conf_info.conf.output_precision()); @@ -2503,14 +2515,14 @@ void ModeExecutive::write_ct_stats() // // Write out the MODE header columns // - for(i=0; i values; vector count; @@ -99,7 +101,7 @@ static void _debug_shape_examine(string &name, const ShapeData &sd, values.push_back(v); count.push_back(1); } else { - int ii = vi - values.begin(); + auto ii = (int) (vi - values.begin()); count[ii] = count[ii] + 1; } } @@ -109,18 +111,25 @@ static void _debug_shape_examine(string &name, const ShapeData &sd, } } +ModeSuperObject::ModeSuperObject() +{ +} + ModeSuperObject::ModeSuperObject(bool isFcst, int n_files, bool do_clusters, + int r_index, int t_index, const vector &mvd, BoolCalc &calc) { _hasUnion = calc.has_union(); + _rIndex = r_index; + _tIndex = t_index; // // set the BoolPlane values using the mvd content // - BoolPlane * simple_plane = new BoolPlane [n_files]; - BoolPlane * merge_plane = new BoolPlane [n_files]; + auto simple_plane = new BoolPlane [n_files]; + auto merge_plane = new BoolPlane [n_files]; for (int j=0; jobjects_from_arrays(do_clusters, true, simple_plane[j]); @@ -137,7 +146,8 @@ ModeSuperObject::ModeSuperObject(bool isFcst, int n_files, bool do_clusters, _simple_result.set_size(nx, ny); merge_result.set_size(nx, ny); - string simple_name, merge_name; + string simple_name; + string merge_name; if (isFcst) { simple_name = "Fcst_Simple"; @@ -146,8 +156,10 @@ ModeSuperObject::ModeSuperObject(bool isFcst, int n_files, bool do_clusters, simple_name = "Obs_Simple"; merge_name = "Obs_Merge"; } - combine_boolplanes(simple_name, simple_plane, n_files, calc, _simple_result); - combine_boolplanes(merge_name, merge_plane, n_files, calc, merge_result); + + mlog << Debug(1) << "\n"; + combine_boolplanes(simple_name, _rIndex, _tIndex, simple_plane, n_files, calc, _simple_result); + combine_boolplanes(merge_name, _rIndex, _tIndex, merge_plane, n_files, calc, merge_result); // create ShapeData objects using something from mvd as a template // (shape data has 1's or bad) @@ -163,7 +175,7 @@ ModeSuperObject::ModeSuperObject(bool isFcst, int n_files, bool do_clusters, } } - ShapeData merge_sd = ShapeData(*(mvd[0]->_simple->_sd)); + auto merge_sd = ShapeData(*(mvd[0]->_simple->_sd)); for (int x=0; x &mvd, BoolCalc &calc); inline ~ModeSuperObject() {} @@ -40,6 +43,8 @@ class ModeSuperObject { bool _isFcst; bool _hasUnion; + int _rIndex; + int _tIndex; BoolPlane _simple_result; ShapeData _simple_sd; ShapeData _merge_sd_split; diff --git a/src/tools/core/mode/multivar_frontend.cc b/src/tools/core/mode/multivar_frontend.cc index baa0537791..77d9882eb0 100644 --- a/src/tools/core/mode/multivar_frontend.cc +++ b/src/tools/core/mode/multivar_frontend.cc @@ -10,7 +10,6 @@ #include "multivar_frontend.h" - #include "mode_usage.h" #ifdef WITH_PYTHON @@ -35,8 +34,7 @@ static const char mode_default_config [] = "MET_BASE/config/MODEMultivarConfig_d static const int dir_creation_mode = 0755; -static ModeExecutive *mode_exec = 0; - +static ModeExecutive *mode_exec = nullptr; //////////////////////////////////////////////////////////////////////// @@ -46,38 +44,42 @@ MultivarFrontEnd::MultivarFrontEnd() do_clusters = false; default_out_dir = "."; compress_level = -1; - mode_exec = 0; + mode_exec = nullptr; } //////////////////////////////////////////////////////////////////////// -int MultivarFrontEnd::run(const StringArray & Argv) - +MultivarFrontEnd::~MultivarFrontEnd() { + if ( mode_exec ) { + delete mode_exec; mode_exec = nullptr; + } + } - // initialize +//////////////////////////////////////////////////////////////////////// - init(Argv); +int MultivarFrontEnd::run(const StringArray & Argv) +{ + // initialize - mlog << Debug(2) << "\n" << sep << "\n"; + _init(Argv); - // read in all the data + mlog << Debug(1) << "\n" << sep << "\n"; // in the conf object, shift *can* be set independently for obs and fcst int shift = config.shift_right; + // read in all the data for (int i=0; i" + << "all convolution threshold arrays must have the same number of elements\n\n"; + exit ( 1 ); + } + if (NCRF != NCRO) { + mlog << Error << "\nMultivarFrontEnd::run() ->" + << "all convolution radius arrays must have the same number of elements\n\n"; + exit ( 1 ); + } - // - // do the individual mode runs which produce everything needed to create - // super objects (stored in 'mvdObs', 'mvdFcst') (both simple and merge steps - // are done here). - // + if ((!config.quilt) && (NCTF != NCRF || NCTO != NCRO)) { + mlog << Error << "\nMultivarFrontEnd::run() ->" + << "all convolution radius and threshold arrays must have the same number of elements without quilting\n\n"; + exit ( 1 ); + } - for (int j=0; j fcstSimple; + vector obsSimple; + + // create simple objects for all convolution settings + if (config.quilt) { + for (int ir=0; irprint(); - } // for j + // Note at this point we know the compare index arrays are the same length for fcst + // and obs - for (int j=0; jprint(); - } // for j + // Filter the data to within the superobjects only and do statistics by invoking mode + // algorithm again on the masked data pairs - mlog << Debug(2) << "\n finished with simple multivar mode runs " << "\n" << sep << "\n"; + for (int k=0; kgrid(); - GrdFileType ft = f->file_type(); - - //? - f->set_shift_right(shift); - - // update config now that we know file type (this sets Fcst to index i) - DataPlane dp; - - if (type == ModeDataType::MvMode_Fcst) { - config.process_config_field(ft, other_t, type, index); - f->data_plane(*(config.Fcst->var_info), dp); - fcstInput.push_back(ModeInputData(name, dp, g)); - } else { - config.process_config_field(other_t, ft, type, index); - f->data_plane(*(config.Obs->var_info), dp); - obsInput.push_back(ModeInputData(name, dp, g)); - } - - delete f; -} - -//////////////////////////////////////////////////////////////////////// - -void MultivarFrontEnd::create_verif_grid() -{ - mlog << Debug(2) << "\n creating the verification grid \n" << sep << "\n"; - - _init_exec(ModeExecutive::TRADITIONAL, "None", "None"); - mode_exec->setup_verification_grid(fcstInput[0], obsInput[0], config); - verification_grid = mode_exec->grid; - delete mode_exec; mode_exec = 0; -} - -//////////////////////////////////////////////////////////////////////// - -MultiVarData *MultivarFrontEnd::create_simple_objects(ModeDataType dtype, int j, - int n_files, - const string &filename, - const ModeInputData &input) -{ - // - // create simple non merged objects - // - _simple_objects(ModeExecutive::MULTIVAR_SIMPLE, dtype, j, n_files, - filename, input); - MultiVarData *mvdi = mode_exec->get_multivar_data(dtype); - delete mode_exec; mode_exec = 0; - - // - // create simple merged objects - // - _simple_objects(ModeExecutive::MULTIVAR_SIMPLE_MERGE, dtype, j, n_files, - filename, input); - mode_exec->add_multivar_merge_data(mvdi, dtype); - delete mode_exec; mode_exec = 0; - return mvdi; -} - -//////////////////////////////////////////////////////////////////////// - -void -MultivarFrontEnd::create_intensity_comparisons(int findex, int oindex, - const ModeSuperObject &fsuper, - const ModeSuperObject &osuper, - MultiVarData &mvdf, MultiVarData &mvdo, - const string &fcst_filename, - const string &obs_filename) -{ - - // mask the input data to be valid only inside the simple super objects - fsuper.mask_data_simple("Fcst", mvdf); - osuper.mask_data_simple("Obs", mvdo); - - mlog << Debug(1) << "Running mvmode intensity comparisions \n\n"; - - _init_exec(ModeExecutive::MULTIVAR_INTENSITY, fcst_filename, obs_filename); - mode_exec->init_multivar_intensities(config); - - ModeConfInfo & conf = mode_exec->engine.conf_info; - conf.set_field_index(findex, oindex); - - // for multivar intensities, explicity set the level and units using stored values - // from pass1 - conf.Fcst->var_info->set_level_name(mvdf._level.c_str()); - conf.Fcst->var_info->set_units(mvdf._units.c_str()); - if (fsuper._hasUnion && conf.Fcst->merge_flag == MergeType::Thresh) { - mlog << Warning << "\nModeFrontEnd::multivar_intensity_comparisons() -> " - << "Logic includes union '||' along with 'merge_flag=THRESH' " - << ". This can lead to bad results\n\n"; - } - conf.Obs->var_info->set_level_name(mvdo._level.c_str()); - conf.Obs->var_info->set_units(mvdo._units.c_str()); - if (osuper._hasUnion && conf.Obs->merge_flag == MergeType::Thresh) { - mlog << Warning << "\nModeFrontEnd::multivar_intensity_comparisons() -> " - << "Logic includes union '||' along with 'merge_flag=THRESH' " - << ". This can lead to bad results\n\n"; - } - - // - // set up data access using inputs - // - mode_exec->setup_multivar_fcst_obs_data_intensities(mvdf, mvdo); - - // - // run the mode algorithm for multivar intensities - // - _intensity_compare_mode_algorithm(mvdf, mvdo, fsuper, osuper); - - delete mode_exec; mode_exec = 0; -} - -//////////////////////////////////////////////////////////////////////// - -void MultivarFrontEnd::process_superobjects(ModeSuperObject &fsuper, - ModeSuperObject &osuper, - const MultiVarData &mvdf, - const MultiVarData &mvdo) -{ - mlog << Debug(1) << "Running superobject mode \n\n"; - - // set the data to 0 inside superobjects and missing everywhere else + int Argc = Argv.n(); - fsuper.mask_data_super("FcstSimple", mvdf); - osuper.mask_data_super("ObsSimple", mvdo); + if ( Argc < 4 ) multivar_usage(); - _init_exec(ModeExecutive::MULTIVAR_SUPER, "None", "None"); - mode_exec->init_multivar_intensities(config); + // set some logging related things here, used in all further processing + _process_command_line(Argv); - ModeConfInfo & conf = mode_exec->engine.conf_info; - if ((fsuper._hasUnion || osuper._hasUnion) && - (conf.Fcst->merge_flag == MergeType::Thresh || - conf.Obs->merge_flag == MergeType::Thresh)) { - mlog << Warning << "\nModeFrontEnd::run_super() -> " - << "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_multivar_fcst_obs_data_super(fsuper._simple_sd, osuper._simple_sd, - *mvdf._grid); + // read the config as fully as possible without any data reads + // (Initialize all the input fields) + _read_config(config_file); - // run the mode algorithm - _superobject_mode_algorithm(fsuper, osuper); + // check for length discrepencies and set up input files + _setup_inputs(); - delete mode_exec; mode_exec = 0; + // set output path + _set_output_path(); } //////////////////////////////////////////////////////////////////////// @@ -419,7 +263,6 @@ void MultivarFrontEnd::process_superobjects(ModeSuperObject &fsuper, void MultivarFrontEnd::_process_command_line(const StringArray & argv) { - CommandLine cline; // @@ -450,16 +293,12 @@ void MultivarFrontEnd::_process_command_line(const StringArray & argv) config_file = cline[2]; return; - } //////////////////////////////////////////////////////////////////////// - void MultivarFrontEnd::_read_config(const string & filename) - { - ConcatString path; path = replace_path(mode_default_config); @@ -473,12 +312,8 @@ void MultivarFrontEnd::_read_config(const string & filename) // what is this, command line overrides config? look deeper.. remove from exec // except traditional mode if (compress_level >= 0) config.nc_info.set_compress_level(compress_level); - // from within mode_exec: - // engine.conf_info.nc_info.compress_level = engine.conf_info.get_compression_level(); - return; - } //////////////////////////////////////////////////////////////////////// @@ -491,7 +326,7 @@ void MultivarFrontEnd::_setup_inputs() if ( config.fcst_multivar_logic.empty() ) { - mlog << Error << "\nmultivar_consistency_checks() ->" + mlog << Error << "\nMultivarFrontEnd::_setup_inputs() ->" << "fcst multivar logic not specified in multivar mode!\n\n"; exit ( 1 ); @@ -499,7 +334,7 @@ void MultivarFrontEnd::_setup_inputs() if ( config.obs_multivar_logic.empty() ) { - mlog << Error << "\nmultivar_consistency_checks() ->" + mlog << Error << "\nMultivarFrontEnd::_setup_inputs() ->" << "obs multivar logic not specified in multivar mode!\n\n"; exit ( 1 ); @@ -516,7 +351,7 @@ void MultivarFrontEnd::_setup_inputs() // if ( n_fcst_files < 2 && n_obs_files < 2) { - mlog << Error << "\nmultivar_consistency_checks() ->" + mlog << Error << "\nMultivarFrontEnd::_setup_inputs() ->" << "Want at least 2 input files for fcst or obs in multivar mode, neither had 2 or more\n\n"; exit ( 1 ); } @@ -538,7 +373,7 @@ void MultivarFrontEnd::_setup_inputs() if (config.fcst_multivar_compare_index.n() != config.obs_multivar_compare_index.n()) { - mlog << Error << "\nmultivar_consistency_checks() ->" + mlog << Error << "\nMultivarFrontEnd::_setup_inputs() ->" << " Need equal number of multivar_compare_index entries for obs and fcst\n\n"; exit(1); } @@ -549,13 +384,13 @@ void MultivarFrontEnd::_setup_inputs() int findex = config.fcst_multivar_compare_index[k]; int oindex = config.obs_multivar_compare_index[k]; if (findex <= 0 || findex > n_fcst_files) { - mlog << Error << "\nmultivar_consistency_checks() ->" + mlog << Error << "\nMultivarFrontEnd::_setup_inputs() ->" << " forecast index " << findex << " out of range, " << conf_key_fcst_multivar_compare_index << " array\n"; badIndex = true; } if (oindex <= 0 || oindex > n_obs_files) { - mlog << Error << "\nmultivar_consistency_checks() ->" + mlog << Error << "\nMultivarFrontEnd::_setup_inputs() ->" << " obs index " << oindex << " out of range, " << conf_key_obs_multivar_compare_index << " array\n"; badIndex = true; @@ -593,7 +428,7 @@ void MultivarFrontEnd::_set_output_path() if ( status < 0 ) { - mlog << Error << "\nset_multivar_dir() ->" + mlog << Error << "\nMultivarFrontEnd::_set_output_path() ->" << " unable to create output directory \"" << output_path << "\"\n\n"; @@ -604,25 +439,24 @@ void MultivarFrontEnd::_set_output_path() //////////////////////////////////////////////////////////////////////// -int MultivarFrontEnd::_mkdir(const char *dir) +int MultivarFrontEnd::_mkdir(const char *dir) const { char tmp[256]; - char *p = NULL; size_t len; snprintf(tmp, sizeof(tmp),"%s",dir); len = strlen(tmp); if (tmp[len - 1] == '/') tmp[len - 1] = 0; - for (p = tmp + 1; *p; p++) + for (char *p = tmp + 1; *p; p++) if (*p == '/') { *p = 0; string s = tmp; - if (s != ".") { - if (mkdir(tmp, dir_creation_mode) < 0) { - mlog << Error << "\n_mkdir() -> Error making " << tmp << "\n"; - return -1; - } + if (s != "." && + mkdir(tmp, dir_creation_mode) < 0) { + mlog << Error << "\nMultivarFrontEnd::_mkdir() ->" + << "Error making " << tmp << "\n"; + return -1; } *p = '/'; } @@ -632,71 +466,201 @@ int MultivarFrontEnd::_mkdir(const char *dir) //////////////////////////////////////////////////////////////////////// +void MultivarFrontEnd::_read_input(const string &name, int index, ModeDataType type, + GrdFileType f_t, GrdFileType other_t, int shift) +{ + Met2dDataFileFactory mtddf_factory; + Met2dDataFile *f = mtddf_factory.new_met_2d_data_file(name.c_str(), f_t); + if (!f) { + mlog << Error << "\nMultivarFrontEnd::_read_input() ->" + << "\nTrouble reading fcst file \"" << name << "\"\n\n"; + exit(1); + } + Grid g = f->grid(); + GrdFileType ft = f->file_type(); + + //? + f->set_shift_right(shift); + + // update config now that we know file type (this sets Fcst to index i) + DataPlane dp; + + if (type == ModeDataType::MvMode_Fcst) { + config.process_config_field(ft, other_t, type, index); + f->data_plane(*(config.Fcst->var_info), dp); + fcstInput.push_back(ModeInputData(name, dp, g)); + } else { + config.process_config_field(other_t, ft, type, index); + f->data_plane(*(config.Obs->var_info), dp); + obsInput.push_back(ModeInputData(name, dp, g)); + } + + delete f; +} + +//////////////////////////////////////////////////////////////////////// + +void MultivarFrontEnd::_create_verif_grid() +{ + mlog << Debug(1) << "\n creating the verification grid \n" << sep << "\n"; + + _init_exec(ModeExecutive::TRADITIONAL, "None", "None"); + mode_exec->setup_verification_grid(fcstInput[0], obsInput[0], config); + verification_grid = mode_exec->grid; + delete mode_exec; mode_exec = nullptr; +} + +//////////////////////////////////////////////////////////////////////// + +void MultivarFrontEnd::_create_simple_objects(ModeDataType dtype, const std::string &name, + int rIndex, int tIndex, int n_files, + const StringArray &filenames, + const std::vector &input, + BoolCalc &calc, SimpleObjects &O) const +{ + O.init(dtype, rIndex, tIndex); + for (int j=0; jprint(); + O._mvd.push_back(mvdi); + } + O.setSuper(dtype == ModeDataType::MvMode_Fcst, n_files, do_clusters, calc); +} + +//////////////////////////////////////////////////////////////////////// + +MultiVarData *MultivarFrontEnd::_create_simple_multivar_data(ModeDataType dtype, + int rIndex, int tIndex, + int j, int n_files, + const string &filename, + const ModeInputData &input) const +{ + // + // create simple non merged objects + // + _simple_objects(ModeExecutive::MULTIVAR_SIMPLE, dtype, rIndex, tIndex, j, n_files, + filename, input); + MultiVarData *mvdi = mode_exec->get_multivar_data(dtype); + delete mode_exec; mode_exec = nullptr; + + // + // create simple merged objects + // + _simple_objects(ModeExecutive::MULTIVAR_SIMPLE_MERGE, dtype, rIndex, tIndex, j, n_files, + filename, input); + mode_exec->add_multivar_merge_data(mvdi, dtype); + delete mode_exec; mode_exec = nullptr; + return mvdi; +} + +//////////////////////////////////////////////////////////////////////// + void MultivarFrontEnd::_simple_objects(ModeExecutive::Processing_t p, - ModeDataType dtype, - int j, int n_files, const string &filename, - const ModeInputData &input) + ModeDataType dtype, int rIndex, + int tIndex, int j, int n_files, + const string &filename, + const ModeInputData &input) const { if (dtype == ModeDataType::MvMode_Fcst) { _init_exec(p, filename, "None"); - mode_exec->init_multivar_simple(j, n_files, dtype, config); + mode_exec->init_multivar_simple(rIndex, tIndex, j, dtype, config); mode_exec->setup_multivar_fcst_data(verification_grid, input); } else { _init_exec(p, "None", filename); - mode_exec->init_multivar_simple(j, n_files, dtype, config); + mode_exec->init_multivar_simple(rIndex, tIndex, j, dtype, config); mode_exec->setup_multivar_obs_data(verification_grid, input); } - _simple_mode_algorithm(p); + _simple_mode_algorithm(p, rIndex, tIndex); } //////////////////////////////////////////////////////////////////////// -void MultivarFrontEnd::_init_exec(ModeExecutive::Processing_t p, - const string &ffile, - const string &ofile) +void MultivarFrontEnd::_simple_mode_algorithm(ModeExecutive::Processing_t p, + int rIndex, int tIndex) const { - mlog << Debug(1) << "Running multivar front end for " << ModeExecutive::stype(p) << "\n"; - - if ( mode_exec ) { delete mode_exec; mode_exec = 0; } - - mode_exec = new ModeExecutive(); - // compress_level = -1; - mode_exec->fcst_file = ffile; - mode_exec->obs_file = ofile; - - mode_exec->match_config_file = config_file; // this is never used - mode_exec->out_dir = output_path; + mode_exec->clear_internal_r_index(); + mode_exec->do_conv_thresh_multivar_simple(p, rIndex, tIndex); + mode_exec->clear_internal_r_index(); +#ifdef WITH_PYTHON + GP.finalize(); + #endif } //////////////////////////////////////////////////////////////////////// void -MultivarFrontEnd::_superobject_mode_algorithm(const ModeSuperObject &fsuper, - const ModeSuperObject &osuper) +MultivarFrontEnd::_create_intensity_comparisons(SimpleObjects &fcsts, int findex, + SimpleObjects &obs, int oindex, + const string &fcst_filename, + const string &obs_filename) { - _mode_algorithm_init(); - mode_exec->clear_internal_r_index(); - mode_exec->do_conv_thresh_multivar_super(); - mode_exec->do_match_merge_multivar(fsuper._merge_sd_split, osuper._merge_sd_split, - ModeExecutive::MULTIVAR_SUPER); - mode_exec->process_output_multivar_super(); - mode_exec->clear_internal_r_index(); -#ifdef WITH_PYTHON - GP.finalize(); - #endif + MultiVarData *mvdf = fcsts._mvd[findex]; + MultiVarData *mvdo = obs._mvd[oindex]; + + // mask the input data to be valid only inside the simple super objects + fcsts._super.mask_data_simple("Fcst", *mvdf); + obs._super.mask_data_simple("Obs", *mvdo); + + // this debug statement assumes fcsts and obs have same conv radius and thresh indices + // which is currently required + mlog << Debug(1) << "\n" << sep + << "\nRunning mvmode intensity comparisions conv_radius[" << fcsts._rIndex+1 + << "] conv_thresh[" << fcsts._tIndex+1 << "]\n" << sep << "\n"; + + _init_exec(ModeExecutive::MULTIVAR_INTENSITY, fcst_filename, obs_filename); + mode_exec->init_multivar_intensities(config); + + ModeConfInfo & conf = mode_exec->engine.conf_info; + conf.set_field_index(findex, oindex); + + // for multivar intensities, explicity set the level and units using stored values + // from pass1 + conf.Fcst->var_info->set_level_name(mvdf->_level.c_str()); + conf.Fcst->var_info->set_units(mvdf->_units.c_str()); + if (fcsts._super._hasUnion && conf.Fcst->merge_flag == MergeType::Thresh) { + mlog << Warning << "\nModeFrontEnd::_create_intensity_comparisons() -> " + << "Logic includes union '||' along with 'merge_flag=THRESH' " + << ". This can lead to bad results\n\n"; + } + conf.Obs->var_info->set_level_name(mvdo->_level.c_str()); + conf.Obs->var_info->set_units(mvdo->_units.c_str()); + if (obs._super._hasUnion && conf.Obs->merge_flag == MergeType::Thresh) { + mlog << Warning << "\nModeFrontEnd::_create_intensity_comparisons() -> " + << "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_multivar_fcst_obs_data_intensities(*mvdf, *mvdo); + + // + // run the mode algorithm for multivar intensities + // + _intensity_compare_mode_algorithm(fcsts._rIndex, fcsts._tIndex, obs._rIndex, obs._tIndex, *mvdf, *mvdo, + fcsts._super, obs._super); + + delete mode_exec; mode_exec = nullptr; } //////////////////////////////////////////////////////////////////////// void -MultivarFrontEnd::_intensity_compare_mode_algorithm(const MultiVarData &mvdf, +MultivarFrontEnd::_intensity_compare_mode_algorithm(int rIndexF, int tIndexF, + int rIndexO, int tIndexO, + const MultiVarData &mvdf, const MultiVarData &mvdo, const ModeSuperObject &fsuper, const ModeSuperObject &osuper) { - _mode_algorithm_init(); - mode_exec->do_conv_thresh_multivar_intensity_compare(); + mode_exec->do_conv_thresh_multivar_intensity_compare(rIndexF, tIndexF, rIndexO, tIndexO); mode_exec->do_match_merge_multivar(fsuper._merge_sd_split, osuper._merge_sd_split, ModeExecutive::MULTIVAR_INTENSITY); // here replace raw data and min/max for plotting @@ -707,16 +671,62 @@ MultivarFrontEnd::_intensity_compare_mode_algorithm(const MultiVarData &mvdf, #endif } +//////////////////////////////////////////////////////////////////////// + +void MultivarFrontEnd::_process_superobjects(SimpleObjects &fcsts, SimpleObjects &obs) +{ + mlog << Debug(1) << "\n" << sep + << "\nRunning mvmode superobject analysis conv_radius[" << fcsts._rIndex+1 + << "] conv_thresh[" << fcsts._tIndex+1 << "]\n" << sep << "\n"; + + const MultiVarData *mvdf = fcsts._mvd[0]; + const MultiVarData *mvdo = obs._mvd[0]; + + // set the data to 0 inside superobjects and missing everywhere else + + fcsts._super.mask_data_super("FcstSimple", *mvdf); + obs._super.mask_data_super("ObsSimple", *mvdo); + + _init_exec(ModeExecutive::MULTIVAR_SUPER, "None", "None"); + mode_exec->init_multivar_intensities(config); + + const ModeConfInfo & conf = mode_exec->engine.conf_info; + if ((fcsts._super._hasUnion || obs._super._hasUnion) && + (conf.Fcst->merge_flag == MergeType::Thresh || + conf.Obs->merge_flag == MergeType::Thresh)) { + mlog << Warning << "\nModeFrontEnd::_process_superobjects() -> " + << "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_multivar_fcst_obs_data_super(fcsts._super._simple_sd, obs._super._simple_sd, + *(mvdf->_grid)); + + // run the mode algorithm + _superobject_mode_algorithm(fcsts._rIndex, fcsts._tIndex, obs._rIndex, obs._tIndex, + fcsts._super, obs._super); + + delete mode_exec; mode_exec = nullptr; +} //////////////////////////////////////////////////////////////////////// -void MultivarFrontEnd::_simple_mode_algorithm(ModeExecutive::Processing_t p) +void +MultivarFrontEnd::_superobject_mode_algorithm(int rIndexF, int tIndexF, + int rIndexO, int tIndexO, + const ModeSuperObject &fsuper, + const ModeSuperObject &osuper) + { - _mode_algorithm_init(); mode_exec->clear_internal_r_index(); - mode_exec->do_conv_thresh_multivar_simple(p); + mode_exec->do_conv_thresh_multivar_super(rIndexF, tIndexF, rIndexO, tIndexO); + mode_exec->do_match_merge_multivar(fsuper._merge_sd_split, osuper._merge_sd_split, + ModeExecutive::MULTIVAR_SUPER); + mode_exec->process_output_multivar_super(); mode_exec->clear_internal_r_index(); - #ifdef WITH_PYTHON GP.finalize(); #endif @@ -724,36 +734,20 @@ void MultivarFrontEnd::_simple_mode_algorithm(ModeExecutive::Processing_t p) //////////////////////////////////////////////////////////////////////// -void MultivarFrontEnd::_mode_algorithm_init() const +void MultivarFrontEnd::_init_exec(ModeExecutive::Processing_t p, + const string &ffile, + const string &ofile) const { - const ModeConfInfo & conf = mode_exec->engine.conf_info; - if ( conf.quilt ) { - mlog << Error << "\nMultiVarFontend::mode_algorithm() -> " - << "quilting not yet implemented for multivar mode \n\n"; - exit ( 1 ); - } - - int NCT = conf.n_conv_threshs(); - int NCR = conf.n_conv_radii(); + mlog << Debug(4) << "Running multivar front end for " << ModeExecutive::stype(p) << "\n"; - if ( NCT != NCR ) { - - mlog << Error << "\nMultivarFrontEnd::_mode_algorithm_init() ->" - << "all convolution radius and threshold arrays must have the same number of elements\n\n"; - - exit ( 1 ); + if ( mode_exec ) { delete mode_exec; mode_exec = nullptr; } - } - - if (NCT > 1) { - - mlog << Error << "\nMultivarFrontEnd::_mode_algorithm_init() ->" - << ": multiple convolution radii and thresholds not implemented in multivar mode\n\n"; + mode_exec = new ModeExecutive(); + mode_exec->fcst_file = ffile; + mode_exec->obs_file = ofile; - exit ( 1 ); - } + mode_exec->match_config_file = config_file; // this is never used + mode_exec->out_dir = output_path; } - - diff --git a/src/tools/core/mode/multivar_frontend.h b/src/tools/core/mode/multivar_frontend.h index f4c78c243d..80cd475660 100644 --- a/src/tools/core/mode/multivar_frontend.h +++ b/src/tools/core/mode/multivar_frontend.h @@ -20,6 +20,7 @@ #include "two_d_array.h" #include "bool_calc.h" #include "multivar_data.h" +#include "simple_objects.hh" #include "mode_superobject.h" #include "mode_input_data.h" #include "mode_exec.h" @@ -31,27 +32,49 @@ class MultivarFrontEnd { int n_fcst_files, n_obs_files; StringArray fcst_filenames; StringArray obs_filenames; - BoolCalc f_calc, o_calc ; - std::vector fcstInput, obsInput; - std::vector mvdFcst, mvdObs; + BoolCalc f_calc; + BoolCalc o_calc; + std::vector fcstInput; + std::vector obsInput; + std::vector mvdFcst; + std::vector mvdObs; std::string fcst_fof; std::string obs_fof; + void _init(const StringArray & Argv); void _process_command_line(const StringArray &); void _read_config(const std::string & filename); void _setup_inputs(); void _set_output_path(); - int _mkdir(const char *dir); - void _simple_objects(ModeExecutive::Processing_t p, ModeDataType dtype, - int j, int n_files, const std::string &filename, - const ModeInputData &input); - void _init_exec(ModeExecutive::Processing_t p, const std::string &ffile, const std::string &ofile); - void _superobject_mode_algorithm(const ModeSuperObject &fsuper, const ModeSuperObject &osuper); - void _intensity_compare_mode_algorithm(const MultiVarData &mvdf, const MultiVarData &mvdo, + int _mkdir(const char *dir) const; + void _read_input(const std::string &name, int index, ModeDataType type, + GrdFileType f_t, GrdFileType other_t, int shift); + void _create_verif_grid(void); + + void _create_simple_objects(ModeDataType dtype, const std::string &name, + int rIndex, int tIndex, int n_files, + const StringArray &filenames, const std::vector &input, + BoolCalc &calc, SimpleObjects &O) const; + MultiVarData *_create_simple_multivar_data(ModeDataType dtype, int rIndex, int tIndex, + int j, int n_files, const std::string &filename, + const ModeInputData &input) const; + void _simple_objects(ModeExecutive::Processing_t p, ModeDataType dtype, int rIndex, + int tIndex, int j, int n_files, const std::string &filename, + const ModeInputData &input) const; + void _simple_mode_algorithm(ModeExecutive::Processing_t p, int rIndex, int tIndex) const; + + void _create_intensity_comparisons(SimpleObjects &fcsts, int findex, SimpleObjects &obs, int oindex, + const string &fcst_filename, const string &obs_filename); + void _intensity_compare_mode_algorithm(int rIndexF, int tIndexF, int rIndexO, int tIndexO, + const MultiVarData &mvdf, const MultiVarData &mvdo, const ModeSuperObject &fsuper, const ModeSuperObject &osuper); - void _simple_mode_algorithm(ModeExecutive::Processing_t p); - void _mode_algorithm_init() const; + void _process_superobjects(SimpleObjects &fcsts, SimpleObjects &obs); + void _superobject_mode_algorithm(int rIndexF, int tIndexF, int rIndexO, int tIndexO, + const ModeSuperObject &fsuper, const ModeSuperObject &osuper); + + void _init_exec(ModeExecutive::Processing_t p, const std::string &ffile, const std::string &ofile) const; + public: bool do_clusters; @@ -66,37 +89,13 @@ class MultivarFrontEnd { ~MultivarFrontEnd(); - int run(const StringArray & Argv); - void init(const StringArray & Argv); static void set_outdir (const StringArray &); static void set_logfile (const StringArray &); static void set_verbosity (const StringArray &); static void set_compress (const StringArray &); - void read_input(const std::string &name, int index, ModeDataType type, - GrdFileType f_t, GrdFileType other_t, int shift); - - - void create_verif_grid(void); - - MultiVarData *create_simple_objects(ModeDataType dtype, int j, int n_files, - const std::string &filename, - const ModeInputData &input); - - void create_intensity_comparisons(int findex, int oindex, - const ModeSuperObject &fsuper, - const ModeSuperObject &osuper, - MultiVarData &mvdf, MultiVarData &mvdo, - const std::string &fcst_filename, - const std::string &obs_filename); - - void process_superobjects(ModeSuperObject &fsuper, - ModeSuperObject &osuper, - const MultiVarData &mvdf, - const MultiVarData &mvdo); - }; diff --git a/src/tools/core/mode/simple_objects.cc b/src/tools/core/mode/simple_objects.cc new file mode 100644 index 0000000000..a7ebd1ef76 --- /dev/null +++ b/src/tools/core/mode/simple_objects.cc @@ -0,0 +1,58 @@ +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +// ** Copyright UCAR (c) 1992 - 2024 +// ** 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 +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* + + +//////////////////////////////////////////////////////////////////////// + +#include "simple_objects.hh" + +using namespace std; + +//////////////////////////////////////////////////////////////////////// + +SimpleObjects::SimpleObjects() : + _dataType(ModeDataType::MvMode_Both), + _rIndex(-1), + _tIndex(-1) +{ +} + +//////////////////////////////////////////////////////////////////////// + +SimpleObjects::~SimpleObjects() +{ +} + +//////////////////////////////////////////////////////////////////////// + +void SimpleObjects::init(ModeDataType dataType, int rIndex, int tIndex) +{ + _dataType = dataType; + _rIndex = rIndex; + _tIndex = tIndex; +} + +//////////////////////////////////////////////////////////////////////// + +void SimpleObjects::setSuper(bool isFcst, int n_fcst_files, bool do_clusters, + BoolCalc &f_calc) +{ + _super = ModeSuperObject(isFcst, n_fcst_files, do_clusters, + _rIndex, _tIndex, _mvd, f_calc); +} + +//////////////////////////////////////////////////////////////////////// + +void SimpleObjects::clear(void) +{ + for (auto &x : _mvd) { + delete x; + x = nullptr; + } + _mvd.clear(); +} diff --git a/src/tools/core/mode/simple_objects.hh b/src/tools/core/mode/simple_objects.hh new file mode 100644 index 0000000000..7215a05336 --- /dev/null +++ b/src/tools/core/mode/simple_objects.hh @@ -0,0 +1,46 @@ +// ** Copyright UCAR (c) 1992 - 2024 +// ** 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 __SIMPLE_OBJECTS_H__ +#define __SIMPLE_OBJECTS_H__ + + +//////////////////////////////////////////////////////////////////////// + + +#include +#include +#include "multivar_data.h" +#include "mode_superobject.h" +#include "bool_calc.h" + +class SimpleObjects { + + public: + + SimpleObjects(); + ~SimpleObjects(); + + void init(ModeDataType dataType, int rIndex, int tIndex); + void setSuper(bool isFcst, int n_fcst_files, bool do_clusters, BoolCalc &f_calc); + void clear(void); + + ModeDataType _dataType; /**< observations or forecasts */ + int _rIndex; /**< Convolution radius index */ + int _tIndex; /**< Convolution threshold index */ + std::vector _mvd; /**< The data from each input */ + ModeSuperObject _super; /**< The superobject created from the data */ +}; + +#endif /* __MODE_FRONT_END_H__ */ + + +/////////////////////////////////////////////////////////////////////////