diff --git a/README.md b/README.md index 1c504e4d69..ee97ac3082 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ -# MET +Model Evaluation Tools (MET) Repository +======================================= + + +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5565322.svg)](https://doi.org/10.5281/zenodo.5565322) This repository contains the source code for the Model Evaluation Tools package (met), unit test code (test), and scripts used to build and test the code (scripts). diff --git a/met/data/config/STATAnalysisConfig_GO_Index b/met/data/config/STATAnalysisConfig_GO_Index index 2277304894..e157e1f6de 100644 --- a/met/data/config/STATAnalysisConfig_GO_Index +++ b/met/data/config/STATAnalysisConfig_GO_Index @@ -76,7 +76,7 @@ fcst_lev = [ "P250", "P250", "P250", "P250", "P400", "P400", "P400", "P400", "Z2", "Z2", "Z2", "Z2", "P400", "P400", "P400", "P400", - "Z0", "Z0", "Z0", "Z0" + "L0", "L0", "L0", "L0" ]; obs_lev = []; diff --git a/met/docs/Users_Guide/release-notes.rst b/met/docs/Users_Guide/release-notes.rst index fc43b53c72..af9fb5168b 100644 --- a/met/docs/Users_Guide/release-notes.rst +++ b/met/docs/Users_Guide/release-notes.rst @@ -5,9 +5,40 @@ When applicable, release notes are followed by the GitHub issue number which describes the bugfix, enhancement, or new feature: `MET GitHub issues. `_ -MET Version 10.1.0-beta2 release notes (|release_date|) +MET Version 10.1.0-beta3 release notes (|release_date|) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* New tools: + + * **Create new Gen-Ens-Prod tool for ensemble product generation** (`#1904 `_). + +* Enhancements: + + * **Enhance MET to use point observations falling between the first and last columns of a global grid** (`#1823 `_). + * **Enhance the PBL derivation logic in PB2NC** (`#1913 `_). + * **Add obs_quality_exc configuration option to specify which quality flags should be excluded** (`#1858 `_). + +* Bugfixes: + + * Fix PB2NC to better inventory BUFR input data when processing all variables (`#1894 `_). + * Fix IODA2NC bug rejecting all input observations in unit tests (`#1922 `_). + * Fix Stat-Analysis skill score index job which always writes a dump row output file (`#1914 `_). + * Fix TC-Stat event equalization logic to include any model name requested using -amodel (`#1932 `_). + +* Logging: + + * Resolve PB2NC string truncation warning messages (`#1909 `_). + * Print warning message for fields that contain no valid data (`#1912 `_). + * Review and revise the warning messages when running the MET unit tests (`#1921 `_). + +* Repository and installation: + + * Enhance compilation script and its documentation (`#1395 `_). + * Reduce the Security hotspots from SonarQube (`#1903 `_). + +MET Version 10.1.0-beta2 release notes (20210901) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * New output: * **Enhance MET to compute the CBS Index** (`#1031 `_). @@ -43,7 +74,7 @@ MET Version 10.1.0-beta2 release notes (|release_date|) * Update FAQ in User's Guide with info from webpage FAQ (`#1834 `_). MET Version 10.1.0-beta1 release notes (20210613) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Add the HSS_EC statistic to the MCTS line type and a configurable option for its computation (`#1749 `_). * Implement a common API for reading and writing the common NetCDF point observation file format (`#1402 `_ and `#1581 `_). diff --git a/met/docs/conf.py b/met/docs/conf.py index 2b646244a6..7a625f0c9e 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -20,11 +20,11 @@ project = 'MET' author = 'UCAR/NCAR, NOAA, CSU/CIRA, and CU/CIRES' author_list = 'Halley Gotway, J., K. Newman, H. Soh, J. Opatz, T. Jensen, J. Prestopnik, L. Goodrich, D. Fillmore, B. Brown, R. Bullock, T. Fowler' -version = '10.1.0-beta2' +version = '10.1.0-beta3' verinfo = version release = f'{version}' release_year = '2021' -release_date = f'{release_year}-07-20' +release_date = f'{release_year}-10-06' copyright = f'{release_year}, {author}' # -- General configuration --------------------------------------------------- diff --git a/met/src/basic/vx_util/num_array.cc b/met/src/basic/vx_util/num_array.cc index a792109883..18fc2ffbae 100644 --- a/met/src/basic/vx_util/num_array.cc +++ b/met/src/basic/vx_util/num_array.cc @@ -31,9 +31,9 @@ using namespace std; //////////////////////////////////////////////////////////////////////// - // - // Code for class NumArray - // +// +// Code for class NumArray +// //////////////////////////////////////////////////////////////////////// @@ -43,7 +43,7 @@ NumArray::NumArray() { -init_from_scratch(); + init_from_scratch(); } @@ -55,7 +55,7 @@ NumArray::~NumArray() { -clear(); + clear(); } @@ -67,9 +67,9 @@ NumArray::NumArray(const NumArray & a) { -init_from_scratch(); + init_from_scratch(); -assign(a); + assign(a); } @@ -81,11 +81,11 @@ NumArray & NumArray::operator=(const NumArray & a) { -if ( this == &a ) return ( * this ); + if ( this == &a ) return ( * this ); -assign(a); + assign(a); -return ( * this ); + return ( * this ); } @@ -97,11 +97,9 @@ void NumArray::init_from_scratch() { -e = (double *) 0; - -clear(); - -return; + clear(); + + return; } @@ -113,13 +111,11 @@ void NumArray::clear() { -if ( e ) { delete [] e; e = (double *) 0; } + e.clear(); -Nelements = Nalloc = 0; - -Sorted = false; + Sorted = false; -return; + return; } @@ -131,11 +127,11 @@ void NumArray::erase() { -Nelements = 0; - -Sorted = false; + int n = e.size(); + e.clear(); + e.reserve(n); -return; + return; } @@ -147,26 +143,13 @@ void NumArray::assign(const NumArray & a) { -clear(); - -if ( a.Nelements == 0 ) return; - -extend(a.Nelements); - -int j; - -for (j=0; j<(a.Nelements); ++j) { - - e[j] = a.e[j]; - -} - -Nelements = a.Nelements; - -Sorted = a.Sorted; + clear(); + e = a.e; + + Sorted = a.Sorted; -return; + return; } @@ -174,59 +157,13 @@ return; //////////////////////////////////////////////////////////////////////// -void NumArray::extend(int len, bool exact) +void NumArray::extend(int len) { -if ( Nalloc >= len ) return; - -if ( ! exact ) { + e.reserve(len); - int k; - - k = len/num_array_alloc_inc; - - if ( len%num_array_alloc_inc ) ++k; - - len = k*num_array_alloc_inc; - -} - -double * u = (double *) 0; - -u = new double [len]; - -if ( !u ) { - - mlog << Error << "\nvoid NumArray::extend(int, bool) -> " - << "memory allocation error\n\n"; - - exit ( 1 ); - -} - -int j; - -memset(u, 0, len*sizeof(double)); - -if ( e ) { - - for (j=0; j= Nelements) ) { + if ( (i < 0) || (i >= n_elements()) ) { - mlog << Error << "\nNumArray::operator[](int) const -> " - << "range check error ... Nelements = " << Nelements - << ", i = " << i << "\n\n"; + mlog << Error << "\nNumArray::operator[](int) const -> " + << "range check error ... Length = " << n_elements() + << ", i = " << i << "\n\n"; - exit ( 1 ); + exit ( 1 ); -} + } -return ( e[i] ); + return ( e[i] ); } @@ -293,7 +229,7 @@ int NumArray::has(int k, bool forward) const { -return(has((double) k, forward)); + return(has((double) k, forward)); } @@ -305,27 +241,27 @@ int NumArray::has(double d, bool forward) const { -int j; -int found = 0; + int j; + int found = 0; -if (forward) { - for (j=0; j=0; --j) { - if ( is_eq(e[j], d) ) { - found = 1; - break; + else { + for (j=n_elements()-1; j>=0; --j) { + if ( is_eq(e[j], d) ) { + found = 1; + break; + } } } -} - -return ( found ); + + return ( found ); } @@ -337,11 +273,11 @@ void NumArray::add(int k) { -add((double) k); + add((double) k); -Sorted = false; + Sorted = false; -return; + return; } @@ -353,13 +289,11 @@ void NumArray::add(double d) { -extend(Nelements + 1, false); - -e[Nelements++] = d; + e.push_back(d); -Sorted = false; + Sorted = false; -return; + return; } @@ -371,19 +305,19 @@ void NumArray::add(const NumArray & a) { -extend(Nelements + a.Nelements); - -int j; + extend(n_elements() + a.n_elements()); + + int j; -for (j=0; j<(a.Nelements); ++j) { + for (j=0; j<(a.n_elements()); ++j) { - e[Nelements++] = a.e[j]; + e.push_back(a.e[j]); -} + } -Sorted = false; + Sorted = false; -return; + return; } @@ -395,19 +329,19 @@ void NumArray::add_const(double v, int n) { -extend(Nelements + n); - -int j; + extend(n_elements() + n); + + int j; -for (j=0; j= Nelements) ) { + if ( (i < 0) || (i >= n_elements()) ) { + + mlog << Error << "\nNumArray::set(int, double) -> " + << "range check error\n\n"; + + exit ( 1 ); - mlog << Error << "\nNumArray::set(int, double) -> " - << "range check error\n\n"; + } + + e[i] = d; + + Sorted = false; - exit ( 1 ); + return; } -e[i] = d; -Sorted = false; +//////////////////////////////////////////////////////////////////////// + + +void NumArray::set_const(double v, int n) + +{ + +erase(); + +add_const(v, n); + + // + // a constant array is sorted + // + +Sorted = true; return; @@ -596,11 +552,15 @@ void NumArray::sort_array() { -if(!Sorted) sort(e, Nelements); + if ( !Sorted ) { -Sorted = true; + sort(e.begin(), e.end()); -return; + } + + Sorted = true; + + return; } @@ -613,7 +573,7 @@ void NumArray::reorder(const NumArray &i_na) { int i, j; // Check that the index array is of the correct length - if(i_na.n_elements() != Nelements) { + if(i_na.n_elements() != n_elements()) { mlog << Error << "\nNumArray::reorder(const NumArray &) -> " << "the index and sorting arrays must have the same length\n\n"; exit(1); @@ -641,6 +601,8 @@ void NumArray::reorder(const NumArray &i_na) { return; } +// SETH, please review the logic of the functions below. +// Do they still work OK after switching to STL::vector? //////////////////////////////////////////////////////////////////////// // @@ -654,63 +616,63 @@ int NumArray::rank_array(int &ties) { -int n_vld, i; + int n_vld, i; -double *data = (double *) 0; -int *data_loc = (int *) 0; -double *data_rank = (double *) 0; + double *data = (double *) 0; + int *data_loc = (int *) 0; + double *data_rank = (double *) 0; -// -// Arrays to store the raw data values to be ranked, their locations, -// and their computed ranks. The ranks are stored as doubles since -// they can be set to 0.5 in the case of ties. -// -data = new double [Nelements]; -data_loc = new int [Nelements]; -data_rank = new double [Nelements]; - -if ( !data || !data_loc || !data_rank ) { + // + // Arrays to store the raw data values to be ranked, their locations, + // and their computed ranks. The ranks are stored as doubles since + // they can be set to 0.5 in the case of ties. + // + data = new double [n_elements()]; + data_loc = new int [n_elements()]; + data_rank = new double [n_elements()]; + + if ( !data || !data_loc || !data_rank ) { - mlog << Error << "\nint NumArray::rank_array() -> " - << "memory allocation error\n\n"; + mlog << Error << "\nint NumArray::rank_array() -> " + << "memory allocation error\n\n"; - exit ( 1 ); + exit ( 1 ); -} + } -// -// Search the data array for valid data and keep track of its location -// -for(i=0, n_vld=0; i 1) { + if(count > 1) { - // Check for slightly negative precision error - var = (s_sq - s*s/(double) count)/((double) (count - 1)); - if(is_eq(var, 0.0)) var = 0; + // Check for slightly negative precision error + var = (s_sq - s*s/(double) count)/((double) (count - 1)); + if(is_eq(var, 0.0)) var = 0; -} -else { - var = bad_data_double; -} + } + else { + var = bad_data_double; + } -return; + return; } @@ -836,13 +798,13 @@ void NumArray::compute_mean_stdev(double &mn, double &stdev) const { -double var; + double var; -compute_mean_variance(mn, var); + compute_mean_variance(mn, var); -stdev = (is_bad_data(var) ? bad_data_double : square_root(var)); + stdev = (is_bad_data(var) ? bad_data_double : square_root(var)); -return; + return; } @@ -854,18 +816,18 @@ double NumArray::sum() const { -int j, count; -double s; + int j, count; + double s; -for(j=0, count=0, s=0.0; j max_n) || - (is_eq(uniq_n[j], max_n) && max_j >= 0 && uniq_v[j] < uniq_v[max_j])) { - max_n = nint(uniq_n[j]); - max_j = j; + if((uniq_n[j] > max_n) || + (is_eq(uniq_n[j], max_n) && max_j >= 0 && uniq_v[j] < uniq_v[max_j])) { + max_n = nint(uniq_n[j]); + max_j = j; + } } -} -if(max_j >= 0) v = uniq_v[max_j]; -else v = bad_data_double; + if(max_j >= 0) v = uniq_v[max_j]; + else v = bad_data_double; -return(v); + return(v); } @@ -926,18 +888,18 @@ double NumArray::min() const { -if(Nelements == 0) return(bad_data_double); + if(n_elements() == 0) return(bad_data_double); -int j; + int j; -double min_v = e[0]; + double min_v = e[0]; -for(j=0; j max_v) max_v = e[j]; -} + for(j=0; j max_v) max_v = e[j]; + } -return(max_v); + return(max_v); } @@ -972,13 +934,13 @@ double NumArray::range() const { -double v, v1, v2; + double v, v1, v2; -v1 = max(); -v2 = min(); -v = (is_bad_data(v1) || is_bad_data(v2) ? bad_data_double : v1 - v2); + v1 = max(); + v2 = min(); + v = (is_bad_data(v1) || is_bad_data(v2) ? bad_data_double : v1 - v2); -return(v); + return(v); } @@ -990,13 +952,13 @@ int NumArray::n_valid() const { -int j, n_vld; + int j, n_vld; -for(j=0, n_vld=0; j= Nelements || - end < 0 || end >= Nelements || - end < beg ) { - mlog << Error << "\nNumArray::subset(int, int) -> " - << "range check error\n\n"; - exit ( 1 ); -} - -// Store subset -for(int i=beg; i<=end; i++) subset_na.add(e[i]); + // Check bounds + if ( beg < 0 || beg >= n_elements() || + end < 0 || end >= n_elements() || + end < beg ) { + mlog << Error << "\nNumArray::subset(int, int) -> " + << "range check error\n\n"; + exit ( 1 ); + } + + // Store subset + for(int i=beg; i<=end; i++) subset_na.add(e[i]); -return ( subset_na ); + return ( subset_na ); } @@ -1056,21 +1018,21 @@ NumArray NumArray::subset(const NumArray &keep) const { -NumArray subset_na; - -// Check bounds -if ( keep.n_elements() != Nelements ) { - mlog << Error << "\nNumArray::subset(const NumArray &) -> " - << "the number of elements do not match\n\n"; - exit ( 1 ); -} + NumArray subset_na; -// Store subset -for(int i=0; i<=Nelements; i++) { - if(keep[i]) subset_na.add(e[i]); -} + // Check bounds + if ( keep.n_elements() != n_elements() ) { + mlog << Error << "\nNumArray::subset(const NumArray &) -> " + << "the number of elements do not match\n\n"; + exit ( 1 ); + } + + // Store subset + for(int i=0; i<=n_elements(); i++) { + if(keep[i]) subset_na.add(e[i]); + } -return ( subset_na ); + return ( subset_na ); } @@ -1082,19 +1044,19 @@ double NumArray::mean() const { -int j, count; -double s, mn; - -for(j=0, count=0, s=0.0; j " - << "the number of elements do not match\n\n"; - exit ( 1 ); -} + if ( wgt.n_elements() != n_elements() ) { + mlog << Error << "\nNumArray::wmean(const NumArray &) -> " + << "the number of elements do not match\n\n"; + exit ( 1 ); + } -int j, count; -double w, s, wmn; + int j, count; + double w, s, wmn; -for(j=0, count=0, w=0.0, s=0.0; j e; bool Sorted; @@ -59,15 +49,15 @@ class NumArray { void erase(); - void extend(int, bool exact = true); + void extend(int); void dump(ostream &, int depth = 0) const; double operator[](int) const; const double * vals() const; - double * buf() const; - + double * buf(); + int has(int, bool forward=true) const; int has(double, bool forward=true) const; @@ -127,12 +117,12 @@ class NumArray { //////////////////////////////////////////////////////////////////////// -inline int NumArray::n_elements() const { return ( Nelements ); } -inline int NumArray::n () const { return ( Nelements ); } -inline const double * NumArray::vals() const { return ( e ); } -inline double * NumArray::buf() const { return ( e ); } -inline void NumArray::inc(int i, int v) { e[i] += v; return; } -inline void NumArray::inc(int i, double v) { e[i] += v; return; } +inline int NumArray::n_elements() const { return ( e.size() ); } +inline int NumArray::n () const { return ( e.size() ); } +inline const double * NumArray::vals() const { return ( e.data() ); } +inline double * NumArray::buf() { return ( e.data() ); } +inline void NumArray::inc(int i, int v) { e[i] += v; return; } +inline void NumArray::inc(int i, double v) { e[i] += v; return; } //////////////////////////////////////////////////////////////////////// diff --git a/met/src/libcode/vx_statistics/pair_base.cc b/met/src/libcode/vx_statistics/pair_base.cc index aaf73755b9..45bf5696a5 100644 --- a/met/src/libcode/vx_statistics/pair_base.cc +++ b/met/src/libcode/vx_statistics/pair_base.cc @@ -157,23 +157,23 @@ void PairBase::erase() { //////////////////////////////////////////////////////////////////////// -void PairBase::extend(int n, bool exact) { +void PairBase::extend(int n) { - o_na.extend (n, exact); - x_na.extend (n, exact); - y_na.extend (n, exact); - wgt_na.extend(n, exact); + o_na.extend (n); + x_na.extend (n); + y_na.extend (n); + wgt_na.extend(n); - cmn_na.extend(n, exact); - csd_na.extend(n, exact); - cdf_na.extend(n, exact); + cmn_na.extend(n); + csd_na.extend(n); + cdf_na.extend(n); if(IsPointVx) { - lat_na.extend(n, exact); - lon_na.extend(n, exact); - vld_ta.extend(n, exact); - lvl_na.extend(n, exact); - elv_na.extend(n, exact); + lat_na.extend(n); + lon_na.extend(n); + vld_ta.extend(n); + lvl_na.extend(n); + elv_na.extend(n); } return; diff --git a/met/src/libcode/vx_statistics/pair_base.h b/met/src/libcode/vx_statistics/pair_base.h index 465432f16f..cb428d29da 100644 --- a/met/src/libcode/vx_statistics/pair_base.h +++ b/met/src/libcode/vx_statistics/pair_base.h @@ -119,7 +119,7 @@ class PairBase { void clear(); void erase(); - void extend(int, bool exact = true); // Allocate memory for expected size + void extend(int); // Allocate memory for expected size bool is_point_vx() const; diff --git a/met/src/libcode/vx_statistics/pair_data_ensemble.cc b/met/src/libcode/vx_statistics/pair_data_ensemble.cc index 683aa499b9..5782cf6a0d 100644 --- a/met/src/libcode/vx_statistics/pair_data_ensemble.cc +++ b/met/src/libcode/vx_statistics/pair_data_ensemble.cc @@ -143,35 +143,35 @@ void PairDataEnsemble::clear() { //////////////////////////////////////////////////////////////////////// -void PairDataEnsemble::extend(int n, bool exact) { +void PairDataEnsemble::extend(int n) { int i; // Allocate memory for the number of observations. // Only applies to arrays sized by n_obs which does not include: // rhist_na, relp_na, phist_na - PairBase::extend(n, exact); - - obs_error_entry.extend(n, exact); - - for(i=0; i0.0 ]; } ];