From 03dbbc9815b109856f1a52214e8a3a2676e22f50 Mon Sep 17 00:00:00 2001 From: jprestop Date: Mon, 14 Jun 2021 12:24:08 -0600 Subject: [PATCH 001/200] Update install_met_env.kiowa Commented out items and added text to description --- .../installation/config/install_met_env.kiowa | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/installation/config/install_met_env.kiowa b/scripts/installation/config/install_met_env.kiowa index e063cea272..0e1eac135c 100644 --- a/scripts/installation/config/install_met_env.kiowa +++ b/scripts/installation/config/install_met_env.kiowa @@ -11,13 +11,13 @@ export SET_D64BIT=FALSE export CFLAGS="-Wall -g" export CXXFLAGS="-Wall -g" -#If you've already compiled these and don't need to compile them again, set the following +# If you've already compiled these and don't need to compile them again, set the following; +# Otherwise, if you do need to install these libraries, comment out the variables below export EXTERNAL_LIBS=/d1/personal/jpresto/MET/MET_testing/mod_script/external_libs -export MET_GRIB2CLIB=${EXTERNAL_LIBS}/lib -export MET_GRIB2CINC=${EXTERNAL_LIBS}/include -export GRIB2CLIB_NAME=-lgrib2c -export MET_BUFRLIB=${EXTERNAL_LIBS}/lib -export BUFRLIB_NAME=-lbufr -export MET_NETCDF=${EXTERNAL_LIBS}/lib -# Also, don't forget to set the following options to zero within the compile script if you've already compiled those libraries as well: COMPILE_GSL, COMPILE_HDF, COMPILE_HDFEOS, COMPILE_CAIRO, COMPILE_FREETYPE - \ No newline at end of file +#export MET_GRIB2CLIB=${EXTERNAL_LIBS}/lib +#export MET_GRIB2CINC=${EXTERNAL_LIBS}/include +#export GRIB2CLIB_NAME=-lgrib2c +#export MET_BUFRLIB=${EXTERNAL_LIBS}/lib +#export BUFRLIB_NAME=-lbufr +#export MET_NETCDF=${EXTERNAL_LIBS}/lib + From 9573488793170908cb59a275761b5b079cbaeffb Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 16 Jun 2021 23:47:49 -0600 Subject: [PATCH 002/200] #1817 Added to_north argument at two_to_one() --- met/src/basic/vx_util/data_plane.cc | 4 ++-- met/src/basic/vx_util/data_plane.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/met/src/basic/vx_util/data_plane.cc b/met/src/basic/vx_util/data_plane.cc index 043e1d7c7b..c855b2a1d5 100644 --- a/met/src/basic/vx_util/data_plane.cc +++ b/met/src/basic/vx_util/data_plane.cc @@ -410,7 +410,7 @@ return; /////////////////////////////////////////////////////////////////////////////// -int DataPlane::two_to_one(int x, int y) const { +int DataPlane::two_to_one(int x, int y, bool to_north) const { int n; if((x < 0) || (x >= Nx) || (y < 0) || (y >= Ny)) { @@ -420,7 +420,7 @@ int DataPlane::two_to_one(int x, int y) const { exit(1); } - n = y*Nx + x; // don't change this! lots of downstream code depends on this! + n = (to_north ? y : (Ny-1-y))*Nx + x; // don't change this! lots of downstream code depends on this! return(n); } diff --git a/met/src/basic/vx_util/data_plane.h b/met/src/basic/vx_util/data_plane.h index 54e3606b55..650d62b226 100644 --- a/met/src/basic/vx_util/data_plane.h +++ b/met/src/basic/vx_util/data_plane.h @@ -109,7 +109,7 @@ class DataPlane { void replace_bad_data(const double value); - int two_to_one(int x, int y) const; + int two_to_one(int x, int y, bool to_north=true) const; void one_to_two(int n, int &x, int &y) const; bool s_is_on(int x, int y) const; From fad14e05cb58b0cc6837a38c5a40cf74b870e45e Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 16 Jun 2021 23:50:08 -0600 Subject: [PATCH 003/200] #1817 Calls two_to_one() with false for the third argument, to_north, if latitude moves north to south --- met/src/tools/other/point2grid/point2grid.cc | 63 +++++++++++++------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/met/src/tools/other/point2grid/point2grid.cc b/met/src/tools/other/point2grid/point2grid.cc index 6402fff121..8f718b0e2a 100644 --- a/met/src/tools/other/point2grid/point2grid.cc +++ b/met/src/tools/other/point2grid/point2grid.cc @@ -328,7 +328,6 @@ void process_command_line(int argc, char **argv) { //////////////////////////////////////////////////////////////////////// void process_data_file() { - DataPlane fr_dp; Grid fr_grid, to_grid; GrdFileType ftype; ConcatString run_cs; @@ -1282,10 +1281,11 @@ void regrid_nc_variable(NcFile *nc_in, Met2dDataFile *fr_mtddf, exit(1); } else { + bool is_to_north = !fr_grid.get_swap_to_north(); float *from_data = new float[from_data_size]; for (int xIdx=0; xIdx data_value) from_min_value = data_value; if (from_max_value < data_value) from_max_value = data_value; } - - valid_cnt++; } - + if (0 < dataArray.n()) { - int data_cnt = dataArray.n(); float to_value; - if (RGInfo.method == InterpMthd_Min) to_value = dataArray.min(); + int data_cnt = dataArray.n(); + if (1 == data_cnt) to_value = dataArray[0]; + else if (RGInfo.method == InterpMthd_Min) to_value = dataArray.min(); else if (RGInfo.method == InterpMthd_Max) to_value = dataArray.max(); else if (RGInfo.method == InterpMthd_Median) { dataArray.sort_array(); @@ -1349,12 +1347,23 @@ void regrid_nc_variable(NcFile *nc_in, Met2dDataFile *fr_mtddf, to_dp.set(to_value, xIdx, yIdx); to_cell_cnt++; - mlog << Debug(9) << method_name - << "max: " << dataArray.max() - << ", min: " << dataArray.min() - << ", mean: " << dataArray.sum()/data_cnt - << " from " << valid_cnt << " out of " - << data_cnt << " data values.\n"; + if(mlog.verbosity_level() >= 9) { + double to_lat, to_lon; + to_grid.xy_to_latlon(xIdx,yIdx, to_lat, to_lon); + to_lon *= -1; + if (1 == data_cnt) + mlog << Debug(9) << method_name + << "value: " << to_value << " to (" << to_lon << ", " << to_lat + << ") from offset " << from_index << ".\n"; + else + mlog << Debug(9) << method_name + << "value: " << to_value + << ", max: " << dataArray.max() + << ", min: " << dataArray.min() + << ", mean: " << dataArray.sum()/data_cnt + << " from " << data_cnt << " (out of " << cellArray.n() + << ") data values to (" << to_lon << ", " << to_lat << ").\n"; + } } } else { @@ -1685,7 +1694,7 @@ void check_lat_lon(int data_size, float *latitudes, float *longitudes) { for (int idx=0; idx MISSING_LATLON && longitudes[idx] > MISSING_LATLON) { - mlog << Debug(7) << method_name << "index: " << idx << " lat: " + mlog << Debug(11) << method_name << "index: " << idx << " lat: " << latitudes[idx] << ", lon: " << longitudes[idx] << "\n"; cnt_printed++; } @@ -1790,8 +1799,9 @@ static bool get_grid_mapping(Grid to_grid, IntArray *cellMapping, static void get_grid_mapping_latlon( DataPlane from_dp, DataPlane to_dp, Grid to_grid, IntArray *cellMapping, float *latitudes, float *longitudes, - int from_lat_count, int from_lon_count, bool *skip_times) { + int from_lat_count, int from_lon_count, bool *skip_times, bool to_north) { double x, y; + double to_ll_lat, to_ll_lon; float lat, lon; int idx_x, idx_y, to_offset; int count_in_grid = 0; @@ -1807,11 +1817,14 @@ static void get_grid_mapping_latlon( for (int xIdx=0; xIdx= 15) { + double to_lat, to_lon; + to_grid.xy_to_latlon(idx_x, idx_y, to_lat, to_lon); + mlog << Debug(15) << method_name << " [" << xIdx << "," << yIdx << "] to " << coord_offset + << " (" << lon << ", " << lat << ") to (" << (to_lon*-1) << ", " << to_lat << ")\n"; + } } } } @@ -1918,7 +1937,8 @@ static bool get_grid_mapping(Grid fr_grid, Grid to_grid, IntArray *cellMapping, if( status ) { get_grid_mapping_latlon(from_dp, to_dp, to_grid, cellMapping, latitudes, longitudes, from_lat_count, - from_lon_count, skip_times); + from_lon_count, skip_times, + !fr_grid.get_swap_to_north()); } if( latitudes ) delete [] latitudes; if( longitudes ) delete [] longitudes; @@ -2129,7 +2149,8 @@ void get_grid_mapping(Grid fr_grid, Grid to_grid, IntArray *cellMapping, else { check_lat_lon(data_size, latitudes, longitudes); get_grid_mapping_latlon(from_dp, to_dp, to_grid, cellMapping, latitudes, - longitudes, from_lat_count, from_lon_count, 0); + longitudes, from_lat_count, from_lon_count, 0, + !fr_grid.get_swap_to_north()); } if (latitudes_buf) delete [] latitudes_buf; From ae2c0a292e3a14212befa04a7b66e26a4e074ecf Mon Sep 17 00:00:00 2001 From: jprestop Date: Thu, 17 Jun 2021 15:13:09 -0600 Subject: [PATCH 004/200] Feature 1819 automation doc warnings (#1836) --- .github/jobs/build_documentation.sh | 25 +++++++++++++++++++ .../workflows/{main.yml => documentation.yml} | 22 +++++----------- 2 files changed, 31 insertions(+), 16 deletions(-) create mode 100755 .github/jobs/build_documentation.sh rename .github/workflows/{main.yml => documentation.yml} (59%) diff --git a/.github/jobs/build_documentation.sh b/.github/jobs/build_documentation.sh new file mode 100755 index 0000000000..c6b73500a2 --- /dev/null +++ b/.github/jobs/build_documentation.sh @@ -0,0 +1,25 @@ +#! /bin/bash + +# path to docs directory relative to top level of repository +# $GITHUB_WORKSPACE is set if the actions/checkout@v2 action is run first + +DOCS_DIR=${GITHUB_WORKSPACE}/met/docs + +# run Make to build the documentation and return to previous directory +cd ${DOCS_DIR} +make clean html +cd - + +# copy HTML output into directory to create an artifact +mkdir -p artifact/documentation +cp -r ${DOCS_DIR}/_build/html/* artifact/documentation + +# check if the warnings.log file is empty +# Copy it into the artifact and documentation directories +# so it will be available in the artifacts +warning_file=${DOCS_DIR}/_build/warnings.log +if [ -s $warning_file ]; then + cp -r ${DOCS_DIR}/_build/warnings.log artifact/doc_warnings.log + cp artifact/doc_warnings.log artifact/documentation + exit 1 +fi diff --git a/.github/workflows/main.yml b/.github/workflows/documentation.yml similarity index 59% rename from .github/workflows/main.yml rename to .github/workflows/documentation.yml index d959c9e411..62c284aded 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/documentation.yml @@ -1,4 +1,4 @@ -name: MET CI/CD Workflow +name: Documentation on: push: branches: @@ -7,6 +7,8 @@ on: - feature_* - main_* - bugfix_* + paths: + - met/docs/** pull_request: types: [opened, reopened, synchronize] @@ -24,26 +26,14 @@ jobs: python -m pip install --upgrade python-dateutil requests sphinx \ sphinx-gallery Pillow sphinx_rtd_theme - name: Build docs - continue-on-error: true - run: | - DOCS_DIR=${GITHUB_WORKSPACE}/met/docs - cd ${DOCS_DIR} - make clean html - cd ${GITHUB_WORKSPACE} - warning_file=${DOCS_DIR}/_build/warnings.log - mkdir -p artifact/documentation - cp -r ${DOCS_DIR}/_build/html/* artifact/documentation - if [ -s $warning_file ]; then - cp -r ${DOCS_DIR}/_build/warnings.log artifact/doc_warnings.log - cp artifact/doc_warnings.log artifact/documentation - else - rm ${warning_file} - fi + run: ./.github/jobs/build_documentation.sh - uses: actions/upload-artifact@v2 + if: always() with: name: documentation path: artifact/documentation - uses: actions/upload-artifact@v2 + if: failure() with: name: documentation_warnings.log path: artifact/doc_warnings.log From 80a91f61c4cc775b1b8f13c9b14106e0fd53e8e9 Mon Sep 17 00:00:00 2001 From: jprestop Date: Tue, 22 Jun 2021 14:38:28 -0600 Subject: [PATCH 005/200] Removing "/lib" that should not be there. --- scripts/installation/config/install_met_env.kiowa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/installation/config/install_met_env.kiowa b/scripts/installation/config/install_met_env.kiowa index 0e1eac135c..7ff69f7ef8 100644 --- a/scripts/installation/config/install_met_env.kiowa +++ b/scripts/installation/config/install_met_env.kiowa @@ -19,5 +19,5 @@ export EXTERNAL_LIBS=/d1/personal/jpresto/MET/MET_testing/mod_script/external_li #export GRIB2CLIB_NAME=-lgrib2c #export MET_BUFRLIB=${EXTERNAL_LIBS}/lib #export BUFRLIB_NAME=-lbufr -#export MET_NETCDF=${EXTERNAL_LIBS}/lib +#export MET_NETCDF=${EXTERNAL_LIBS} From 1cb3cb141f0b9bbea76fe154e5608fe1a2d625d2 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 23 Jun 2021 09:09:59 -0600 Subject: [PATCH 006/200] #1508 checking stat() methoid returns no error before looking at FILE flag --- met/src/basic/vx_log/file_fxns.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/met/src/basic/vx_log/file_fxns.cc b/met/src/basic/vx_log/file_fxns.cc index 16a98ce261..49a5fec382 100644 --- a/met/src/basic/vx_log/file_fxns.cc +++ b/met/src/basic/vx_log/file_fxns.cc @@ -28,8 +28,7 @@ using namespace std; bool is_regular_file(const char *path) { struct stat path_stat; - stat(path, &path_stat); - return(S_ISREG(path_stat.st_mode)); + return(!stat(path, &path_stat) && S_ISREG(path_stat.st_mode)); } //////////////////////////////////////////////////////////////////////// From aeb600a487d6caee3e2bab3b5e610ab6c17f7531 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 13:03:30 -0600 Subject: [PATCH 007/200] Enable PDF creation --- .readthedocs.yaml | 2 +- met/docs/conf.py | 53 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index e148a2aad0..acae87d7f0 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -7,7 +7,7 @@ version: 2 # Build all formats (htmlzip, pdf, epub) #formats: all -formats: [] +formats: [pdf] # Optionally set the version of Python and requirements required to build your # docs diff --git a/met/docs/conf.py b/met/docs/conf.py index 61d78fba23..552f099f5b 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-beta1' +version = '10.1.0-beta2' verinfo = version release = f'{version}' release_year = '2021' -release_date = f'{release_year}-06-13' +release_date = f'{release_year}-06-25' copyright = f'{release_year}, {author}' # -- General configuration --------------------------------------------------- @@ -34,6 +34,55 @@ # ones. extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx'] +# settings for ReadTheDocs PDF creation +latex_engine = 'pdflatex' +latex_theme = 'manual' +latex_logo = os.path.join('_static','met_logo_2019_09.png') +latex_show_pagerefs = True +latex_master_doc = 'Users_Guide/index' + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + 'papersize': 'letterpaper', + 'releasename':"{version}", + 'fncychap': '\\usepackage{fncychap}', + 'fontpkg': '\\usepackage{amsmath,amsfonts,amssymb,amsthm}', + + 'figure_align':'htbp', + 'pointsize': '11pt', + + 'preamble': r''' + \usepackage{charter} + \usepackage[defaultsans]{lato} + \usepackage{inconsolata} + \setcounter{secnumdepth}{4} + \setcounter{tocdepth}{4} + ''', + + 'sphinxsetup': \ + 'hmargin={0.7in,0.7in}, vmargin={1in,1in}, \ + verbatimwithframe=true, \ + TitleColor={rgb}{0,0,0}, \ + HeaderFamily=\\rmfamily\\bfseries, \ + InnerLinkColor={rgb}{0,0,1}, \ + OuterLinkColor={rgb}{0,0,1}', + 'maketitle': '\\sphinxmaketitle', +# 'tableofcontents': ' ', + 'printindex': ' ' +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (latex_master_doc, + 'users_guide.tex', + 'MET User\'s Guide', + ' ', + 'manual') +] + # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] From 04d887bda7bd0c243ab5554bef9c168d869c9f6e Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 13:38:12 -0600 Subject: [PATCH 008/200] Modify inputenc, fontenc latex_elements --- met/docs/conf.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/met/docs/conf.py b/met/docs/conf.py index 552f099f5b..5fd35bee0c 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -48,6 +48,8 @@ 'releasename':"{version}", 'fncychap': '\\usepackage{fncychap}', 'fontpkg': '\\usepackage{amsmath,amsfonts,amssymb,amsthm}', + 'inputenc': '\\usepackage[utf8]{inputenc}' + 'fontenc': '\\usepackage[LGR,T1]{fontenc}' 'figure_align':'htbp', 'pointsize': '11pt', From 492cd2e283b0a9e61d03c96e97c25d4421ea2939 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 13:41:05 -0600 Subject: [PATCH 009/200] Fix typo in conf.py --- met/docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/conf.py b/met/docs/conf.py index 5fd35bee0c..9474c4b5d7 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -48,8 +48,8 @@ 'releasename':"{version}", 'fncychap': '\\usepackage{fncychap}', 'fontpkg': '\\usepackage{amsmath,amsfonts,amssymb,amsthm}', - 'inputenc': '\\usepackage[utf8]{inputenc}' - 'fontenc': '\\usepackage[LGR,T1]{fontenc}' + 'inputenc': '\\usepackage[utf8]{inputenc}', + 'fontenc': '\\usepackage[LGR,T1]{fontenc}', 'figure_align':'htbp', 'pointsize': '11pt', From 33cabf4f236e1dea8df35636ef21a63a3177143d Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 14:21:01 -0600 Subject: [PATCH 010/200] Replace unicode with ascii --- .../map/admin_by_country/admin_Yemen_data | 4 +- met/data/map/admin_data | 4 +- met/docs/Users_Guide/appendixA.rst | 6 +- met/docs/Users_Guide/appendixB.rst | 4 +- met/docs/Users_Guide/appendixC.rst | 20 +++---- met/docs/Users_Guide/appendixD.rst | 6 +- met/docs/Users_Guide/appendixE.rst | 16 ++--- met/docs/Users_Guide/appendixF.rst | 8 +-- met/docs/Users_Guide/data_io.rst | 10 ++-- met/docs/Users_Guide/ensemble-stat.rst | 4 +- met/docs/Users_Guide/grid-diag.rst | 4 +- met/docs/Users_Guide/grid-stat.rst | 10 ++-- met/docs/Users_Guide/masking.rst | 38 ++++++------ met/docs/Users_Guide/mode-analysis.rst | 6 +- met/docs/Users_Guide/mode-td.rst | 16 ++--- met/docs/Users_Guide/mode.rst | 6 +- met/docs/Users_Guide/point-stat.rst | 36 ++++++------ met/docs/Users_Guide/reformat_grid.rst | 42 +++++++------- met/docs/Users_Guide/reformat_point.rst | 58 +++++++++---------- met/docs/Users_Guide/refs.rst | 22 +++---- met/docs/Users_Guide/rmw-analysis.rst | 2 +- met/docs/Users_Guide/series-analysis.rst | 2 +- met/docs/Users_Guide/stat-analysis.rst | 28 ++++----- met/docs/Users_Guide/tc-dland.rst | 2 +- met/docs/Users_Guide/tc-gen.rst | 6 +- met/docs/Users_Guide/tc-pairs.rst | 10 ++-- met/docs/Users_Guide/tc-rmw.rst | 2 +- met/docs/Users_Guide/tc-stat.rst | 6 +- met/docs/Users_Guide/wavelet-stat.rst | 24 ++++---- 29 files changed, 201 insertions(+), 201 deletions(-) diff --git a/met/data/map/admin_by_country/admin_Yemen_data b/met/data/map/admin_by_country/admin_Yemen_data index 3bb2d565c1..38eacd3988 100644 --- a/met/data/map/admin_by_country/admin_Yemen_data +++ b/met/data/map/admin_by_country/admin_Yemen_data @@ -126,7 +126,7 @@ 12.94042 -45.09903 12.86061 -45.05790 12.80125 -44.85958 -4 33 13.829 14.8252 -46.0336 -44.5861 'Al Bayḑā’ (Yemen)' +4 33 13.829 14.8252 -46.0336 -44.5861 'Al Bayḑā' (Yemen)' 14.53238 -45.11610 14.50399 -45.18688 14.55476 -45.31480 @@ -579,7 +579,7 @@ 17.42610 -43.61780 17.36670 -43.68330 17.33890 -43.83190 -17 40 14.7473 16.0428 -45.1087 -43.5061 'Şan‘ā’ (Yemen)' +17 40 14.7473 16.0428 -45.1087 -43.5061 'Şan‘ā' (Yemen)' 15.12214 -45.08009 14.79469 -44.90892 14.74730 -44.83651 diff --git a/met/data/map/admin_data b/met/data/map/admin_data index e1e5e18f84..db40e5e64b 100644 --- a/met/data/map/admin_data +++ b/met/data/map/admin_data @@ -82728,7 +82728,7 @@ 30.32615 -48.28101 30.20689 -48.39930 30.20050 -48.40535 -1193 33 13.829 14.8252 -46.0336 -44.5861 'Al Bayḑā’ (Yemen)' +1193 33 13.829 14.8252 -46.0336 -44.5861 'Al Bayḑā' (Yemen)' 14.53238 -45.11610 14.50399 -45.18688 14.55476 -45.31480 @@ -85990,7 +85990,7 @@ 35.17110 -43.41893 35.14398 -43.44602 35.05437 -43.54642 -1267 40 14.7473 16.0428 -45.1087 -43.5061 'Şan‘ā’ (Yemen)' +1267 40 14.7473 16.0428 -45.1087 -43.5061 'Şan‘ā' (Yemen)' 15.12214 -45.08009 14.79469 -44.90892 14.74730 -44.83651 diff --git a/met/docs/Users_Guide/appendixA.rst b/met/docs/Users_Guide/appendixA.rst index e8e5973e9d..a96d2b71c4 100644 --- a/met/docs/Users_Guide/appendixA.rst +++ b/met/docs/Users_Guide/appendixA.rst @@ -44,7 +44,7 @@ A. Currently, very few graphics are included. The plotting tools (plot_point_obs **Q. How do I find the version of the tool I am using?** -A. Type the name of the tool followed by **-version**. For example, type “pb2nc **-version**”. +A. Type the name of the tool followed by **-version**. For example, type "pb2nc **-version**". **Q. What are MET's conventions for latitude, longitude, azimuth and bearing angles?** @@ -81,11 +81,11 @@ The first place to look for help with individual commands is this user's guide o **Error while loading shared libraries** -* Add the lib dir to your LD_LIBRARY_PATH. For example, if you receive the following error: “./mode_analysis: error while loading shared libraries: libgsl.so.19: cannot open shared object file: No such file or directory”, you should add the path to the gsl lib (for example, */home/user/MET/gsl-2.1/lib*) to your LD_LIBRARY_PATH. +* Add the lib dir to your LD_LIBRARY_PATH. For example, if you receive the following error: "./mode_analysis: error while loading shared libraries: libgsl.so.19: cannot open shared object file: No such file or directory", you should add the path to the gsl lib (for example, */home/user/MET/gsl-2.1/lib*) to your LD_LIBRARY_PATH. **General troubleshooting** -* For configuration files used, make certain to use empty square brackets (e.g. [ ]) to indicate no stratification is desired. Do NOT use empty double quotation marks inside square brackets (e.g. [“”]). +* For configuration files used, make certain to use empty square brackets (e.g. [ ]) to indicate no stratification is desired. Do NOT use empty double quotation marks inside square brackets (e.g. [""]). * Have you designated all the required command line arguments? diff --git a/met/docs/Users_Guide/appendixB.rst b/met/docs/Users_Guide/appendixB.rst index 4f93087fad..605712ca43 100644 --- a/met/docs/Users_Guide/appendixB.rst +++ b/met/docs/Users_Guide/appendixB.rst @@ -33,7 +33,7 @@ To specify a Lambert Grid, the syntax is lambert Nx Ny lat_ll lon_ll lon_orient D_km R_km standard_lat_1 [ standard_lat_2 ] N|S -Here, **Nx** and **Ny** are the number of points in, respectively, the **x** and **y** grid directions. These two numbers give the overall size of the grid. **lat_ll** and **lon_ll** are the latitude and longitude, in degrees, of the lower left point of the grid. North latitude and east longitude are considered positive. **lon_orient** is the orientation longitude of the grid. It’s the meridian of longitude that’s parallel to one of the vertical grid directions. **D_km** and **R_km** are the grid resolution and the radius of the Earth, both in kilometers. **standard_lat_1** and **standard_lat_2** are the standard parallels of the Lambert projection. If the two latitudes are the same, then only one needs to be given. **N|S** means to write either **N** or **S** depending on whether the Lambert projection is from the north pole or the south pole. +Here, **Nx** and **Ny** are the number of points in, respectively, the **x** and **y** grid directions. These two numbers give the overall size of the grid. **lat_ll** and **lon_ll** are the latitude and longitude, in degrees, of the lower left point of the grid. North latitude and east longitude are considered positive. **lon_orient** is the orientation longitude of the grid. It's the meridian of longitude that's parallel to one of the vertical grid directions. **D_km** and **R_km** are the grid resolution and the radius of the Earth, both in kilometers. **standard_lat_1** and **standard_lat_2** are the standard parallels of the Lambert projection. If the two latitudes are the same, then only one needs to be given. **N|S** means to write either **N** or **S** depending on whether the Lambert projection is from the north pole or the south pole. As an example of specifying a Lambert grid, suppose you have a northern hemisphere Lambert grid with 614 points in the x direction and 428 points in the y direction. The lower left corner of the grid is at latitude :math:`12.190^\circ` north and longitude :math:`133.459^\circ` west. The orientation longitude is :math:`95^\circ` west. The grid spacing is :math:`12.19058^\circ` km. The radius of the Earth is the default value used in many grib files: 6367.47 km. Both standard parallels are at :math:`25^\circ` north. To specify this grid in the config file, you would write @@ -55,7 +55,7 @@ For Plate Carrée (i.e. Lat/Lon) grids, the syntax is latlon Nx Ny lat_ll lon_ll delta_lat delta_lon -The parameters **Nx, Ny, lat_ll** and **lon_ll** are as before. **delta_lat** and **delta_lon** are the latitude and longitude increments of the grid—i.e., the change in latitude or longitude between one grid point and an adjacent grid point. +The parameters **Nx, Ny, lat_ll** and **lon_ll** are as before. **delta_lat** and **delta_lon** are the latitude and longitude increments of the grid-i.e., the change in latitude or longitude between one grid point and an adjacent grid point. For a Rotated Plate Carrée (i.e. Rotated Lat/Lon) grids, the syntax is diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 547e211d7f..6b1dd59f26 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -594,9 +594,9 @@ Partial Sums lines (SL1L2, SAL1L2, VL1L2, VAL1L2) :numref:`table_PS_format_info_SL1L2`, :numref:`table_PS_format_info_SAL1L2`, :numref:`table_PS_format_info_VL1L2`, and :numref:`table_PS_format_info_VAL1L2` -The SL1L2, SAL1L2, VL1L2, and VAL1L2 line types are used to store data summaries (e.g. partial sums) that can later be accumulated into verification statistics. These are divided according to scalar or vector summaries (S or V). The climate anomaly values (A) can be stored in place of the actuals, which is just a re-centering of the values around the climatological average. L1 and L2 refer to the L1 and L2 norms, the distance metrics commonly referred to as the “city block” and “Euclidean” distances. The city block is the absolute value of a distance while the Euclidean distance is the square root of the squared distance. +The SL1L2, SAL1L2, VL1L2, and VAL1L2 line types are used to store data summaries (e.g. partial sums) that can later be accumulated into verification statistics. These are divided according to scalar or vector summaries (S or V). The climate anomaly values (A) can be stored in place of the actuals, which is just a re-centering of the values around the climatological average. L1 and L2 refer to the L1 and L2 norms, the distance metrics commonly referred to as the "city block" and "Euclidean" distances. The city block is the absolute value of a distance while the Euclidean distance is the square root of the squared distance. -The partial sums can be accumulated over individual cases to produce statistics for a longer period without any loss of information because these sums are *sufficient* for resulting statistics such as RMSE, bias, correlation coefficient, and MAE (:ref:`Mood et al., 1974 `). Thus, the individual errors need not be stored, all of the information relevant to calculation of statistics are contained in the sums. As an example, the sum of all data points and the sum of all squared data points (or equivalently, the sample mean and sample variance) are *jointly sufficient* for estimates of the Gaussian distribution mean and variance. +The partial sums can be accumulated over individual cases to produce statistics for a longer period without any loss of information because these sums are *sufficient* for resulting statistics such as RMSE, bias, correlation coefficient, and MAE (:ref:`Mood et al., 1974 `). Thus, the individual errors need not be stored, all of the information relevant to calculation of statistics are contained in the sums. As an example, the sum of all data points and the sum of all squared data points (or equivalently, the sample mean and sample variance) are *jointly sufficient* for estimates of the Gaussian distribution mean and variance. *Minimally sufficient* statistics are those that condense the data most, with no loss of information. Statistics based on L1 and L2 norms allow for good compression of information. Statistics based on other norms, such as order statistics, do not result in good compression of information. For this reason, statistics such as RMSE are often preferred to statistics such as the median absolute deviation. The partial sums are not sufficient for order statistics, such as the median or quartiles. @@ -1078,23 +1078,23 @@ The results of the distance map verification approaches that are included in the Baddeley's :math:`\Delta` Metric and Hausdorff Distance ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Called “BADDELEY” and “HAUSDORFF” in the DMAP +Called "BADDELEY" and "HAUSDORFF" in the DMAP output :numref:`table_GS_format_info_DMAP` The Baddeley's :math:`\Delta` Metric is given by .. math:: \Delta_{p,w} (A,B) = [ \frac{1}{N} \sum_{s \in D} | w(d(s,A)) - w(d(s,B))|]^{\frac{1}{P}} -where :math:`d(s,\cdot)` is the distance map for the respective event area, :math:`w(\cdot)` is an optional concave function (i.e., :math:`w( t + u) \leq w(t)+w(u))` that is strictly increasing at zero with :math:`w(t)=0` if and only if :math:`t=0`, *N* is the size of the domain, and *p* is a user chosen parameter for the :math:`L_{p}` norm. The default choice of :math:`p = 2` corresponds to a Euclidean average, :math:`p = 1` is a simple average of the difference in distance maps, and the limiting case of :math:`p= \infty` gives the maximum difference between the two distance maps and is called the Hausdorff distance, denoted as :math:`H(A,B)`, and is the metric that motivated the development of Baddeley’s :math:`\Delta` metric. A typical choice, and the only available with MET, for :math:`w(\cdot) \text{ is } w(t)= \min\{t,c\}`, where *c* is a user-chosen constant with :math:`c = \infty` meaning that :math:`w(\cdot)` is not applied. This choice of :math:`w(\cdot)` provides a cutoff for distances beyond the pre-specified amount given by *c*. +where :math:`d(s,\cdot)` is the distance map for the respective event area, :math:`w(\cdot)` is an optional concave function (i.e., :math:`w( t + u) \leq w(t)+w(u))` that is strictly increasing at zero with :math:`w(t)=0` if and only if :math:`t=0`, *N* is the size of the domain, and *p* is a user chosen parameter for the :math:`L_{p}` norm. The default choice of :math:`p = 2` corresponds to a Euclidean average, :math:`p = 1` is a simple average of the difference in distance maps, and the limiting case of :math:`p= \infty` gives the maximum difference between the two distance maps and is called the Hausdorff distance, denoted as :math:`H(A,B)`, and is the metric that motivated the development of Baddeley's :math:`\Delta` metric. A typical choice, and the only available with MET, for :math:`w(\cdot) \text{ is } w(t)= \min\{t,c\}`, where *c* is a user-chosen constant with :math:`c = \infty` meaning that :math:`w(\cdot)` is not applied. This choice of :math:`w(\cdot)` provides a cutoff for distances beyond the pre-specified amount given by *c*. -In terms of distance maps, Baddeley’s :math:`\Delta` is the :math:`L_{p}` norm of the top left panel in :numref:`grid-stat_fig4` provided :math:`c= \infty`. If :math:`0` for more details. diff --git a/met/docs/Users_Guide/appendixE.rst b/met/docs/Users_Guide/appendixE.rst index 22826ce420..e5967f61f4 100644 --- a/met/docs/Users_Guide/appendixE.rst +++ b/met/docs/Users_Guide/appendixE.rst @@ -31,23 +31,23 @@ The usage statement for wwmca_regrid is wwmca_regrid -out filename config filename [ -nh filename ] [ -sh filename ] -Here, the **-out** switch tells wwmca_regrid what to name the output netCDF file. The **-config** switch gives the name of the config file that wwmca_regrid should use—like many of the MET tools, wwmca-regrid uses a configuration file to specify user-changeable parameters. The format of this file will be explained below. +Here, the **-out** switch tells wwmca_regrid what to name the output netCDF file. The **-config** switch gives the name of the config file that wwmca_regrid should use-like many of the MET tools, wwmca-regrid uses a configuration file to specify user-changeable parameters. The format of this file will be explained below. The **-nh** and **-sh** options give names of WWMCA cloud percent files that wwmca_regrid should use as input. Northern hemisphere files are specified with **-nh**, and southern hemisphere files with **-sh**. At least one of these must be given, but in many cases both need not be given. -In any regridding problem, there are two grids involved: the “From” grid, which is the grid the input data are on, and the “To” grid, which is the grid the data are to be moved onto. For wwmca_regrid, the “To” grid is specified in the config file. If this grid is entirely confined to one hemisphere, then only the WWMCA data file for that hemisphere needs to be given. It’s only when the “To” grid straddles the equator that data files for both hemispheres need to be given (though the interpolation width parameter in the config file can change this—see below). Once the “To” grid is specified in the config file, the WWMCA-Regrid tool will know which input data files it needs, and will complain if it’s not given the right ones. +In any regridding problem, there are two grids involved: the "From" grid, which is the grid the input data are on, and the "To" grid, which is the grid the data are to be moved onto. For wwmca_regrid, the "To" grid is specified in the config file. If this grid is entirely confined to one hemisphere, then only the WWMCA data file for that hemisphere needs to be given. It's only when the "To" grid straddles the equator that data files for both hemispheres need to be given (though the interpolation width parameter in the config file can change this-see below). Once the "To" grid is specified in the config file, the WWMCA-Regrid tool will know which input data files it needs, and will complain if it's not given the right ones. -Now let’s talk about the details of the config file. The config file has the same C-like syntax that all the other MET config files use. The first (and most complicated) thing to specify is the “To” grid. This is given by the **to_grid** parameter. If you are using one of the standard NCEP grids, for example grid #218, you can simply write +Now let's talk about the details of the config file. The config file has the same C-like syntax that all the other MET config files use. The first (and most complicated) thing to specify is the "To" grid. This is given by the **to_grid** parameter. If you are using one of the standard NCEP grids, for example grid #218, you can simply write .. code-block:: none To grid = "G218"; -and that will work. Failing that, you must give the parameters that specify the grid and it’s projection. Please refer the description of the grid specification strings in :ref:`appendixB`. +and that will work. Failing that, you must give the parameters that specify the grid and it's projection. Please refer the description of the grid specification strings in :ref:`appendixB`. Thankfully, the rest of the parameters in the config file are easier to specify. -The next two config file parameters have to do with specifying the interpolation scheme used. The **interp_method** parameter specifies which interpolation method is to be used. Four methods are supported: average, maximum, minimum and nearest neighbor. As an example, to specify the “average” method, one would write +The next two config file parameters have to do with specifying the interpolation scheme used. The **interp_method** parameter specifies which interpolation method is to be used. Four methods are supported: average, maximum, minimum and nearest neighbor. As an example, to specify the "average" method, one would write .. code-block:: none @@ -61,15 +61,15 @@ The other interpolation parameter is **interp_width**. This specifies the width The value must be odd and ≥ 1. If a value of 1 is specified, then nearest neighbor interpolation will be used regardless of the value assigned to **interp_method**. -The fact that an interpolation box is used has one subtle implication—the “To” grid is effectively fattened by half the width of the interpolation box. This means that even for a “To” grid that is entirely contained in one hemisphere, if it comes close to the equator, this virtual fattening may be enough to push it over the equator, and the user will then have to provide input WWMCA files for both hemispheres, even though the “To” grid doesn’t cross the equator. The WWMCA-Regrid tool should detect this situation and complain to the user if not given the correct input files. +The fact that an interpolation box is used has one subtle implication-the "To" grid is effectively fattened by half the width of the interpolation box. This means that even for a "To" grid that is entirely contained in one hemisphere, if it comes close to the equator, this virtual fattening may be enough to push it over the equator, and the user will then have to provide input WWMCA files for both hemispheres, even though the "To" grid doesn't cross the equator. The WWMCA-Regrid tool should detect this situation and complain to the user if not given the correct input files. -The next variable, **good_percent**, tells what fraction of the values in the interpolation square needs to be “good” in order for the interpolation scheme to return a “good” result. Example: +The next variable, **good_percent**, tells what fraction of the values in the interpolation square needs to be "good" in order for the interpolation scheme to return a "good" result. Example: .. code-block:: none good percent = 0; -The rest of the config file parameters have to do with how the output netCDF file represents the data. These should be self-explanatory, so I’ll just give an example: +The rest of the config file parameters have to do with how the output netCDF file represents the data. These should be self-explanatory, so I'll just give an example: .. code-block:: none diff --git a/met/docs/Users_Guide/appendixF.rst b/met/docs/Users_Guide/appendixF.rst index aaaa228318..3a4046e9ea 100644 --- a/met/docs/Users_Guide/appendixF.rst +++ b/met/docs/Users_Guide/appendixF.rst @@ -17,9 +17,9 @@ The local Python installation must also support a minimum set of required packag In addition to the **configure** option mentioned above, two variables, **MET_PYTHON_CC** and **MET_PYTHON_LD**, must also be set for the configuration process. These may either be set as environment variables or as command line options to **configure**. These constants are passed as compiler command line options when building MET to enable the compiler to find the requisite Python header files and libraries in the user's local filesystem. Fortunately, Python provides a way to set these variables properly. This frees the user from the necessity of having any expert knowledge of the compiling and linking process. Along with the **Python** executable, there should be another executable called **python3-config**, whose output can be used to set these environment variables as follows: -• On the command line, run “**python3-config --cflags**”. Set the value of **MET_PYTHON_CC** to the output of that command. +• On the command line, run "**python3-config --cflags**". Set the value of **MET_PYTHON_CC** to the output of that command. -• Again on the command line, run “**python3-config --ldflags**”. Set the value of **MET_PYTHON_LD** to the output of that command. +• Again on the command line, run "**python3-config --ldflags**". Set the value of **MET_PYTHON_LD** to the output of that command. Make sure that these are set as environment variables or that you have included them on the command line prior to running **configure**. @@ -239,7 +239,7 @@ Python Embedding for Point Observations _______________________________________ -The ASCII2NC tool supports the “-format python” option. With this option, point observations may be passed as input. An example of this is provided in :numref:`ascii2nc-pyembed`. That example uses the **read_ascii_point.py** sample script which is included with the MET code. It reads ASCII data in MET's 11-column point observation format and stores it in a Pandas dataframe to be read by the ASCII2NC tool with Python. +The ASCII2NC tool supports the "-format python" option. With this option, point observations may be passed as input. An example of this is provided in :numref:`ascii2nc-pyembed`. That example uses the **read_ascii_point.py** sample script which is included with the MET code. It reads ASCII data in MET's 11-column point observation format and stores it in a Pandas dataframe to be read by the ASCII2NC tool with Python. The **read_ascii_point.py** sample script can be found in: @@ -250,7 +250,7 @@ The **read_ascii_point.py** sample script can be found in: Python Embedding for MPR data _____________________________ -The Stat-Analysis tool supports the “-lookin python” option. With this option, matched pair (MPR) data may be passed as input. An example of this is provided in :numref:`StA-pyembed`. That example uses the **read_ascii_mpr.py** sample script which is included with the MET code. It reads MPR data and stores it in a Pandas dataframe to be read by the Stat-Analysis tool with Python. +The Stat-Analysis tool supports the "-lookin python" option. With this option, matched pair (MPR) data may be passed as input. An example of this is provided in :numref:`StA-pyembed`. That example uses the **read_ascii_mpr.py** sample script which is included with the MET code. It reads MPR data and stores it in a Pandas dataframe to be read by the Stat-Analysis tool with Python. The **read_ascii_mpr.py** sample script can be found in: diff --git a/met/docs/Users_Guide/data_io.rst b/met/docs/Users_Guide/data_io.rst index 3dd4552ab9..8b6d41ea95 100644 --- a/met/docs/Users_Guide/data_io.rst +++ b/met/docs/Users_Guide/data_io.rst @@ -92,7 +92,7 @@ The following is a summary of the input and output formats for each of the tools #. **Pcp-Combine Tool** - * **Input**: Two or more gridded model or observation files (in GRIB format for “sum” command, or any gridded file for “add”, “subtract”, and “derive” commands) containing data (often accumulated precipitation) to be combined. + * **Input**: Two or more gridded model or observation files (in GRIB format for "sum" command, or any gridded file for "add", "subtract", and "derive" commands) containing data (often accumulated precipitation) to be combined. * **Output**: One NetCDF file containing output for the requested operation(s). @@ -142,7 +142,7 @@ The following is a summary of the input and output formats for each of the tools * **Input**: One gridded model file, one gridded observation file, and one configuration file. - * **Output**: One STAT file containing the “ISC” line type, one ASCII file containing intensity-scale information and statistics, one NetCDF file containing information about the wavelet decomposition of forecast and observed fields and their differences, and one PostScript file containing plots and summaries of the intensity-scale verification. + * **Output**: One STAT file containing the "ISC" line type, one ASCII file containing intensity-scale information and statistics, one NetCDF file containing information about the wavelet decomposition of forecast and observed fields and their differences, and one PostScript file containing plots and summaries of the intensity-scale verification. #. **GSID2MPR Tool** @@ -160,7 +160,7 @@ The following is a summary of the input and output formats for each of the tools * **Input**: One or more STAT files output from the Point-Stat, Grid-Stat, Ensemble Stat, Wavelet-Stat, or TC-Gen tools and, optionally, one configuration file containing specifications for the analysis job(s) to be run on the STAT data. - * **Output**: ASCII output of the analysis jobs is printed to the screen unless redirected to a file using the “-out” option or redirected to a STAT output file using the “-out_stat” option. + * **Output**: ASCII output of the analysis jobs is printed to the screen unless redirected to a file using the "-out" option or redirected to a STAT output file using the "-out_stat" option. #. **Series-Analysis Tool** @@ -184,7 +184,7 @@ The following is a summary of the input and output formats for each of the tools * **Input**: One or more MODE object statistics files from the MODE tool and, optionally, one configuration file containing specification for the analysis job(s) to be run on the object data. - * **Output**: ASCII output of the analysis jobs will be printed to the screen unless redirected to a file using the “-out” option. + * **Output**: ASCII output of the analysis jobs will be printed to the screen unless redirected to a file using the "-out" option. #. **MODE-TD Tool** @@ -208,7 +208,7 @@ The following is a summary of the input and output formats for each of the tools * **Input**: One or more TCSTAT output files output from the TC-Pairs tool and, optionally, one configuration file containing specifications for the analysis job(s) to be run on the TCSTAT data. - * **Output**: ASCII output of the analysis jobs will be printed to the screen unless redirected to a file using the “-out” option. + * **Output**: ASCII output of the analysis jobs will be printed to the screen unless redirected to a file using the "-out" option. #. **TC-Gen Tool** diff --git a/met/docs/Users_Guide/ensemble-stat.rst b/met/docs/Users_Guide/ensemble-stat.rst index cfe920c0e6..d4763fe32f 100644 --- a/met/docs/Users_Guide/ensemble-stat.rst +++ b/met/docs/Users_Guide/ensemble-stat.rst @@ -106,9 +106,9 @@ Optional arguments for ensemble_stat 10. The **-log** file outputs log messages to the specified file. -11. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. +11. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. -12. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +12. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the ensemble_stat calling sequence is shown below: diff --git a/met/docs/Users_Guide/grid-diag.rst b/met/docs/Users_Guide/grid-diag.rst index fb6c14f58c..22200ad0e2 100644 --- a/met/docs/Users_Guide/grid-diag.rst +++ b/met/docs/Users_Guide/grid-diag.rst @@ -48,9 +48,9 @@ Optional arguments for grid_diag 4. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -5. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +5. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -6. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +6. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. grid_diag configuration file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/met/docs/Users_Guide/grid-stat.rst b/met/docs/Users_Guide/grid-stat.rst index 123954bc47..b05ec4ad7d 100644 --- a/met/docs/Users_Guide/grid-stat.rst +++ b/met/docs/Users_Guide/grid-stat.rst @@ -31,7 +31,7 @@ Measures for continuous variables For continuous variables, many verification measures are based on the forecast error (i.e., f - o). However, it also is of interest to investigate characteristics of the forecasts, and the observations, as well as their relationship. These concepts are consistent with the general framework for verification outlined by :ref:`Murphy and Winkler (1987) `. The statistics produced by MET for continuous forecasts represent this philosophy of verification, which focuses on a variety of aspects of performance rather than a single measure. See :numref:`Appendix C, Section %s ` for specific information. -A user may wish to eliminate certain values of the forecasts from the calculation of statistics, a process referred to here as “conditional verification”. For example, a user may eliminate all temperatures above freezing and then calculate the error statistics only for those forecasts of below freezing temperatures. Another common example involves verification of wind forecasts. Since wind direction is indeterminate at very low wind speeds, the user may wish to set a minimum wind speed threshold prior to calculating error statistics for wind direction. The user may specify these thresholds in the configuration file to specify the conditional verification. Thresholds can be specified using the usual Fortran conventions (<, <=, ==, !-, >=, or >) followed by a numeric value. The threshold type may also be specified using two letter abbreviations (lt, le, eq, ne, ge, gt). Further, more complex thresholds can be achieved by defining multiple thresholds and using && or || to string together event definition logic. The forecast and observation threshold can be used together according to user preference by specifying one of: UNION, INTERSECTION, or SYMDIFF (symmetric difference). +A user may wish to eliminate certain values of the forecasts from the calculation of statistics, a process referred to here as "conditional verification". For example, a user may eliminate all temperatures above freezing and then calculate the error statistics only for those forecasts of below freezing temperatures. Another common example involves verification of wind forecasts. Since wind direction is indeterminate at very low wind speeds, the user may wish to set a minimum wind speed threshold prior to calculating error statistics for wind direction. The user may specify these thresholds in the configuration file to specify the conditional verification. Thresholds can be specified using the usual Fortran conventions (<, <=, ==, !-, >=, or >) followed by a numeric value. The threshold type may also be specified using two letter abbreviations (lt, le, eq, ne, ge, gt). Further, more complex thresholds can be achieved by defining multiple thresholds and using && or || to string together event definition logic. The forecast and observation threshold can be used together according to user preference by specifying one of: UNION, INTERSECTION, or SYMDIFF (symmetric difference). Measures for probabilistic forecasts and dichotomous outcomes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ When computing continuous statistics on a regular large scale or global latitude Neighborhood methods ~~~~~~~~~~~~~~~~~~~~ -MET also incorporates several neighborhood methods to give credit to forecasts that are close to the observations, but not necessarily exactly matched up in space. Also referred to as “fuzzy” verification methods, these methods do not just compare a single forecast at each grid point to a single observation at each grid point; they compare the forecasts and observations in a neighborhood surrounding the point of interest. With the neighborhood method, the user chooses a distance within which the forecast event can fall from the observed event and still be considered a hit. In MET this is implemented by defining a square search window around each grid point. Within the search window, the number of observed events is compared to the number of forecast events. In this way, credit is given to forecasts that are close to the observations without requiring a strict match between forecasted events and observed events at any particular grid point. The neighborhood methods allow the user to see how forecast skill varies with neighborhood size and can help determine the smallest neighborhood size that can be used to give sufficiently accurate forecasts. +MET also incorporates several neighborhood methods to give credit to forecasts that are close to the observations, but not necessarily exactly matched up in space. Also referred to as "fuzzy" verification methods, these methods do not just compare a single forecast at each grid point to a single observation at each grid point; they compare the forecasts and observations in a neighborhood surrounding the point of interest. With the neighborhood method, the user chooses a distance within which the forecast event can fall from the observed event and still be considered a hit. In MET this is implemented by defining a square search window around each grid point. Within the search window, the number of observed events is compared to the number of forecast events. In this way, credit is given to forecasts that are close to the observations without requiring a strict match between forecasted events and observed events at any particular grid point. The neighborhood methods allow the user to see how forecast skill varies with neighborhood size and can help determine the smallest neighborhood size that can be used to give sufficiently accurate forecasts. There are several ways to present the results of the neighborhood approaches, such as the Fractions Skill Score (FSS) or the Fractions Brier Score (FBS). These scores are presented in :numref:`Appendix C, Section %s `. One can also simply up-scale the information on the forecast verification grid by smoothing or resampling within a specified neighborhood around each grid point and recalculate the traditional verification metrics on the coarser grid. The MET output includes traditional contingency table statistics for each threshold and neighborhood window size. @@ -163,9 +163,9 @@ Optional arguments for grid_stat 5. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -6. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +6. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -7. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +7. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the grid_stat calling sequence is listed below: @@ -251,7 +251,7 @@ The **field** entry is set to **BOTH, FCST, OBS**, or **NONE** to indicate the f The **vld_thresh** entry contains a number between 0 and 1. When performing neighborhood verification over some neighborhood of points the ratio of the number of valid data points to the total number of points in the neighborhood is computed. If that ratio is greater than this threshold, that value is included in the neighborhood verification. Setting this threshold to 1, which is the default, requires that the entire neighborhood must contain valid data. This variable will typically come into play only along the boundaries of the verification region chosen. -The **cov_thresh** entry contains a comma separated list of thresholds to be applied to the neighborhood coverage field. The coverage is the proportion of forecast points in the neighborhood that exceed the forecast threshold. For example, if 10 of the 25 forecast grid points contain values larger than a threshold of 2, then the coverage is 10/25 = 0.4. If the coverage threshold is set to 0.5, then this neighborhood is considered to be a “No” forecast. +The **cov_thresh** entry contains a comma separated list of thresholds to be applied to the neighborhood coverage field. The coverage is the proportion of forecast points in the neighborhood that exceed the forecast threshold. For example, if 10 of the 25 forecast grid points contain values larger than a threshold of 2, then the coverage is 10/25 = 0.4. If the coverage threshold is set to 0.5, then this neighborhood is considered to be a "No" forecast. ___________________ diff --git a/met/docs/Users_Guide/masking.rst b/met/docs/Users_Guide/masking.rst index 08ef85727c..db695f97f1 100644 --- a/met/docs/Users_Guide/masking.rst +++ b/met/docs/Users_Guide/masking.rst @@ -3,7 +3,7 @@ Regional Verification using Spatial Masking =========================================== -Verification over a particular region or area of interest may be performed using “masking”. Defining a masking region is simply selecting the desired set of grid points to be used. The Gen-Vx-Mask tool automates this process and replaces the Gen-Poly-Mask and Gen-Circle-Mask tools from previous releases. It may be run to create a bitmap verification masking region to be used by many of the statistical tools. This tool enables the user to generate a masking region once for a domain and apply it to many cases. It has been enhanced to support additional types of masking region definition (e.g. tropical-cyclone track over water only). An iterative approach may be used to define complex areas by combining multiple masking regions together. +Verification over a particular region or area of interest may be performed using "masking". Defining a masking region is simply selecting the desired set of grid points to be used. The Gen-Vx-Mask tool automates this process and replaces the Gen-Poly-Mask and Gen-Circle-Mask tools from previous releases. It may be run to create a bitmap verification masking region to be used by many of the statistical tools. This tool enables the user to generate a masking region once for a domain and apply it to many cases. It has been enhanced to support additional types of masking region definition (e.g. tropical-cyclone track over water only). An iterative approach may be used to define complex areas by combining multiple masking regions together. Gen-Vx-Mask tool ________________ @@ -45,15 +45,15 @@ Required arguments for gen_vx_mask 2. The **mask_file** argument defines the masking information, see below. -• For “poly”, “box”, “circle”, and “track” masking, specify an ASCII Lat/Lon file. +• For "poly", "box", "circle", and "track" masking, specify an ASCII Lat/Lon file. -• For “grid” and “data” masking, specify a gridded data file. +• For "grid" and "data" masking, specify a gridded data file. -• For “solar_alt” and “solar_azi” masking, specify a gridded data file or a time string in YYYYMMDD[_HH[MMSS]] format. +• For "solar_alt" and "solar_azi" masking, specify a gridded data file or a time string in YYYYMMDD[_HH[MMSS]] format. -• For “lat” and “lon” masking, no “mask_file” needed, simply repeat the path for “input_file”. +• For "lat" and "lon" masking, no "mask_file" needed, simply repeat the path for "input_file". -• For “shape” masking, specify an ESRI shapefile (.shp). +• For "shape" masking, specify an ESRI shapefile (.shp). 3. The **out_file** argument is the output NetCDF mask file to be written. @@ -62,25 +62,25 @@ Required arguments for gen_vx_mask Optional arguments for gen_vx_mask ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -5. The **-input_field string** option can be used to read existing mask data from “input_file”. +5. The **-input_field string** option can be used to read existing mask data from "input_file". -6. The **-mask_field string** option can be used to define the field from “mask_file” to be used for “data” masking. +6. The **-mask_field string** option can be used to define the field from "mask_file" to be used for "data" masking. -7. The **-complement** option can be used to compute the complement of the area defined by “mask_file”. +7. The **-complement** option can be used to compute the complement of the area defined by "mask_file". -8. The **-union | -intersection | -symdiff** option can be used to specify how to combine the masks from “input_file” and “mask_file”. +8. The **-union | -intersection | -symdiff** option can be used to specify how to combine the masks from "input_file" and "mask_file". 9. The **-thresh string** option can be used to define the threshold to be applied. -• For “circle” and “track” masking, threshold the distance (km). +• For "circle" and "track" masking, threshold the distance (km). -• For “data” masking, threshold the values of “mask_field”. +• For "data" masking, threshold the values of "mask_field". -• For “solar_alt” and “solar_azi” masking, threshold the computed solar values. +• For "solar_alt" and "solar_azi" masking, threshold the computed solar values. -• For “lat” and “lon” masking, threshold the latitude and longitude values. +• For "lat" and "lon" masking, threshold the latitude and longitude values. -10. The **-height n** and **-width n** options set the size in grid units for “box”masking. +10. The **-height n** and **-width n** options set the size in grid units for "box"masking. 11. The **-shapeno n** option is only used for shapefile masking. (See description of shapefile masking below). @@ -92,7 +92,7 @@ Optional arguments for gen_vx_mask 15. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. -16. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +16. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. The Gen-Vx-Mask tool supports the following types of masking region definition selected using the **-type** command line option: @@ -112,7 +112,7 @@ The Gen-Vx-Mask tool supports the following types of masking region definition s 8. Latitude (**lat**) and longitude (**lon**) masking computes the latitude and longitude value at each grid point. This logic only requires the definition of the grid, specified by the **input_file**. Technically, the **mask_file** is not needed, but a value must be specified for the command line to parse correctly. Users are advised to simply repeat the **input_file** setting twice. If the **-thresh** command line option is not used, the raw latitude or longitude values for each grid point will be written to the output. This option is useful when defining latitude or longitude bands over which to compute statistics. -9. Shapefile (**shape**) masking uses a closed polygon taken from an ESRI shapefile to define the masking region. Gen-Vx-Mask reads the shapefile with the ".shp" suffix and extracts the latitude and longitudes of the vertices. The other types of shapefiles (index file, suffix “.shx”, and dBASE file, suffix “.dbf”) are not currently used. The shapefile must consist of closed polygons rather than polylines, points, or any of the other data types that shapefiles support. Shapefiles usually contain more than one polygon, and the **-shape n** command line option enables the user to select one polygon from the shapefile. The integer **n** tells which shape number to use from the shapefile. Note that this value is zero-based, so that the first polygon in the shapefile is polygon number 0, the second polygon in the shapefile is polygon number 1, etc. For the user's convenience, some utilities that perform human-readable screen dumps of shapefile contents are provided. The gis_dump_shp, gis_dump_shx and gis_dump_dbf tools enable the user to examine the contents of her shapefiles. As an example, if the user knows the name of the particular polygon but not the number of the polygon in the shapefile, the user can use the gis_dump_dbf utility to examine the names of the polygons in the shapefile. The information written to the screen will display the corresponding polygon number. +9. Shapefile (**shape**) masking uses a closed polygon taken from an ESRI shapefile to define the masking region. Gen-Vx-Mask reads the shapefile with the ".shp" suffix and extracts the latitude and longitudes of the vertices. The other types of shapefiles (index file, suffix ".shx", and dBASE file, suffix ".dbf") are not currently used. The shapefile must consist of closed polygons rather than polylines, points, or any of the other data types that shapefiles support. Shapefiles usually contain more than one polygon, and the **-shape n** command line option enables the user to select one polygon from the shapefile. The integer **n** tells which shape number to use from the shapefile. Note that this value is zero-based, so that the first polygon in the shapefile is polygon number 0, the second polygon in the shapefile is polygon number 1, etc. For the user's convenience, some utilities that perform human-readable screen dumps of shapefile contents are provided. The gis_dump_shp, gis_dump_shx and gis_dump_dbf tools enable the user to examine the contents of her shapefiles. As an example, if the user knows the name of the particular polygon but not the number of the polygon in the shapefile, the user can use the gis_dump_dbf utility to examine the names of the polygons in the shapefile. The information written to the screen will display the corresponding polygon number. The polyline, box, circle, and track masking methods all read an ASCII file containing Lat/Lon locations. Those files must contain a string, which defines the name of the masking region, followed by a series of whitespace-separated latitude (degrees north) and longitude (degree east) values. @@ -150,7 +150,7 @@ This three step process enables the Gen-Vx-Mask tool to be run iteratively on it • Rerun the Gen-Vx-Mask tool passing in the output of the first call and applying polyline masking to define the geographic area of interest. - – Use the **-intersection** option to only select grid points whose value is non-zero in both the input field and the current mask. + - Use the **-intersection** option to only select grid points whose value is non-zero in both the input field and the current mask. An example of the gen_vx_mask calling sequence is shown below: @@ -164,4 +164,4 @@ In this example, the Gen-Vx-Mask tool will read the ASCII Lat/Lon file named **C Feature-Relative Methods ________________________ -This section contains a description of several methods that may be used to perform feature-relative (or event -based) evaluation. The methodology pertains to examining the environment surrounding a particular feature or event such as a tropical, extra-tropical cyclone, convective cell, snow-band, etc. Several approaches are available for these types of investigations including applying masking described above (e.g. circle or box) or using the “FORCE” interpolation method in the regrid configuration option (see :numref:`config_options`). These methods generally require additional scripting, including potentially storm-track identification, outside of MET to be paired with the features of the MET tools. METplus may be used to execute this type of analysis. Please refer to the `METplus User's Guide `__. +This section contains a description of several methods that may be used to perform feature-relative (or event -based) evaluation. The methodology pertains to examining the environment surrounding a particular feature or event such as a tropical, extra-tropical cyclone, convective cell, snow-band, etc. Several approaches are available for these types of investigations including applying masking described above (e.g. circle or box) or using the "FORCE" interpolation method in the regrid configuration option (see :numref:`config_options`). These methods generally require additional scripting, including potentially storm-track identification, outside of MET to be paired with the features of the MET tools. METplus may be used to execute this type of analysis. Please refer to the `METplus User's Guide `__. diff --git a/met/docs/Users_Guide/mode-analysis.rst b/met/docs/Users_Guide/mode-analysis.rst index 53852534e3..c641f8b8e6 100644 --- a/met/docs/Users_Guide/mode-analysis.rst +++ b/met/docs/Users_Guide/mode-analysis.rst @@ -13,9 +13,9 @@ Users may wish to summarize multiple ASCII files produced by MODE across many ca Scientific and statistical aspects __________________________________ -The MODE-Analysis tool operates in two modes, called “summary” and “bycase”. In summary mode, the user specifies on the command line the MODE output columns of interest as well as filtering criteria that determine which input lines should be used. For example, a user may be interested in forecast object areas, but only if the object was matched, and only if the object centroid is inside a particular region. The summary statistics generated for each specified column of data are the minimum, maximum, mean, standard deviation, and the 10th, 25th, 50th, 75th and 90th percentiles. In addition, the user may specify a “dump'” file: the individual MODE lines used to produce the statistics will be written to this file. This option provides the user with a filtering capability. The dump file will consist only of lines that match the specified criteria. +The MODE-Analysis tool operates in two modes, called "summary" and "bycase". In summary mode, the user specifies on the command line the MODE output columns of interest as well as filtering criteria that determine which input lines should be used. For example, a user may be interested in forecast object areas, but only if the object was matched, and only if the object centroid is inside a particular region. The summary statistics generated for each specified column of data are the minimum, maximum, mean, standard deviation, and the 10th, 25th, 50th, 75th and 90th percentiles. In addition, the user may specify a "dump'" file: the individual MODE lines used to produce the statistics will be written to this file. This option provides the user with a filtering capability. The dump file will consist only of lines that match the specified criteria. -The other option for operating the analysis tool is “bycase”. Given initial and final values for forecast lead time, the tool will output, for each valid time in the interval, the matched area, unmatched area, and the number of forecast and observed objects that were matched or unmatched. For the areas, the user can specify forecast or observed objects, and also simple or cluster objects. A dump file may also be specified in this mode. +The other option for operating the analysis tool is "bycase". Given initial and final values for forecast lead time, the tool will output, for each valid time in the interval, the matched area, unmatched area, and the number of forecast and observed objects that were matched or unmatched. For the areas, the user can specify forecast or observed objects, and also simple or cluster objects. A dump file may also be specified in this mode. Practical information _____________________ @@ -591,7 +591,7 @@ mode_analysis configuration file To use the MODE-Analysis tool, the user must un-comment the options in the configuration file to apply them and comment out unwanted options. The options in the configuration file for the MODE-Analysis tools are the same as the MODE command line options described in :numref:`mode_analysis-usage`. -The parameters that are set in the configuration file either add to or override parameters that are set on the command line. For the “set string” and “set integer type” options enclosed in brackets, the values specified in the configuration file are added to any values set on the command line. For the “toggle” and “min/max type” options, the values specified in the configuration file override those set on the command line. +The parameters that are set in the configuration file either add to or override parameters that are set on the command line. For the "set string" and "set integer type" options enclosed in brackets, the values specified in the configuration file are added to any values set on the command line. For the "toggle" and "min/max type" options, the values specified in the configuration file override those set on the command line. mode_analysis output ~~~~~~~~~~~~~~~~~~~~ diff --git a/met/docs/Users_Guide/mode-td.rst b/met/docs/Users_Guide/mode-td.rst index 75f45b2054..b646410835 100644 --- a/met/docs/Users_Guide/mode-td.rst +++ b/met/docs/Users_Guide/mode-td.rst @@ -42,11 +42,11 @@ Convolution As in MODE, MTD applies a convolution filter to the raw data as a preliminary step in resolving the field into objects. The convolution step in MTD differs in several respects from that performed in MODE, however. -First, MTD typically reads in several planes of data for each data field—one plane for each time step, and there is really no limit to the number of time steps. So MTD is convolving much more data than it would be if it were simply analyzing a 2D data field. Secondly, MTD convolves in time as well as space, which again increases the amount of data needing to be processed. The net effect of all this is to greatly increase the time needed to perform the convolution step. +First, MTD typically reads in several planes of data for each data field-one plane for each time step, and there is really no limit to the number of time steps. So MTD is convolving much more data than it would be if it were simply analyzing a 2D data field. Secondly, MTD convolves in time as well as space, which again increases the amount of data needing to be processed. The net effect of all this is to greatly increase the time needed to perform the convolution step. Because of this, the developers decided to make several changes in the way convolution was performed in MTD. Most of the differences come from the need to make the convolution step as fast as possible. -The most basic change is to use a square convolution filter rather than the circular one that MODE uses. The overall “size” of the filter is still determined by one parameter (denoted :math:`R`, as in MODE), but this should not be thought of as a radius. Instead, the size of the square is :math:`(2 R + 1) \times (2 R + 1)`, as shown in :numref:`mtd-two_r_plus_one`. +The most basic change is to use a square convolution filter rather than the circular one that MODE uses. The overall "size" of the filter is still determined by one parameter (denoted :math:`R`, as in MODE), but this should not be thought of as a radius. Instead, the size of the square is :math:`(2 R + 1) \times (2 R + 1)`, as shown in :numref:`mtd-two_r_plus_one`. .. _mtd-two_r_plus_one: @@ -73,7 +73,7 @@ The vector **velocity** :math:`(v_x, v_y)` is obtained by fitting a line to a 3D The spatial orientation of an object (what traditional MODE calls the **axis angle** of an object) is gotten by fitting a plane to an object. As with the case of velocity, our optimization criterion is that the sum of the squares of the spatial distances from each point of the object to the plane be minimized. -:numref:`mtd-axis_3d` gives some idea of the reason for fitting a plane, rather than a line, as MODE does. On the left in the figure, we see an object (in blue shaped like an “A”) at several time steps moving through the grid. For simplicity, the object is not rotating as it moves (though of course real objects can certainly do this). At each time step, the 2D MODE spatial axis of the object is indicated by the red line. In the center of the figure, we see the same thing, just with more time steps. And on the right, even more time steps. We see that the axis lines at each time step sweep out a plane in three dimensions, shown in red on the right. This plane is the same one that MTD would calculate for this 3D object to determine its spatial orientation, *i.e.,* axis angle. Indeed, for the special case of an object that is not moving at all, the MTD calculation of axis angle reduces to the same one that traditional MODE uses, as it should. +:numref:`mtd-axis_3d` gives some idea of the reason for fitting a plane, rather than a line, as MODE does. On the left in the figure, we see an object (in blue shaped like an "A") at several time steps moving through the grid. For simplicity, the object is not rotating as it moves (though of course real objects can certainly do this). At each time step, the 2D MODE spatial axis of the object is indicated by the red line. In the center of the figure, we see the same thing, just with more time steps. And on the right, even more time steps. We see that the axis lines at each time step sweep out a plane in three dimensions, shown in red on the right. This plane is the same one that MTD would calculate for this 3D object to determine its spatial orientation, *i.e.,* axis angle. Indeed, for the special case of an object that is not moving at all, the MTD calculation of axis angle reduces to the same one that traditional MODE uses, as it should. .. _mtd-axis_3d: @@ -92,9 +92,9 @@ Finally, MTD calculates several **intensity percentiles** of the raw data values 3D Pair Attributes ~~~~~~~~~~~~~~~~~~ -The next category of spatial attributes is for pairs of objects — one of the pair coming from the collection of forecast objects, the other coming from the observation objects. +The next category of spatial attributes is for pairs of objects - one of the pair coming from the collection of forecast objects, the other coming from the observation objects. -Note: whenever a pair attribute is described below as a *delta*, that means it's a simple difference of two single-object attributes. The difference is always taken as “forecast minus observed”. +Note: whenever a pair attribute is described below as a *delta*, that means it's a simple difference of two single-object attributes. The difference is always taken as "forecast minus observed". The **spatial centroid distance** is the purely spatial part of the centroid separation of two objects. If one centroid is at :math:`(\bar{x}_1, \bar{y}_1, \bar{t}_1)` and the other is at :math:`(\bar{x}_2, \bar{y}_2, \bar{t}_2)` then the distance is calculated as @@ -184,7 +184,7 @@ MTD input The formats for two-dimensional data files used as input to MTD are the same ones supported by most of the MET tools. Generally speaking, if MODE can use a forecast or observation data file as input, then that file can also be used by MTD. The only difference is that while MODE takes only one forecast and one observed data file as input, MTD takes a series of files. -As shown in the next section, filenames for each time used must be given. Thus, for example, if MTD is being used for verification over a period of 24 hours, and the data file valid times are separated by one hour, then a total of 48 filenames must be specified on the MTD command line — 24 filenames for the forecast files, and 24 for the observation files. Further, the filenames must be given in order of increasing valid time. Many users will prefer to write scripts to automate this, rather than type in a lengthy command line by hand. +As shown in the next section, filenames for each time used must be given. Thus, for example, if MTD is being used for verification over a period of 24 hours, and the data file valid times are separated by one hour, then a total of 48 filenames must be specified on the MTD command line - 24 filenames for the forecast files, and 24 for the observation files. Further, the filenames must be given in order of increasing valid time. Many users will prefer to write scripts to automate this, rather than type in a lengthy command line by hand. MTD usage ~~~~~~~~~ @@ -558,7 +558,7 @@ The contents of the OBJECT_ID and OBJECT_CAT columns identify the objects using - Angle that the axis plane of an object makes with the grid x direction * - 33 - VOLUME - - Integer count of the number of 3D “cells” in an object + - Integer count of the number of 3D "cells" in an object * - 34 - START_TIME - Object start time @@ -631,7 +631,7 @@ The contents of the OBJECT_ID and OBJECT_CAT columns identify the objects using - Difference in object ending time steps * - 33 - INTERSECTION_VOLUME - - “Volume” of object intersection + - "Volume" of object intersection * - 34 - DURATION_DIFF - Difference in the lifetimes of the two objects diff --git a/met/docs/Users_Guide/mode.rst b/met/docs/Users_Guide/mode.rst index 68556c2c9c..5ab864f459 100644 --- a/met/docs/Users_Guide/mode.rst +++ b/met/docs/Users_Guide/mode.rst @@ -46,7 +46,7 @@ where :math:`T` is the threshold. The objects are the connected regions where :m .. math:: F(x,y)=M(x,y)f(x,y). -Thus, two parameters — the radius of influence :math:`R`, and the threshold :math:`T` — control the entire process of resolving objects in the raw data field. +Thus, two parameters - the radius of influence :math:`R`, and the threshold :math:`T` - control the entire process of resolving objects in the raw data field. An example of the steps involved in resolving objects is shown in :numref:`mode-object_id`. It shows a "raw" precipitation field, where the vertical coordinate represents the precipitation amount. Part (b) shows the convolved field, and part (c) shows the masked field obtained after the threshold is applied. Finally, :numref:`mode-object_id` shows the objects once the original precipitation values have been restored to the interiors of the objects. @@ -148,7 +148,7 @@ Optional arguments for mode 7. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -8. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +8. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the MODE calling sequence is listed below: @@ -641,7 +641,7 @@ This first file uses the following naming convention: where *PREFIX* indicates the user-defined output prefix, *FCST\_VAR\_LVL* is the forecast variable and vertical level being used, *OBS\_VAR\_LVL* is the observation variable and vertical level being used, *HHMMSSL* indicates the forecast lead time, *YYYYMMDD\_HHMMSSV* indicates the forecast valid time, and *HHMMSSA* indicates the accumulation period. The {\tt cts} string stands for contingency table statistics. The generation of this file can be disabled using the *ct\_stats\_flag* option in the configuration file. This CTS output file differs somewhat from the CTS output of the Point-Stat and Grid-Stat tools. The columns of this output file are summarized in :numref:`CTS_output`. -The second ASCII file the MODE tool generates contains all of the attributes for simple objects, the merged cluster objects, and pairs of objects. Each line in this file contains the same number of columns, though those columns not applicable to a given line contain fill data. The first row of every MODE object attribute file is a header containing the column names. The number of lines in this file depends on the number of objects defined. This file contains lines of 6 types that are indicated by the contents of the **OBJECT_ID** column. The **OBJECT_ID** can take the following 6 forms: **FNN, ONN, FNNN_ONNN, CFNNN, CONNN, CFNNN_CONNN**. In each case, **NNN** is a three-digit number indicating the object index. While all lines have the first 18 header columns in common, these 6 forms for **OBJECT_ID** can be divided into two types - one for single objects and one for pairs of objects. The single object lines **(FNN, ONN, CFNNN**, and **CONNN)** contain valid data in columns 19–39 and fill data in columns 40–51. The object pair lines **(FNNN_ONNN** and **CFNNN_CONNN)** contain valid data in columns 40–51 and fill data in columns 19–39. +The second ASCII file the MODE tool generates contains all of the attributes for simple objects, the merged cluster objects, and pairs of objects. Each line in this file contains the same number of columns, though those columns not applicable to a given line contain fill data. The first row of every MODE object attribute file is a header containing the column names. The number of lines in this file depends on the number of objects defined. This file contains lines of 6 types that are indicated by the contents of the **OBJECT_ID** column. The **OBJECT_ID** can take the following 6 forms: **FNN, ONN, FNNN_ONNN, CFNNN, CONNN, CFNNN_CONNN**. In each case, **NNN** is a three-digit number indicating the object index. While all lines have the first 18 header columns in common, these 6 forms for **OBJECT_ID** can be divided into two types - one for single objects and one for pairs of objects. The single object lines **(FNN, ONN, CFNNN**, and **CONNN)** contain valid data in columns 19-39 and fill data in columns 40-51. The object pair lines **(FNNN_ONNN** and **CFNNN_CONNN)** contain valid data in columns 40-51 and fill data in columns 19-39. These object identifiers are described in :numref:`MODE_object_attribute`. diff --git a/met/docs/Users_Guide/point-stat.rst b/met/docs/Users_Guide/point-stat.rst index a1a7cdd9cf..ed99da2a59 100644 --- a/met/docs/Users_Guide/point-stat.rst +++ b/met/docs/Users_Guide/point-stat.rst @@ -1307,58 +1307,58 @@ The first set of header columns are common to all of the output files generated * - 25 - TOTAL - Total number of data points - * - 26–28 + * - 26-28 - FBAR - Mean value of forecast wind speed - * - 29–31 + * - 29-31 - OBAR - Mean value of observed wind speed - * - 32–34 + * - 32-34 - FS_RMS - Root mean square forecast wind speed - * - 35–37 + * - 35-37 - OS_RMS - Root mean square observed wind speed - * - 38–40 + * - 38-40 - MSVE - Mean squared length of the vector difference between the forecast and observed winds - * - 41–43 + * - 41-43 - RMSVE - Square root of MSVE - * - 45–46 + * - 45-46 - FSTDEV - Standard deviation of the forecast wind speed - * - 47–49 + * - 47-49 - OSTDEV - Standard deviation of the observed wind field - * - 50–52 + * - 50-52 - FDIR - Direction of the average forecast wind vector - * - 53–55 + * - 53-55 - ODIR - Direction of the average observed wind vector - * - 56–58 + * - 56-58 - FBAR_SPEED - Length (speed) of the average forecast wind vector - * - 59–61 + * - 59-61 - OBAR_SPEED - Length (speed) of the average observed wind vector - * - 62–64 + * - 62-64 - VDIFF_SPEED - Length (speed) of the vector difference between the average forecast and average observed wind vectors - * - 65–67 + * - 65-67 - VDIFF_DIR - Direction of the vector difference between the average forecast and average wind vectors - * - 68–70 + * - 68-70 - SPEED_ERR - Difference between the length of the average forecast wind vector and the average observed wind vector (in the sense F - O) - * - 71–73 + * - 71-73 - SPEED_ABSERR - Absolute value of SPEED_ERR - * - 74–76 + * - 74-76 - DIR_ERR - Signed angle between the directions of the average forecast and observed wing vectors. Positive if the forecast wind vector is counterclockwise from the observed wind vector - * - 77–79 + * - 77-79 - DIR_ABSERR - Absolute value of DIR_ABSERR diff --git a/met/docs/Users_Guide/reformat_grid.rst b/met/docs/Users_Guide/reformat_grid.rst index c2c5fe36ba..5975de88d1 100644 --- a/met/docs/Users_Guide/reformat_grid.rst +++ b/met/docs/Users_Guide/reformat_grid.rst @@ -10,17 +10,17 @@ ________________ This section describes the Pcp-Combine tool which summarizes data across multiple input gridded data files and writes the results to a single NetCDF output file. It is often used to modify precipitation accumulation intervals in the forecast and/or observation datasets to make them comparable. However it can also be used to derive summary fields, such as daily min/max temperature or average precipitation rate. -The Pcp-Combine tool supports four types of commands (“sum”, “add”, “subtract”, and “derive”) which may be run on any gridded data files supported by MET. +The Pcp-Combine tool supports four types of commands ("sum", "add", "subtract", and "derive") which may be run on any gridded data files supported by MET. -1. The “sum” command is the default command and therefore specifying “-sum” on the command line is optional. Using the sum arguments described below, Pcp-Combine searches the input directories (“-pcpdir” option) for data that matches the requested time stamps and accumulation intervals. Pcp-Combine only considers files from the input data directory which match the specified regular expression (“-pcprx” option). While “sum” searches for matching data, all the other commands are run on the explicit set of input files specified. +1. The "sum" command is the default command and therefore specifying "-sum" on the command line is optional. Using the sum arguments described below, Pcp-Combine searches the input directories ("-pcpdir" option) for data that matches the requested time stamps and accumulation intervals. Pcp-Combine only considers files from the input data directory which match the specified regular expression ("-pcprx" option). While "sum" searches for matching data, all the other commands are run on the explicit set of input files specified. -2. The “add” command reads the requested data from the input data files and adds them together. +2. The "add" command reads the requested data from the input data files and adds them together. -3. The “subtract” command reads the requested data from exactly two input files and computes their difference. +3. The "subtract" command reads the requested data from exactly two input files and computes their difference. -4. The “derive” command reads the requested data from the input data files and computes the requested summary fields. +4. The "derive" command reads the requested data from the input data files and computes the requested summary fields. -By default, the Pcp-Combine tool processes data for **APCP**, the GRIB string for accumulated precipitation. When requesting data using time strings (i.e. [HH]MMSS), Pcp-Combine searches for accumulated precipitation for that accumulation interval. Alternatively, use the “-field” option to process fields other than **APCP** or for non-GRIB files. The “-field” option may be used multiple times to process multiple fields in a single run. Since the Pcp-Combine tool does not support automated regridding, all input data must be on the same grid. In general the input files should have the same initialization time unless the user has indicated that it should ignore the initialization time for the “sum” command. The “subtract” command produces a warning when the input initialization times differ or the subtraction results in a negative accumulation interval. +By default, the Pcp-Combine tool processes data for **APCP**, the GRIB string for accumulated precipitation. When requesting data using time strings (i.e. [HH]MMSS), Pcp-Combine searches for accumulated precipitation for that accumulation interval. Alternatively, use the "-field" option to process fields other than **APCP** or for non-GRIB files. The "-field" option may be used multiple times to process multiple fields in a single run. Since the Pcp-Combine tool does not support automated regridding, all input data must be on the same grid. In general the input files should have the same initialization time unless the user has indicated that it should ignore the initialization time for the "sum" command. The "subtract" command produces a warning when the input initialization times differ or the subtraction results in a negative accumulation interval. pcp_combine usage ~~~~~~~~~~~~~~~~~ @@ -82,9 +82,9 @@ Optional arguments for pcp_combine 6. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -7. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +7. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -8. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +8. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. Required arguments for the pcp_combine sum command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -100,14 +100,14 @@ Required arguments for the pcp_combine sum command Optional arguments for pcp_combine sum command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -5. The **-pcpdir path** option indicates the directories in which the input files reside. The contents of “**path**” will override the default setting. This option may be used multiple times and can accept multiple arguments, supporting the use of wildcards. +5. The **-pcpdir path** option indicates the directories in which the input files reside. The contents of "**path**" will override the default setting. This option may be used multiple times and can accept multiple arguments, supporting the use of wildcards. -6. The **-pcprx reg_exp** option indicates the regular expression to be used in matching files in the search directories specified. The contents of “reg_exp” will override the default setting that matches all file names. If the search directories contain a large number of files, the user may specify that only a subset of those files be processed using a regular expression which will speed up the run time. +6. The **-pcprx reg_exp** option indicates the regular expression to be used in matching files in the search directories specified. The contents of "reg_exp" will override the default setting that matches all file names. If the search directories contain a large number of files, the user may specify that only a subset of those files be processed using a regular expression which will speed up the run time. Required arguments for the pcp_combine derive command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -1. The “derive” run command must be followed by **stat_list** which is a comma-separated list of summary fields to be computed. The **stat_list** may be set to sum, min, max, range, mean, stdev, and vld_count for the sum, minimum, maximum, range (max-min), average, standard deviation, and valid data count fields, respectively. +1. The "derive" run command must be followed by **stat_list** which is a comma-separated list of summary fields to be computed. The **stat_list** may be set to sum, min, max, range, mean, stdev, and vld_count for the sum, minimum, maximum, range (max-min), average, standard deviation, and valid data count fields, respectively. Input files for pcp_combine add, subtract, and derive commands ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -116,9 +116,9 @@ The input files for the add, subtract, and derive command can be specified in on 1. Use **file_1 config_str_1 ... file_n config_str_n** to specify the full path to each input file followed by a description of the data to be read from it. The **config_str_i** argument describing the data can be a set to a time string in HH[MMSS] format for accumulated precipitation or a full configuration string. For example, use **'name="TMP"; level="P500";'** to process temperature at 500mb. -2. Use **file_1 ... file_n** to specify the list of input files to be processed on the command line. Rather than specifying a separate configuration string for each input file, the “-field” command line option is required to specify the data to be processed. +2. Use **file_1 ... file_n** to specify the list of input files to be processed on the command line. Rather than specifying a separate configuration string for each input file, the "-field" command line option is required to specify the data to be processed. -3. Use **input_file_list** to specify the name of an ASCII file which contains the paths for the gridded data files to be processed. As in the previous option, the “-field” command line option is required to specify the data to be processed. +3. Use **input_file_list** to specify the name of an ASCII file which contains the paths for the gridded data files to be processed. As in the previous option, the "-field" command line option is required to specify the data to be processed. An example of the pcp_combine calling sequence is presented below: @@ -260,7 +260,7 @@ Optional arguments for regrid_data_plane 12. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -13. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +13. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. 14. The **-compress level** option specifies the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. @@ -337,9 +337,9 @@ Optional arguments for shift_data_plane 9. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -10. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +10. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -11. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +11. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. For more details on setting the **-method** and **-width** options, see the **regrid** entry in :numref:`config_options`. An example of the shift_data_plane calling sequence is shown below: @@ -402,7 +402,7 @@ Optional arguments for modis_regrid 8. The **-units text** option specifies the units string in the global attributes section of the output file. -9. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +9. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the modis_regrid calling sequence is shown below: @@ -462,7 +462,7 @@ Optional arguments for wwmca_plot 4. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -5. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. +5. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. .. figure:: figure/reformat_grid_fig2.png @@ -502,11 +502,11 @@ Optional arguments for wwmca_regrid 5. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -6. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. +6. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. -7. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +7. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. -In any regridding problem, there are two grids involved: the “From” grid, which is the grid the input data are on, and the “To” grid, which is the grid the data are to be moved onto. In **WWMCA-Regrid** the “From” grid is pre-defined by the hemisphere of the WWMCA binary files being processed. The “To” grid and corresponding regridding logic are specified using the **regrid** section of the configuration file. If the “To” grid is entirely confined to one hemisphere, then only the WWMCA data file for that hemisphere needs to be given. If the “To” grid or the interpolation box used straddles the equator, the data files for both hemispheres need to be given. Once the “To” grid is specified in the config file, the WWMCA-Regrid tool will know which input data files it needs and will complain if it is not given the right ones. +In any regridding problem, there are two grids involved: the "From" grid, which is the grid the input data are on, and the "To" grid, which is the grid the data are to be moved onto. In **WWMCA-Regrid** the "From" grid is pre-defined by the hemisphere of the WWMCA binary files being processed. The "To" grid and corresponding regridding logic are specified using the **regrid** section of the configuration file. If the "To" grid is entirely confined to one hemisphere, then only the WWMCA data file for that hemisphere needs to be given. If the "To" grid or the interpolation box used straddles the equator, the data files for both hemispheres need to be given. Once the "To" grid is specified in the config file, the WWMCA-Regrid tool will know which input data files it needs and will complain if it is not given the right ones. wwmca_regrid configuration file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/met/docs/Users_Guide/reformat_point.rst b/met/docs/Users_Guide/reformat_point.rst index f872a12b40..999393b72d 100644 --- a/met/docs/Users_Guide/reformat_point.rst +++ b/met/docs/Users_Guide/reformat_point.rst @@ -61,10 +61,10 @@ The **-valid_beg** time option in YYYYMMDD[_HH[MMSS]] format sets the beginning The **-valid_end** time option in YYYYMMDD[_HH[MMSS]] format sets the end of the retention time window. 4. -The **-nmsg num_messages** option may be used for testing purposes. This argument indicates that only the first “num_messages” PrepBUFR messages should be processed rather than the whole file. This option is provided to speed up testing because running the PB2NC tool can take a few minutes for each file. Most users will not need this option. +The **-nmsg num_messages** option may be used for testing purposes. This argument indicates that only the first "num_messages" PrepBUFR messages should be processed rather than the whole file. This option is provided to speed up testing because running the PB2NC tool can take a few minutes for each file. Most users will not need this option. 5. -The **-dump path** option may be used to dump the entire contents of the PrepBUFR file to several ASCII files written to the directory specified by “path”. The user may use this option to view a human-readable version of the input PrepBUFR file, although writing the contents to ASCII files can be slow. +The **-dump path** option may be used to dump the entire contents of the PrepBUFR file to several ASCII files written to the directory specified by "path". The user may use this option to view a human-readable version of the input PrepBUFR file, although writing the contents to ASCII files can be slow. 6. The **-index** option shows the available variables with valid data from the BUFR input. It collects the available variable list from BUFR input and checks the existence of valid data and directs the variable names with valid data to the screen. The NetCDF output won't be generated. @@ -73,10 +73,10 @@ The **-index** option shows the available variables with valid data from the BUF The **-log** file option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. 8. -The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. 9. -The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the pb2nc calling sequence is shown below: @@ -99,7 +99,7 @@ When editing configuration files, environment variables may be used for setting For example, using an environment variable to set the **message_type** (see below) parameter to use ADPUPA and ADPSFC message types might consist of the following: -\* In a C-Shell: **setenv MSG_TYP ' “ADPUPA”, “ADPSFC” '** +\* In a C-Shell: **setenv MSG_TYP ' "ADPUPA", "ADPSFC" '** \* In the configuration file: **message_type = [ ${MSG_TYP} ];** @@ -128,7 +128,7 @@ ___________________ .. code-block:: none - message_type_map = [ { key = “AIRCAR”; val = “AIRCAR_PROFILES”; } ]; + message_type_map = [ { key = "AIRCAR"; val = "AIRCAR_PROFILES"; } ]; The **message_type_map** entry is an array of dictionaries, each containing a **key** string and **val** string. This defines a mapping of input PrepBUFR message types to output message types. This provides a method for renaming input PrepBUFR message types. @@ -293,7 +293,7 @@ ___________________ The **time_summary** dictionary enables additional processing for observations with high temporal resolution. The **flag** entry toggles the **time_summary** on (**TRUE**) and off (**FALSE**). If the **raw_data** flag is set to TRUE, then both the individual observation values and the derived time summary value will be written to the output. If FALSE, only the summary values are written. Observations may be summarized across the user specified time period defined by the **beg** and **end** entries in HHMMSS format. The **step** entry defines the time between intervals in seconds. The **width** entry specifies the summary interval in seconds. It may either be set as an integer number of seconds for a centered time interval or a dictionary with beginning and ending time offsets in seconds. -This example listed above does a 10-minute time summary (width = 600;) every 5 minutes (step = 300;) throughout the day (beg = “000000”; end = 235959”;). The first interval will be from 23:55:00 the previous day through 00:04:59 of the current day. The second interval will be from 0:00:00 through 00:09:59. And so on. +This example listed above does a 10-minute time summary (width = 600;) every 5 minutes (step = 300;) throughout the day (beg = "000000"; end = 235959";). The first interval will be from 23:55:00 the previous day through 00:04:59 of the current day. The second interval will be from 0:00:00 through 00:09:59. And so on. The two **width** settings listed above are equivalent. Both define a centered 10-minute time interval. Use the **beg** and **end** entries to define uncentered time intervals. The following example requests observations for one hour prior: @@ -422,7 +422,7 @@ This section describes how to run the ASCII2NC tool. The ASCII2NC tool is used t Initial versions of the ASCII2NC tool supported only a simple 11 column ASCII point observation format. It currently supports point observation data in the following formats: the default 11 column format, little_r format, `SURFace RADiation (SURFRAD) `_ and Integrated Surface Irradiance Study (ISIS) formats, the Western Wind and Solar Integration Study (WWSIS) format, and the `AErosol RObotic NEtwork (AERONET) versions 2 and 3 format. `_ WWSIS data are available by request from National Renewable Energy Laboratory (NREL) in Boulder, CO. -MET version 9.0 adds support for the passing observations to ascii2nc using a Python script with the “-format python” option. An example of running ASCII2NC with Python embedding is included below. +MET version 9.0 adds support for the passing observations to ascii2nc using a Python script with the "-format python" option. An example of running ASCII2NC with Python embedding is included below. The default ASCII point observation format consists of one row of data per observation value. Each row of data consists of 11 columns as shown in :numref:`table_reform-point_ascii2nc_format`. @@ -496,14 +496,14 @@ ascii2nc has two required arguments and can take several optional ones. Required arguments for ascii2nc ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -1. The **ascii_file** argument is the ASCII point observation file(s) to be processed. If using Python embedding with “-format python” provides a quoted string containing the Python script to be run followed by any command line arguments that script takes. +1. The **ascii_file** argument is the ASCII point observation file(s) to be processed. If using Python embedding with "-format python" provides a quoted string containing the Python script to be run followed by any command line arguments that script takes. 2. The **netcdf_file** argument is the NetCDF output file to be written. Optional arguments for ascii2nc ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -3. The **-format ASCII_format** option may be set to “met_point”, “little_r”, “surfrad”, “wwsis”, “aeronet”, “aeronetv2”, “aeronetv3”, or “python”. If passing in ISIS data, use the “surfrad” format flag. +3. The **-format ASCII_format** option may be set to "met_point", "little_r", "surfrad", "wwsis", "aeronet", "aeronetv2", "aeronetv3", or "python". If passing in ISIS data, use the "surfrad" format flag. 4. The **-config file** option is the configuration file for generating time summaries. @@ -511,13 +511,13 @@ Optional arguments for ascii2nc 6. The **-mask_poly** file option is a polyline masking file to filter the point observations spatially. -7. The **-mask_sid** file|list option is a station ID masking file or a comma-separated list of station ID's to filter the point observations spatially. See the description of the “sid” entry in :numref:`config_options`. +7. The **-mask_sid** file|list option is a station ID masking file or a comma-separated list of station ID's to filter the point observations spatially. See the description of the "sid" entry in :numref:`config_options`. 8. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -9. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +9. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -10. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +10. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the ascii2nc calling sequence is shown below: @@ -538,7 +538,7 @@ Here is an example of processing the same set of observations but using Python e .. code-block:: none ascii2nc -format python \ - “MET_BASE/python/read_ascii_point.py sample_ascii_obs.txt" \ + "MET_BASE/python/read_ascii_point.py sample_ascii_obs.txt" \ sample_ascii_obs_python.nc Please refer to :numref:`Appendix F, Section %s ` for more details about Python embedding in MET. @@ -592,7 +592,7 @@ ascii2nc output The NetCDF output of the ASCII2NC tool is structured in the same way as the output of the PB2NC tool described in :numref:`pb2nc output`. -“obs_vid” variable is replaced with “obs_gc” when the GRIB code is given instead of the variable names. In this case, the global variable “use_var_id” does not exist or set to false (use_var_id = "false" ;). Three variables (obs_var, obs_units, and obs_desc) related with variable names are not added. +"obs_vid" variable is replaced with "obs_gc" when the GRIB code is given instead of the variable names. In this case, the global variable "use_var_id" does not exist or set to false (use_var_id = "false" ;). Three variables (obs_var, obs_units, and obs_desc) related with variable names are not added. MADIS2NC tool @@ -662,13 +662,13 @@ Optional arguments for madis2nc 9. The **-mask_poly file** option defines a polyline masking file for filtering the point observations spatially. -10. The **-mask_sid file|list** option is a station ID masking file or a comma-separated list of station ID's for filtering the point observations spatially. See the description of the “sid” entry in :numref:`config_options`. +10. The **-mask_sid file|list** option is a station ID masking file or a comma-separated list of station ID's for filtering the point observations spatially. See the description of the "sid" entry in :numref:`config_options`. 11. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -12. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. +12. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. 13. The **-compress level** option specifies the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. @@ -720,7 +720,7 @@ madis2nc output The NetCDF output of the MADIS2NC tool is structured in the same way as the output of the PB2NC tool described in :numref:`pb2nc output`. -“obs_vid” variable is replaced with “obs_gc” when the GRIB code is given instead of the variable names. In this case, the global variable “use_var_id” does not exist or set to false (use_var_id = "false" ;). Three variables (obs_var, obs_units, and obs_desc) related with variable names are not added. +"obs_vid" variable is replaced with "obs_gc" when the GRIB code is given instead of the variable names. In this case, the global variable "use_var_id" does not exist or set to false (use_var_id = "false" ;). Three variables (obs_var, obs_units, and obs_desc) related with variable names are not added. LIDAR2NC tool @@ -762,9 +762,9 @@ Optional arguments for lidar2nc 3. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -4. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +4. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -5. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +5. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. lidar2nc output ~~~~~~~~~~~~~~~ @@ -889,9 +889,9 @@ Optional arguments for ioda2nc 8. The **-log** file option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -9. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +9. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -10. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +10. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the ioda2nc calling sequence is shown below: @@ -1017,7 +1017,7 @@ Required arguments for point2grid 3. The **output_filename** argument is the name of the output NetCDF file to be written. -4. The **-field** string argument is a string that defines the data to be regridded. It may be used multiple times. If **-adp** option is given (for AOD data from GOES16/17), the name consists with the variable name from the input data file and the variable name from ADP data file (for example, “AOD_Smoke” or “AOD_Dust”: getting AOD variable from the input data and applying smoke or dust variable from ADP data file). +4. The **-field** string argument is a string that defines the data to be regridded. It may be used multiple times. If **-adp** option is given (for AOD data from GOES16/17), the name consists with the variable name from the input data file and the variable name from ADP data file (for example, "AOD_Smoke" or "AOD_Dust": getting AOD variable from the input data and applying smoke or dust variable from ADP data file). Optional arguments for point2grid @@ -1025,9 +1025,9 @@ Optional arguments for point2grid 5. The **-config** file option is the configuration file to be used. -6. The **-qc** flags option specifies a comma-separated list of quality control (QC) flags, for example “0,1”. This should only be applied if grid_mapping is set to “goes_imager_projection” and the QC variable exists. +6. The **-qc** flags option specifies a comma-separated list of quality control (QC) flags, for example "0,1". This should only be applied if grid_mapping is set to "goes_imager_projection" and the QC variable exists. -7. The **-adp adp_file_name** option provides an additional Aerosol Detection Product (ADP) information on aerosols, dust, and smoke. This option is ignored if the requested variable is not AOD (“AOD_Dust” or “AOD_Smoke”) from GOES16/17. The gridded data is filtered by the presence of dust/smoke. If -qc options are given, it's applied to QC of dust/smoke, too (First filtering with AOD QC values and the second filtering with dust/smoke QC values). +7. The **-adp adp_file_name** option provides an additional Aerosol Detection Product (ADP) information on aerosols, dust, and smoke. This option is ignored if the requested variable is not AOD ("AOD_Dust" or "AOD_Smoke") from GOES16/17. The gridded data is filtered by the presence of dust/smoke. If -qc options are given, it's applied to QC of dust/smoke, too (First filtering with AOD QC values and the second filtering with dust/smoke QC values). 8. The **-method type** option specifies the regridding method. The default method is UW_MEAN. @@ -1043,9 +1043,9 @@ Optional arguments for point2grid 14. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -15. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +15. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -16. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +16. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. Only 4 interpolation methods are applied to the field variables; MIN/MAX/MEDIAN/UW_MEAN. The GAUSSIAN method is applied to the probability variable only. Unlike regrad_data_plane, MAX method is applied to the file variable and Gaussian method to the probability variable with the MAXGAUSS method. If the probability variable is not requested, MAXGAUSS method is the same as MAX method. @@ -1083,13 +1083,13 @@ The point2grid tool will output a gridded NetCDF file containing the following: 4. The count field which represents the number of point observations that were included calculating the value of the variable at that grid cell. -5. The mask field which is a binary field representing the presence or lack thereof of point observations at that grid cell. A value of “1” indicates that there was at least one point observation within the bounds of that grid cell and a value of “0” indicates the lack of point observations at that grid cell. +5. The mask field which is a binary field representing the presence or lack thereof of point observations at that grid cell. A value of "1" indicates that there was at least one point observation within the bounds of that grid cell and a value of "0" indicates the lack of point observations at that grid cell. 6. The probability field which is the probability of the event defined by the **-prob_cat_thresh** command line option. The output variable name includes the threshold used to define the probability. Ranges from 0 to 1. -7. The probability mask field which is a binary field that represents whether or not there is probability data at that grid point. Can be either “0” or “1” with “0” meaning the probability value does not exist and a value of “1” meaning that the probability value does exist. +7. The probability mask field which is a binary field that represents whether or not there is probability data at that grid point. Can be either "0" or "1" with "0" meaning the probability value does not exist and a value of "1" meaning that the probability value does exist. For MET observation input and CF complaint NetCDF input with 2D time variable: The latest observation time within the target grid is saved as the observation time. If the "valid_time" is configured at the configuration file, the valid_time from the configuration file is saved into the output file. diff --git a/met/docs/Users_Guide/refs.rst b/met/docs/Users_Guide/refs.rst index a039a91ab8..a58ddf8dda 100644 --- a/met/docs/Users_Guide/refs.rst +++ b/met/docs/Users_Guide/refs.rst @@ -13,7 +13,7 @@ References | Barker, T. W., 1991: The relationship between spread and forecast error in -| extended-range forecasts. *Journal of Climate*, 4, 733–742. +| extended-range forecasts. *Journal of Climate*, 4, 733-742. | .. _Bradley-2008: @@ -27,7 +27,7 @@ References | Brill, K. F., and F. Mesinger, 2009: Applying a general analytic method | for assessing bias sensitivity to bias-adjusted threat and equitable -| threat scores. *Weather and Forecasting*, 24, 1748–1754. +| threat scores. *Weather and Forecasting*, 24, 1748-1754. | .. _Brown-2007: @@ -45,7 +45,7 @@ References | Buizza, R., 1997: Potential forecast skill of ensemble prediction and spread | and skill distributions of the ECMWF ensemble prediction system. *Monthly* -| *Weather Review*,125, 99–119. +| *Weather Review*,125, 99-119. | .. _Bullock-2016: @@ -58,7 +58,7 @@ References | Candille, G., and O. Talagrand, 2008: Impact of observational error on the | validation of ensemble prediction systems. *Quarterly Journal of the Royal* -| *Meteorological Society* 134: 959–971. +| *Meteorological Society* 134: 959-971. | .. _Casati-2004: @@ -153,9 +153,9 @@ References .. _Mason-2004: -| Mason, S. J., 2004: On Using “Climatology” as a Reference Strategy +| Mason, S. J., 2004: On Using "Climatology" as a Reference Strategy | in the Brier and Ranked Probability Skill Scores. *Monthly Weather Review*, -| 132, 1891–1895. +| 132, 1891-1895. | .. _Mittermaier-2014: @@ -166,7 +166,7 @@ References .. _Mood-1974: -| Mood, A. M., F. A. Graybill and D. C. Boes, 1974: *Introduction to the* +| Mood, A. M., F. A. Graybill and D. C. Boes, 1974: *Introduction to the* | *Theory of Statistics*, McGraw-Hill, 299-338. | @@ -194,14 +194,14 @@ References | Saetra O., H. Hersbach, J-R Bidlot, D. Richardson, 2004: Effects of | observation errors on the statistics for ensemble spread and -| reliability. *Monthly Weather Review* 132: 1487–1501. +| reliability. *Monthly Weather Review* 132: 1487-1501. | .. _Santos-2012: | Santos C. and A. Ghelli, 2012: Observational probability method to assess | ensemble precipitation forecasts. *Quarterly Journal of the Royal* -| *Meteorological Society* 138: 209–221. +| *Meteorological Society* 138: 209-221. | .. _Schwartz-2017: @@ -213,7 +213,7 @@ References .. _Stephenson-2000: -| Stephenson, D.B., 2000: Use of the “Odds Ratio” for diagnosing +| Stephenson, D.B., 2000: Use of the "Odds Ratio" for diagnosing | forecast skill. *Weather and Forecasting*, 15, 221-232. | @@ -235,7 +235,7 @@ References | Wilks, D.S. 2010: Sampling distributions of the Brier score and Brier skill | score under serial dependence. *Quarterly Journal of the Royal* -| *Meteorological Society,*, 136, 2109–2118. doi:10.1002/qj.709 +| *Meteorological Society,*, 136, 2109-2118. doi:10.1002/qj.709 | .. _Wilks-2011: diff --git a/met/docs/Users_Guide/rmw-analysis.rst b/met/docs/Users_Guide/rmw-analysis.rst index c7247446f5..9ae27fe82f 100644 --- a/met/docs/Users_Guide/rmw-analysis.rst +++ b/met/docs/Users_Guide/rmw-analysis.rst @@ -43,7 +43,7 @@ Optional arguments for rmw_analysis 4. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no logfile. -5. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +5. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. rmw_analysis configuration file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/met/docs/Users_Guide/series-analysis.rst b/met/docs/Users_Guide/series-analysis.rst index 26e7e200ea..bc9095dbf1 100644 --- a/met/docs/Users_Guide/series-analysis.rst +++ b/met/docs/Users_Guide/series-analysis.rst @@ -63,7 +63,7 @@ Optional arguments for series_analysis 8. The -v level overrides the default level of logging (2). -9. The -compress level option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +9. The -compress level option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the series_analysis calling sequence is shown below: diff --git a/met/docs/Users_Guide/stat-analysis.rst b/met/docs/Users_Guide/stat-analysis.rst index d12ae5746a..2267f7ba03 100644 --- a/met/docs/Users_Guide/stat-analysis.rst +++ b/met/docs/Users_Guide/stat-analysis.rst @@ -8,23 +8,23 @@ ____________ The Stat-Analysis tool ties together results from the Point-Stat, Grid-Stat, Ensemble-Stat, Wavelet-Stat, and TC-Gen tools by providing summary statistical information and a way to filter their STAT output files. It processes the STAT output created by the other MET tools in a variety of ways which are described in this section. -MET version 9.0 adds support for the passing matched pair data (MPR) into Stat-Analysis using a Python script with the “-lookin python ...” option. An example of running Stat-Analysis with Python embedding is shown in :numref:`stat_analysis-usage`. +MET version 9.0 adds support for the passing matched pair data (MPR) into Stat-Analysis using a Python script with the "-lookin python ..." option. An example of running Stat-Analysis with Python embedding is shown in :numref:`stat_analysis-usage`. Scientific and statistical aspects __________________________________ -The Stat-Analysis tool can perform a variety of analyses, and each type of analysis is called a “job”. The job types include the ability to (i) aggregate results over a user-specified time; (ii) stratify statistics based on time of day, model initialization time, lead-time, model run identifier, output filename, or wavelet decomposition scale; and (iii) compute specific verification indices such as the GO Index [1]_ +The Stat-Analysis tool can perform a variety of analyses, and each type of analysis is called a "job". The job types include the ability to (i) aggregate results over a user-specified time; (ii) stratify statistics based on time of day, model initialization time, lead-time, model run identifier, output filename, or wavelet decomposition scale; and (iii) compute specific verification indices such as the GO Index [1]_ and wind direction statistics. Future functionality may include information about time-trends and/or calculations based on climatology (e.g., anomaly correlation). This section summarizes the capabilities of the supported Stat-Analysis jobs. Filter STAT lines ~~~~~~~~~~~~~~~~~ -The Stat-Analysis “filter” job simply filters out specific STAT lines based on user-specified search criteria. All of the STAT lines that are retained from one or many files are written to a single output file. The output file for filtered STAT lines must be specified using the **-dump_row** job command option. +The Stat-Analysis "filter" job simply filters out specific STAT lines based on user-specified search criteria. All of the STAT lines that are retained from one or many files are written to a single output file. The output file for filtered STAT lines must be specified using the **-dump_row** job command option. Summary statistics for columns ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The Stat-Analysis “summary” job produces summary information for columns of data. After the user specifies the column(s) of interest and any other relevant search criteria, summary information is produced from values in those column(s) of data. The summary statistics produced are: mean, standard deviation, minimum, maximum, the 10th, 25th, 50th, 75th, and 90th percentiles, the interquartile range, the range, and both weighted and unweighted means using the logic prescribed by the World Meteorological Organization (WMO). +The Stat-Analysis "summary" job produces summary information for columns of data. After the user specifies the column(s) of interest and any other relevant search criteria, summary information is produced from values in those column(s) of data. The summary statistics produced are: mean, standard deviation, minimum, maximum, the 10th, 25th, 50th, 75th, and 90th percentiles, the interquartile range, the range, and both weighted and unweighted means using the logic prescribed by the World Meteorological Organization (WMO). Confidence intervals are computed for the mean and standard deviation of the column of data. For the mean, the confidence interval is computed two ways - based on an assumption of normality and also using the bootstrap method. For the standard deviation, the confidence interval is computed using the bootstrap method. In this application of the bootstrap method, the values in the column of data being summarized are resampled, and for each replicated sample, the mean and standard deviation are computed. @@ -39,14 +39,14 @@ The **-derive** job command option can be used to perform the derivation of stat Aggregated values from multiple STAT lines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The Stat-Analysis “aggregate” job aggregates values from multiple STAT lines of the same type. The user may specify the specific line type of interest and any other relevant search criteria. The Stat-Analysis tool then creates sums of each of the values in all lines matching the search criteria. The aggregated data are output as the same line type as the user specified. The STAT line types which may be aggregated in this way are the contingency table (FHO, CTC, PCT, MCTC, NBRCTC), partial sums (SL1L2, SAL1L2, VL1L2, and VAL1L2), and other (ISC, ECNT, RPS, RHIST, PHIST, RELP, NBRCNT, SSVAR, and GRAD) line types. +The Stat-Analysis "aggregate" job aggregates values from multiple STAT lines of the same type. The user may specify the specific line type of interest and any other relevant search criteria. The Stat-Analysis tool then creates sums of each of the values in all lines matching the search criteria. The aggregated data are output as the same line type as the user specified. The STAT line types which may be aggregated in this way are the contingency table (FHO, CTC, PCT, MCTC, NBRCTC), partial sums (SL1L2, SAL1L2, VL1L2, and VAL1L2), and other (ISC, ECNT, RPS, RHIST, PHIST, RELP, NBRCNT, SSVAR, and GRAD) line types. Aggregate STAT lines and produce aggregated statistics ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The Stat-Analysis “aggregate-stat” job aggregates multiple STAT lines of the same type together and produces relevant statistics from the aggregated line. This may be done in the same manner listed above in :numref:`StA_Aggregated-values-from`. However, rather than writing out the aggregated STAT line itself, the relevant statistics generated from that aggregated line are provided in the output. Specifically, if a contingency table line type (FHO, CTC, PCT, MCTC, or NBRCTC) has been aggregated, contingency table statistics (CTS, ECLV, PSTD, MCTS, or NBRCTS) line types can be computed. If a partial sums line type (SL1L2 or SAL1L2) has been aggregated, the continuous statistics (CNT) line type can be computed. If a vector partial sums line type (VL1L2) has been aggregated, the vector continuous statistics (VCNT) line type can be computed. For ensembles, the ORANK line type can be accumulated into ECNT, RPS, RHIST, PHIST, RELP, or SSVAR output. If the matched pair line type (MPR) has been aggregated, may output line types (FHO, CTC, CTS, CNT, MCTC, MCTS, SL1L2, SAL1L2, VL1L2, VCNT, WDIR, PCT, PSTD, PJC, PRC, or ECLV) can be computed. Multiple output line types may be specified for each “aggregate-stat” job, as long as each output is derivable from the input. +The Stat-Analysis "aggregate-stat" job aggregates multiple STAT lines of the same type together and produces relevant statistics from the aggregated line. This may be done in the same manner listed above in :numref:`StA_Aggregated-values-from`. However, rather than writing out the aggregated STAT line itself, the relevant statistics generated from that aggregated line are provided in the output. Specifically, if a contingency table line type (FHO, CTC, PCT, MCTC, or NBRCTC) has been aggregated, contingency table statistics (CTS, ECLV, PSTD, MCTS, or NBRCTS) line types can be computed. If a partial sums line type (SL1L2 or SAL1L2) has been aggregated, the continuous statistics (CNT) line type can be computed. If a vector partial sums line type (VL1L2) has been aggregated, the vector continuous statistics (VCNT) line type can be computed. For ensembles, the ORANK line type can be accumulated into ECNT, RPS, RHIST, PHIST, RELP, or SSVAR output. If the matched pair line type (MPR) has been aggregated, may output line types (FHO, CTC, CTS, CNT, MCTC, MCTS, SL1L2, SAL1L2, VL1L2, VCNT, WDIR, PCT, PSTD, PJC, PRC, or ECLV) can be computed. Multiple output line types may be specified for each "aggregate-stat" job, as long as each output is derivable from the input. -When aggregating the matched pair line type (MPR), additional required job command options are determined by the requested output line type(s). For example, the “-out_thresh” (or “-out_fcst_thresh” and “-out_obs_thresh” options) are required to compute contingnecy table counts (FHO, CTC) or statistics (CTS). Those same job command options can also specify filtering thresholds when computing continuous partial sums (SL1L2, SAL1L2) or statistics (CNT). Output is written for each threshold specified. +When aggregating the matched pair line type (MPR), additional required job command options are determined by the requested output line type(s). For example, the "-out_thresh" (or "-out_fcst_thresh" and "-out_obs_thresh" options) are required to compute contingnecy table counts (FHO, CTC) or statistics (CTS). Those same job command options can also specify filtering thresholds when computing continuous partial sums (SL1L2, SAL1L2) or statistics (CNT). Output is written for each threshold specified. When aggregating the matched pair line type (MPR) and computing an output contingency table statistics (CTS) or continuous statistics (CNT) line type, the bootstrapping method can be applied to compute confidence intervals. The bootstrapping method is applied here in the same way that it is applied in the statistics tools. For a set of n matched forecast-observation pairs, the matched pairs are resampled with replacement many times. For each replicated sample, the corresponding statistics are computed. The confidence intervals are derived from the statistics computed for each replicated sample. @@ -55,7 +55,7 @@ When aggregating the matched pair line type (MPR) and computing an output contin Skill Score Index, including GO Index ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The Stat-Analysis “ss_index” and “go_index” jobs calculate the skill score indices by weighting scores for different meteorological fields at different pressure levels and for different lead times. The GO Index is a special case of the Skill Score index for which a specific configuration file is provided. The GO index is a weighted average of the RMSE values for wind speed, dew point temperature, temperature, height, and pressure at several levels in the atmosphere. The variables, levels, and lead times included in the index are shown in :numref:`compute_GO_Index` and are defined by a default Stat-Analysis configuration file. The partial sums (SL1L2 lines in the STAT output) for each of these variables at each level and lead time must have been computed in a previous step. The Stat-Analysis tool then uses the weights in :numref:`compute_GO_Index` to compute values for the GO Index. For a general skill score index, the user can specify the weights and variables to use in the calculations in a Stat-Analysis configuration file and run the ss_index job type. +The Stat-Analysis "ss_index" and "go_index" jobs calculate the skill score indices by weighting scores for different meteorological fields at different pressure levels and for different lead times. The GO Index is a special case of the Skill Score index for which a specific configuration file is provided. The GO index is a weighted average of the RMSE values for wind speed, dew point temperature, temperature, height, and pressure at several levels in the atmosphere. The variables, levels, and lead times included in the index are shown in :numref:`compute_GO_Index` and are defined by a default Stat-Analysis configuration file. The partial sums (SL1L2 lines in the STAT output) for each of these variables at each level and lead time must have been computed in a previous step. The Stat-Analysis tool then uses the weights in :numref:`compute_GO_Index` to compute values for the GO Index. For a general skill score index, the user can specify the weights and variables to use in the calculations in a Stat-Analysis configuration file and run the ss_index job type. .. _compute_GO_Index: @@ -151,12 +151,12 @@ The Stat-Analysis “ss_index” and “go_index” jobs calculate the skill sco Ramp Events ~~~~~~~~~~~ -The Stat-Analysis “ramp” job identifies ramp events (large increases or decreases in values over a time window) in both the forecast and observation data. It categorizes these events as hits, misses, false alarms, or correct negatives by applying a configurable matching time window and computes the corresponding categorical statistics. +The Stat-Analysis "ramp" job identifies ramp events (large increases or decreases in values over a time window) in both the forecast and observation data. It categorizes these events as hits, misses, false alarms, or correct negatives by applying a configurable matching time window and computes the corresponding categorical statistics. Wind Direction Statistics ~~~~~~~~~~~~~~~~~~~~~~~~~ -The Stat-Analysis “aggregate_stat” job can read vector partial sums and derive wind direction error statistics (WDIR). The vector partial sums (VL1L2 or VAL1L2) or matched pairs (MPR) for the UGRD and VGRD must have been computed in a previous step, i.e. by Point-Stat or Grid-Stat tools. This job computes an average forecast wind direction and an average observed wind direction along with their difference. The output is in degrees. In Point-Stat and Grid-Stat, the UGRD and VGRD can be verified using thresholds on their values or on the calculated wind speed. If thresholds have been applied, the wind direction statistics are calculated for each threshold. +The Stat-Analysis "aggregate_stat" job can read vector partial sums and derive wind direction error statistics (WDIR). The vector partial sums (VL1L2 or VAL1L2) or matched pairs (MPR) for the UGRD and VGRD must have been computed in a previous step, i.e. by Point-Stat or Grid-Stat tools. This job computes an average forecast wind direction and an average observed wind direction along with their difference. The output is in degrees. In Point-Stat and Grid-Stat, the UGRD and VGRD can be verified using thresholds on their values or on the calculated wind speed. If thresholds have been applied, the wind direction statistics are calculated for each threshold. The first step in verifying wind direction is running the Grid-Stat and/or Point-Stat tools to verify each forecast of interest and generate the VL1L2 or MPR line(s). When running these tools, please note: @@ -203,7 +203,7 @@ In the usage statement for the Stat-Analysis tool, some additional terminology i Required arguments for stat_analysis ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -1. The **-lookin path** specifies the name of a directory to be searched recursively for STAT files (ending in “.stat”) or any explicit file name with any suffix (such as “_ctc.txt”) to be read. This option may be used multiple times to specify multiple directories and/or files to be read. If “-lookin python” is used, it must be followed by a Python embedding script and any command line arguments it takes. Python embedding can be used to pass matched pair (MPR) lines as input to Stat-Analysis. +1. The **-lookin path** specifies the name of a directory to be searched recursively for STAT files (ending in ".stat") or any explicit file name with any suffix (such as "_ctc.txt") to be read. This option may be used multiple times to specify multiple directories and/or files to be read. If "-lookin python" is used, it must be followed by a Python embedding script and any command line arguments it takes. Python embedding can be used to pass matched pair (MPR) lines as input to Stat-Analysis. 2. Either a configuration file must be specified with the **-config** option, or a **JOB COMMAND LINE** must be denoted. The **JOB COMMAND LINE** is described in :numref:`stat_analysis-configuration-file` @@ -553,9 +553,9 @@ This option specifies the desired output line type(s) for the **aggregate_stat** The Stat-Analysis tool writes its output to either the log file or the file specified using the **-out** command line option. However the **aggregate** and **aggregate_stat** jobs create STAT output lines and the standard output written lacks the full set of STAT header columns. The **-out_stat** job command option may be used for these jobs to specify the name of an output file to which full STAT output lines should be written. When the **-out_stat** job command option is used for **aggregate** and **aggregate_stat** jobs the output is sent to the **-out_stat** file instead of the log or **-out** file. -Jobs will often combine output with multiple entries in the header columns. For example, a job may aggregate output with three different values in the **VX_MASK** column, such as “mask1”, “mask2”, and “mask3”. The output **VX_MASK** column will contain the unique values encountered concatenated together with commas: “mask1,mask2,mask3”. Alternatively, the **-set_hdr** option may be used to specify what should be written to the output header columns, such as “-set_hdr VX_MASK all_three_masks”. +Jobs will often combine output with multiple entries in the header columns. For example, a job may aggregate output with three different values in the **VX_MASK** column, such as "mask1", "mask2", and "mask3". The output **VX_MASK** column will contain the unique values encountered concatenated together with commas: "mask1,mask2,mask3". Alternatively, the **-set_hdr** option may be used to specify what should be written to the output header columns, such as "-set_hdr VX_MASK all_three_masks". -When using the “-out_stat” option to create a .stat output file and stratifying results using one or more “-by” job command options, those columns may be referenced in the “-set_hdr” option. When using multiple “-by” options, use “CASE” to reference the full case information string: +When using the "-out_stat" option to create a .stat output file and stratifying results using one or more "-by" job command options, those columns may be referenced in the "-set_hdr" option. When using multiple "-by" options, use "CASE" to reference the full case information string: .. code-block:: none @@ -570,7 +570,7 @@ The example above reads MPR lines, stratifies the data by forecast variable name -mask_poly file -mask_sid file|list -When processing input MPR lines, these options may be used to define a masking grid, polyline, or list of station ID's to filter the matched pair data geographically prior to computing statistics. The **-mask_sid** option is a station ID masking file or a comma-separated list of station ID's for filtering the matched pairs spatially. See the description of the “sid” entry in :numref:`config_options`. +When processing input MPR lines, these options may be used to define a masking grid, polyline, or list of station ID's to filter the matched pair data geographically prior to computing statistics. The **-mask_sid** option is a station ID masking file or a comma-separated list of station ID's for filtering the matched pairs spatially. See the description of the "sid" entry in :numref:`config_options`. .. code-block:: none diff --git a/met/docs/Users_Guide/tc-dland.rst b/met/docs/Users_Guide/tc-dland.rst index d902be5569..163c732968 100644 --- a/met/docs/Users_Guide/tc-dland.rst +++ b/met/docs/Users_Guide/tc-dland.rst @@ -58,6 +58,6 @@ Optional arguments for tc_dland 5. The **-log file** argument outputs log messages to the specified file. -6. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +6. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. 7. The **-compress level** option specifies the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. Setting the compression level to 0 will make no compression for the NetCDF output. Lower numbers result in minimal compression and faster I/O processing speed; higher numbers result in better compression, but at the expense of I/O processing speed. diff --git a/met/docs/Users_Guide/tc-gen.rst b/met/docs/Users_Guide/tc-gen.rst index 763c5663b4..61209566dc 100644 --- a/met/docs/Users_Guide/tc-gen.rst +++ b/met/docs/Users_Guide/tc-gen.rst @@ -6,7 +6,7 @@ TC-Gen Tool Introduction ____________ -The TC-Gen tool provides verification of tropical cyclone genesis forecasts in ATCF file format. Producing reliable tropical cyclone genesis forecasts is an important metric for global numerical weather prediction models. This tool ingests deterministic model output post-processed by a genesis tracking software (e.g. GFDL vortex tracker) and ATCF format reference dataset(s) (e.g. Best Track analysis and CARQ operational tracks) and outputs categorical counts and statistics. The capability to modify the spatial and temporal tolerances that define a “hit” forecast is included to give users the ability to condition the criteria based on model performance and/or conduct sensitivity analyses. Statistical aspects are outlined in :numref:`tc-gen_stat_aspects` and practical aspects of the TC-Gen tool are described in :numref:`tc-gen_practical_info`. +The TC-Gen tool provides verification of tropical cyclone genesis forecasts in ATCF file format. Producing reliable tropical cyclone genesis forecasts is an important metric for global numerical weather prediction models. This tool ingests deterministic model output post-processed by a genesis tracking software (e.g. GFDL vortex tracker) and ATCF format reference dataset(s) (e.g. Best Track analysis and CARQ operational tracks) and outputs categorical counts and statistics. The capability to modify the spatial and temporal tolerances that define a "hit" forecast is included to give users the ability to condition the criteria based on model performance and/or conduct sensitivity analyses. Statistical aspects are outlined in :numref:`tc-gen_stat_aspects` and practical aspects of the TC-Gen tool are described in :numref:`tc-gen_practical_info`. .. _tc-gen_stat_aspects: @@ -48,7 +48,7 @@ Required arguments for tc_gen 1. The **-genesis path** argument is the path to one or more ATCF or fort.66 (see documentation listed below) files generated by the Geophysical Fluid Dynamics Laboratory (GFDL) Vortex Tracker when run in tcgen mode or an ASCII file list or a top-level directory containing them. The **-genesis** option must be used at least once. The required file format is described in the "Output formats" section of the `GFDL Vortex Tracker users guide. `_ -2. The **-track path** argument is one or more ATCF reference track files or an ASCII file list or top-level directory containing them, with files ending in “.dat”. This tool processes either Best track data from bdeck files, or operational track data (e.g. CARQ) from adeck files, or both. Providing both bdeck and adeck files will result in a richer dataset to match with the **-genesis** files. Both adeck and bdeck data should be provided using the **-track** option. The **-track** option must be used at least once. +2. The **-track path** argument is one or more ATCF reference track files or an ASCII file list or top-level directory containing them, with files ending in ".dat". This tool processes either Best track data from bdeck files, or operational track data (e.g. CARQ) from adeck files, or both. Providing both bdeck and adeck files will result in a richer dataset to match with the **-genesis** files. Both adeck and bdeck data should be provided using the **-track** option. The **-track** option must be used at least once. 3. The **-config** file argument indicates the name of the configuration file to be used. The contents of the configuration file are discussed below. @@ -59,7 +59,7 @@ Optional arguments for tc_gen 5. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -6. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +6. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. The TC-Gen tool implements the following logic: diff --git a/met/docs/Users_Guide/tc-pairs.rst b/met/docs/Users_Guide/tc-pairs.rst index 24afaf814a..ac0182a97e 100644 --- a/met/docs/Users_Guide/tc-pairs.rst +++ b/met/docs/Users_Guide/tc-pairs.rst @@ -35,11 +35,11 @@ tc_pairs has required arguments and can accept several optional arguments. Required arguments for tc_pairs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -1. The **-adeck source** argument indicates the adeck TC-Pairs acceptable format data source containing tropical cyclone model forecast (output from tracker) data to be verified. Acceptable data formats are limited to the standard ATCF format and the one column modified ATCF file, generated by running the tracker in genesis mode. It specifies the name of a TC-Pairs acceptable format file or top-level directory containing TC-Pairs acceptable format files ending in “.dat” to be processed. The **-adeck** or **-edeck** option must be used at least once. +1. The **-adeck source** argument indicates the adeck TC-Pairs acceptable format data source containing tropical cyclone model forecast (output from tracker) data to be verified. Acceptable data formats are limited to the standard ATCF format and the one column modified ATCF file, generated by running the tracker in genesis mode. It specifies the name of a TC-Pairs acceptable format file or top-level directory containing TC-Pairs acceptable format files ending in ".dat" to be processed. The **-adeck** or **-edeck** option must be used at least once. -2. The **-edeck source** argument indicates the edeck ATCF format data source containing probabilistic track data to be verified. It specifies the name of an ATCF format file or top-level directory containing ATCF format files ending in “.dat” to be processed. The **-adeck** or **-edeck** option must be used at least once. +2. The **-edeck source** argument indicates the edeck ATCF format data source containing probabilistic track data to be verified. It specifies the name of an ATCF format file or top-level directory containing ATCF format files ending in ".dat" to be processed. The **-adeck** or **-edeck** option must be used at least once. -3. The **-bdeck source** argument indicates the TC-Pairs acceptable format data source containing the tropical cyclone reference dataset to be used for verifying the adeck source. This source is typically the NHC Best Track Analysis, but could be any TC-Pairs acceptable formatted reference. The acceptable data formats for bdecks are the same as those for adecks. This argument specifies the name of a TC-Pairs acceptable format file or top-level directory containing TC-Pairs acceptable format files ending in “.dat” to be processed. +3. The **-bdeck source** argument indicates the TC-Pairs acceptable format data source containing the tropical cyclone reference dataset to be used for verifying the adeck source. This source is typically the NHC Best Track Analysis, but could be any TC-Pairs acceptable formatted reference. The acceptable data formats for bdecks are the same as those for adecks. This argument specifies the name of a TC-Pairs acceptable format file or top-level directory containing TC-Pairs acceptable format files ending in ".dat" to be processed. 4. The **-config file** argument indicates the name of the configuration file to be used. The contents of the configuration file are discussed below. @@ -50,7 +50,7 @@ Optional arguments for tc_pairs 6. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -7. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +7. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. This tool currently only supports the rapid intensification (**RI**) edeck probability type but support for additional edeck probability types will be added in future releases. At least one **-adeck** or **-edeck** option must be specified. The **-adeck, -edeck**, and **-bdeck** options may optionally be followed with **suffix=string** to append that string to all model names found within that data source. This option may be useful when processing track data from two different sources which reuse the same model names. @@ -151,7 +151,7 @@ ____________________ .. code-block:: none - lag_time = [ “06”, “12” ]; + lag_time = [ "06", "12" ]; The **lag_time** field is a comma-separated list of forecast lag times to be used in HH[MMSS] format. For each adeck track identified, a lagged track will be derived for each entry. In the tc_pairs output, the original adeck record will be retained, with the lagged entry listed as the adeck name with "_LAG_HH" appended. diff --git a/met/docs/Users_Guide/tc-rmw.rst b/met/docs/Users_Guide/tc-rmw.rst index efe5273c84..852973b0f1 100644 --- a/met/docs/Users_Guide/tc-rmw.rst +++ b/met/docs/Users_Guide/tc-rmw.rst @@ -44,7 +44,7 @@ Optional arguments for tc_rmw 5. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no logfile. -6. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +6. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. tc_rmw configuration file ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/met/docs/Users_Guide/tc-stat.rst b/met/docs/Users_Guide/tc-stat.rst index c66a6f6894..ee774eee0d 100644 --- a/met/docs/Users_Guide/tc-stat.rst +++ b/met/docs/Users_Guide/tc-stat.rst @@ -104,7 +104,7 @@ Optional arguments for tc_stat 4. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -5. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +5. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. 6. The **-config file** argument indicates the name of the configuration file to be used. The contents of the configuration file are discussed below. @@ -396,13 +396,13 @@ This job produces summary statistics for the column name specified by the **-col "COL_NAME", followed by the summary statistics that are applied; 3. -“SUMMARY”, which is followed by the total, mean (with confidence intervals), standard deviation, minimum value, percentiles (10th, 25th, 50th, 75th, 90th), maximum value, interquartile range, range, sum, time to independence, and frequency of superior performance. +"SUMMARY", which is followed by the total, mean (with confidence intervals), standard deviation, minimum value, percentiles (10th, 25th, 50th, 75th, 90th), maximum value, interquartile range, range, sum, time to independence, and frequency of superior performance. The output columns are shown below in :numref:`table_columnar_output_summary_tc_stat` The **-by** option can also be used one or more times to make this job more powerful. Rather than running the specified job once, it will be run once for each unique combination of the entries found in the column(s) specified with the **-by** option. .. _table_columnar_output_summary_tc_stat: -.. list-table:: Columnar output of “summary” job output from the TC-Stat tool. +.. list-table:: Columnar output of "summary" job output from the TC-Stat tool. :widths: auto :header-rows: 2 diff --git a/met/docs/Users_Guide/wavelet-stat.rst b/met/docs/Users_Guide/wavelet-stat.rst index ae26221f34..33bf779692 100644 --- a/met/docs/Users_Guide/wavelet-stat.rst +++ b/met/docs/Users_Guide/wavelet-stat.rst @@ -59,14 +59,14 @@ The Intensity-Scale (IS) skill score evaluates the forecast skill as a function - - Total * - - - o = 1 (e.g., “Yes”) - - o = 0 (e.g., “No”) + - o = 1 (e.g., "Yes") + - o = 0 (e.g., "No") - - * - f = 1 (e.g., “Yes”) + * - f = 1 (e.g., "Yes") - Hits **= a** - False Alarms **= b** - **a+b** - * - f = 0 (e.g., “No”) + * - f = 0 (e.g., "No") - Misses **= c** - Correct rejections **= d** - **c+d** @@ -182,9 +182,9 @@ Optional arguments for wavelet_stat 5. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -6. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. +6. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. -7. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +7. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the wavelet_stat calling sequence is listed below: @@ -217,7 +217,7 @@ _______________________ mask_missing_flag = NONE; met_data_dir = "MET_BASE"; ps_plot_flag = TRUE; - fcst_raw_plot = { color_table = "MET_BASE/colortables/met_default.ctable”; + fcst_raw_plot = { color_table = "MET_BASE/colortables/met_default.ctable"; plot_min = 0.0; plot_max = 0.0; } obs_raw_plot = { ... } wvlt_plot = { ... } @@ -482,19 +482,19 @@ The dimensions and variables included in the wavelet_stat NetCDF files are descr - Description * - FCST_FIELD_LEVEL_RAW - tile, x, y - - Raw values for the forecast field specified by “FIELD_LEVEL” + - Raw values for the forecast field specified by "FIELD_LEVEL" * - OBS_FIELD_LEVEL_RAW - tile, x, y - - Raw values for the observation field specified by “FIELD_LEVEL” + - Raw values for the observation field specified by "FIELD_LEVEL" * - DIFF_FIELD_LEVEL_RAW - tile, x, y - - Raw values for the difference field (**f-o**) specified by “FIELD_LEVEL” + - Raw values for the difference field (**f-o**) specified by "FIELD_LEVEL" * - FCST_FIELD_LEVEL_THRESH - tile, scale, x, y - - Wavelet scale-decomposition of the forecast field specified by “FIELD_LEVEL_THRESH” + - Wavelet scale-decomposition of the forecast field specified by "FIELD_LEVEL_THRESH" * - OBS_FIELD_LEVEL_THRESH - tile, scale, x, y - - Wavelet scale-decomposition of the observation field specified by “FIELD_LEVEL_THRESH” + - Wavelet scale-decomposition of the observation field specified by "FIELD_LEVEL_THRESH" Lastly, the **Wavelet-Stat** tool creates a PostScript plot summarizing the scale-decomposition approach used in the verification. The PostScript plot is generated using internal libraries and does not depend on an external plotting package. The generation of this PostScript output can be disabled using the **ps_plot_flag** configuration file option. From a1105eed00e9cbc1ec74b0110694742bcbf59de3 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 15:10:29 -0600 Subject: [PATCH 011/200] Replace unicode exponent with math mode --- met/docs/Users_Guide/wavelet-stat.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/met/docs/Users_Guide/wavelet-stat.rst b/met/docs/Users_Guide/wavelet-stat.rst index 33bf779692..0f4bf9a281 100644 --- a/met/docs/Users_Guide/wavelet-stat.rst +++ b/met/docs/Users_Guide/wavelet-stat.rst @@ -32,7 +32,7 @@ The Intensity Scale approach can be summarized in the following 5 steps: 1. For each threshold, the forecast and observation fields are transformed into binary fields: where the grid-point precipitation value meets the threshold criteria it is assigned 1, where the threshold criteria are not met it is assigned 0. :numref:`wavelet-stat_NIMROD_3h_fcst` illustrates an example of a forecast and observation fields, and their corresponding binary fields for a threshold of 1mm/h. This case shows an intense storm of the scale of 160 km displaced almost its entire length. The displacement error is clearly visible from the binary field difference and the contingency table image obtained for the same threshold :numref:`contingency_table_counts`. -2. The binary forecast and observation fields obtained from the thresholding are then decomposed into the sum of components on different scales, by using a 2D Haar wavelet filter (:numref:`wavelet-stat_NIMROD_diff`). Note that the scale components are fields, and their sum adds up to the original binary field. For a forecast defined over square domain of **2ⁿ x 2ⁿ** grid-points, the scale components are **n+1: n** mother wavelet components + the largest father wavelet (or scale-function) component. The **n** mother wavelet components have resolution equal to **1, 2, 4, ...** :math:`\mathbf{2^{n-1}}` grid-points. The largest father wavelet component is a constant field over the **2ⁿ x 2ⁿ** grid-point domain with value equal to the field mean. +2. The binary forecast and observation fields obtained from the thresholding are then decomposed into the sum of components on different scales, by using a 2D Haar wavelet filter (:numref:`wavelet-stat_NIMROD_diff`). Note that the scale components are fields, and their sum adds up to the original binary field. For a forecast defined over square domain of :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} grid-points, the scale components are **n+1: n** mother wavelet components + the largest father wavelet (or scale-function) component. The **n** mother wavelet components have resolution equal to **1, 2, 4, ...** :math:`\mathbf{2^{n-1}}` grid-points. The largest father wavelet component is a constant field over the :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} grid-point domain with value equal to the field mean. **Note** that the wavelet transform is a linear operator: this implies that the difference of the spatial scale components of the binary forecast and observation fields (:numref:`wavelet-stat_NIMROD_diff`) are equal to the spatial scale components of the difference of the binary forecast and observation fields (:numref:`wavelet-stat_NIMROD_binary_fcst_and_obs`), and these scale components also add up to the original binary field difference (:numref:`wavelet-stat_NIMROD_3h_fcst`). The intensity-scale technique considers thus the spatial scale of the error. For the case illustrated (:numref:`wavelet-stat_NIMROD_3h_fcst` and :numref:`wavelet-stat_NIMROD_binary_fcst_and_obs`) note the large error associated at the scale of 160 km, due the storm, 160km displaced almost its entire length. @@ -128,18 +128,18 @@ Note that the energy squared of the observation binary field is identical to the The spatial domain constraints ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The Intensity-Scale technique is constrained by the fact that orthogonal wavelets (discrete wavelet transforms) are usually performed dyadic domains, square domains of **2ⁿ x 2ⁿ** grid-points. The Wavelet-Stat tool handles this issue based on settings in the configuration file by defining tiles of dimensions **2ⁿ x 2ⁿ** over the input domain in the following ways: +The Intensity-Scale technique is constrained by the fact that orthogonal wavelets (discrete wavelet transforms) are usually performed dyadic domains, square domains of :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} grid-points. The Wavelet-Stat tool handles this issue based on settings in the configuration file by defining tiles of dimensions :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} over the input domain in the following ways: -1. User-Defined Tiling: The user may define one or more tiles of size **2ⁿ x 2ⁿ** over their domain to be applied. This is done by selecting the grid coordinates for the lower-left corner of the tile(s) and the tile dimension to be used. If the user specifies more than one tile, the Intensity-Scale method will be applied to each tile separately. At the end, the results will automatically be aggregated across all the tiles and written out with the results for each of the individual tiles. Users are encouraged to select tiles which consist entirely of valid data. +1. User-Defined Tiling: The user may define one or more tiles of size :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} over their domain to be applied. This is done by selecting the grid coordinates for the lower-left corner of the tile(s) and the tile dimension to be used. If the user specifies more than one tile, the Intensity-Scale method will be applied to each tile separately. At the end, the results will automatically be aggregated across all the tiles and written out with the results for each of the individual tiles. Users are encouraged to select tiles which consist entirely of valid data. -2. Automated Tiling: This tiling method is essentially the same as the user-defined tiling method listed above except that the tool automatically selects the location and size of the tile(s) to be applied. It figures out the maximum tile of dimension **2ⁿ x 2ⁿ** that fits within the domain and places the tile at the center of the domain. For domains that are very elongated in one direction, it defines as many of these tiles as possible that fit within the domain. +2. Automated Tiling: This tiling method is essentially the same as the user-defined tiling method listed above except that the tool automatically selects the location and size of the tile(s) to be applied. It figures out the maximum tile of dimension :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} that fits within the domain and places the tile at the center of the domain. For domains that are very elongated in one direction, it defines as many of these tiles as possible that fit within the domain. -3. Padding: If the domain size is only slightly smaller than **2ⁿ x 2ⁿ**, for certain variables (e.g. precipitation), it is advisable to expand the domain out to **2ⁿ x 2ⁿ** grid-points by adding extra rows and/or columns of fill data. For precipitation variables, a fill value of zero is used. For continuous variables, such as temperature, the fill value is defined as the mean of the valid data in the rest of the field. A drawback to the padding method is the introduction of artificial data into the original field. Padding should only be used when a very small number of rows and/or columns need to be added. +3. Padding: If the domain size is only slightly smaller than :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n}, for certain variables (e.g. precipitation), it is advisable to expand the domain out to :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} grid-points by adding extra rows and/or columns of fill data. For precipitation variables, a fill value of zero is used. For continuous variables, such as temperature, the fill value is defined as the mean of the valid data in the rest of the field. A drawback to the padding method is the introduction of artificial data into the original field. Padding should only be used when a very small number of rows and/or columns need to be added. Aggregation of statistics on multiple cases ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The Stat-Analysis tool aggregates the intensity scale technique results. Since the results are scale-dependent, it is sensible to aggregate results from multiple model runs (e.g. daily runs for a season) on the same spatial domain, so that the scale components for each singular case will be the same number, and the domain, if not a square domain of **2ⁿ x 2ⁿ** grid-points, will be treated in the same fashion. Similarly, the intensity thresholds for each run should all be the same. +The Stat-Analysis tool aggregates the intensity scale technique results. Since the results are scale-dependent, it is sensible to aggregate results from multiple model runs (e.g. daily runs for a season) on the same spatial domain, so that the scale components for each singular case will be the same number, and the domain, if not a square domain of :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} grid-points, will be treated in the same fashion. Similarly, the intensity thresholds for each run should all be the same. The MSE and forecast and observation squared energy for each scale and thresholds are aggregated simply with a weighted average, where weights are proportional to the number of grid-points used in each single run to evaluate the statistics. If the same domain is always used (and it should) the weights result all the same, and the weighted averaging is a simple mean. For each threshold, the aggregated Br is equal to the aggregated squared energy of the binary observation field, and the aggregated FBI is obtained as the ratio of the aggregated squared energies of the forecast and observation binary fields. From aggregated Br and FBI, the MSErandom for the aggregated runs can be evaluated using the same formula as for the single run. Finally, the Intensity-Scale Skill Score is evaluated by using the aggregated statistics within the same formula used for the single case. @@ -243,7 +243,7 @@ The **grid_decomp_flag** variable specifies how tiling should be performed: • **TILE** indicates that the user-defined tiles should be applied. -• **PAD** indicated that the data should be padded out to the nearest dimension of **2ⁿ x 2ⁿ** +• **PAD** indicated that the data should be padded out to the nearest dimension of :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} The **width** and **location** variables allow users to manually define the tiles of dimension they would like to apply. The x_ll and y_ll variables specify the location of one or more lower-left tile grid (x, y) points. @@ -460,11 +460,11 @@ The dimensions and variables included in the wavelet_stat NetCDF files are descr * - NetCDF Dimension - Description * - x - - Dimension of the tile which equals **2ⁿ** + - Dimension of the tile which equals :math:`\mathbf{2^n} * - y - - Dimension of the tile which equals **2ⁿ** + - Dimension of the tile which equals :math:`\mathbf{2^n} * - scale - - Dimension for the number of scales. This is set to **n+2**, where **2ⁿ** is the tile dimension. The 2 extra scales are for the binary image and the wavelet averaged over the whole tile. + - Dimension for the number of scales. This is set to **n+2**, where :math:`\mathbf{2^n} is the tile dimension. The 2 extra scales are for the binary image and the wavelet averaged over the whole tile. * - tile - Dimension for the number of tiles used From 87befb3c5da461634de9b46156b762a48268f38d Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 15:29:55 -0600 Subject: [PATCH 012/200] Change eqnarray to align --- met/docs/Users_Guide/mode.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/mode.rst b/met/docs/Users_Guide/mode.rst index 5ab864f459..defbb38603 100644 --- a/met/docs/Users_Guide/mode.rst +++ b/met/docs/Users_Guide/mode.rst @@ -30,7 +30,7 @@ The process used for resolving objects in a raw data field is called *convolutio In this formula, :math:`f` is the raw data field, :math:`\phi` is the filter function, and :math:`C` is the resulting convolved field. The variables :math:`(x, y)` and :math:`(u, v)` are grid coordinates. The filter function :math:`\phi` is a simple circular filter determined by a radius of influence :math:`R` , and a height :math:`H` : -.. math:: \phi (x,y) = \begin{eqnarray}\begin{cases} H &\text{if } x^2 + y^2\leq R^2\\ 0 &\text{otherwise.} \end{cases}\end{eqnarray} +.. math:: \phi (x,y) = \begin{align}\begin{cases} H &\text{if } x^2 + y^2\leq R^2\\ 0 &\text{otherwise.} \end{cases}\end{align} The parameters :math:`R` and :math:`H` are not independent. They are related by the requirement that the integral of :math:`\phi` over the grid be unity: @@ -40,7 +40,7 @@ Thus, the radius of influence :math:`R` is the only tunable parameter in the con Once the convolved field :math:`C` is in hand, it is thresholded to create a mask field :math:`M` : -.. math:: M(x,y) = \begin{eqnarray}\begin{cases} 1 &\text{if } C(x,y)\ge T\\ 0 &\text{otherwise.} \end{cases}\end{eqnarray} +.. math:: M(x,y) = \begin{align}\begin{cases} 1 &\text{if } C(x,y)\ge T\\ 0 &\text{otherwise.} \end{cases}\end{align} where :math:`T` is the threshold. The objects are the connected regions where :math:`M = 1` . Finally, the raw data are restored to object interiors to obtain the object field :math:`F` : From e0f82235c294ab3b29b589243f9de239ed6e2feb Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 15:40:15 -0600 Subject: [PATCH 013/200] Replace gif images with png for PDF --- .../figure/plotting-Gilbert-skill-score.png | Bin 0 -> 15350 bytes .../figure/plotting-verification.png | Bin 0 -> 60682 bytes .../figure/plotting_Gilbert_skill_score.gif | Bin 12846 -> 0 bytes .../figure/plotting_verification.gif | Bin 46212 -> 0 bytes met/docs/Users_Guide/plotting.rst | 4 ++-- 5 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 met/docs/Users_Guide/figure/plotting-Gilbert-skill-score.png create mode 100644 met/docs/Users_Guide/figure/plotting-verification.png delete mode 100644 met/docs/Users_Guide/figure/plotting_Gilbert_skill_score.gif delete mode 100644 met/docs/Users_Guide/figure/plotting_verification.gif diff --git a/met/docs/Users_Guide/figure/plotting-Gilbert-skill-score.png b/met/docs/Users_Guide/figure/plotting-Gilbert-skill-score.png new file mode 100644 index 0000000000000000000000000000000000000000..0b8b71056a20c8becf513232088b4f340379a011 GIT binary patch literal 15350 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 r{cbAv%bI$n> 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 literal 0 HcmV?d00001 diff --git a/met/docs/Users_Guide/figure/plotting_Gilbert_skill_score.gif b/met/docs/Users_Guide/figure/plotting_Gilbert_skill_score.gif deleted file mode 100644 index 7840e1e6eac958e9d1c9034601ac7f10b25f7683..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12846 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

&FgfunH3lnijAiY-RmJnv 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 diff --git a/met/docs/Users_Guide/plotting.rst b/met/docs/Users_Guide/plotting.rst index 04e9ee629a..e9e97a5529 100644 --- a/met/docs/Users_Guide/plotting.rst +++ b/met/docs/Users_Guide/plotting.rst @@ -320,7 +320,7 @@ The plots in :numref:`plotting_Gilbert_skill_score` show time series of frequenc .. _plotting_Gilbert_skill_score: -.. figure:: figure/plotting_Gilbert_skill_score.gif +.. figure:: figure/plotting_Gilbert_skill_score.png Time series of forecast area bias and Gilbert Skill Score for four model configurations (different lines) stratified by time-of-day. @@ -333,7 +333,7 @@ When using the MODE tool, it is possible to think of matched objects as hits and .. _plotting_verification: -.. figure:: figure/plotting_verification.gif +.. figure:: figure/plotting_verification.png Traditional verification scores applied to output of the MODE tool, computed by defining matched observed objects to be hits, unmatched observed objects to be misses, and unmatched forecast objects to be false alarms; weighted by object area. Bar plots show numbers (penultimate row) and areas (bottom row) of observed and forecast objects, respectively. From ea51e96571a46a16a393698c65e946475f580ad3 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 15:46:46 -0600 Subject: [PATCH 014/200] Fix png file names --- met/docs/Users_Guide/plotting.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/plotting.rst b/met/docs/Users_Guide/plotting.rst index e9e97a5529..7f748e7885 100644 --- a/met/docs/Users_Guide/plotting.rst +++ b/met/docs/Users_Guide/plotting.rst @@ -320,7 +320,7 @@ The plots in :numref:`plotting_Gilbert_skill_score` show time series of frequenc .. _plotting_Gilbert_skill_score: -.. figure:: figure/plotting_Gilbert_skill_score.png +.. figure:: figure/plotting-Gilbert-skill-score.png Time series of forecast area bias and Gilbert Skill Score for four model configurations (different lines) stratified by time-of-day. @@ -333,7 +333,7 @@ When using the MODE tool, it is possible to think of matched objects as hits and .. _plotting_verification: -.. figure:: figure/plotting_verification.png +.. figure:: figure/plotting-verification.png Traditional verification scores applied to output of the MODE tool, computed by defining matched observed objects to be hits, unmatched observed objects to be misses, and unmatched forecast objects to be false alarms; weighted by object area. Bar plots show numbers (penultimate row) and areas (bottom row) of observed and forecast objects, respectively. From 2063d0dab270331ba8254c60334515bb68e1954f Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 16:00:34 -0600 Subject: [PATCH 015/200] Escape underscore in variable name in math mode --- met/docs/Users_Guide/appendixC.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 6b1dd59f26..2fe0b3e529 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -147,7 +147,7 @@ Called "H_RATE" in FHO output :numref:`table_PS_format_info_FHO` H_RATE is defined as -.. math:: \text{H_RATE } = \frac{n_{11}}{T}. +.. math:: \text{H\_RATE } = \frac{n_{11}}{T}. H_RATE is equivalent to the H value computed by the NCEP verification system. H_RATE ranges from 0 to 1; a perfect forecast would have H_RATE = 1. From 7a5b842b5093c1ede3977deac435400b2d7c10d9 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 16:22:03 -0600 Subject: [PATCH 016/200] Escape underscore in variable name in math mode --- met/docs/Users_Guide/appendixC.rst | 2 +- met/docs/Users_Guide/appendixG.rst | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 2fe0b3e529..1622b06201 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -581,7 +581,7 @@ The anomaly correlation coefficient is equivalent to the Pearson correlation coe The centered anomaly correlation coefficient (ANOM_CORR) which includes the mean error is defined as: -.. math:: \text{ANOM_CORR } = \frac{ \bar{[(f - c) - \bar{(f - c)}][(a - c) - \bar{(a - c)}]}}{ \sqrt{ \bar{( (f - c) - \bar{(f - c)})^2} \bar{( (a - c) - \bar{(a - c)})^2}}} +.. math:: \text{ANOM\_CORR } = \frac{ \bar{[(f - c) - \bar{(f - c)}][(a - c) - \bar{(a - c)}]}}{ \sqrt{ \bar{( (f - c) - \bar{(f - c)})^2} \bar{( (a - c) - \bar{(a - c)})^2}}} The uncentered anomaly correlation coefficient (ANOM_CORR_UNCNTR) which does not include the mean errors is defined as: diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index 12316fe477..9510b78b02 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -82,9 +82,9 @@ _________________________ FS_RMS and OS_RMS are the root-mean-square values of the forecast and observed wind speeds. -.. math:: \text{FS_RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} +.. math:: \text{FS\_RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} - \text{OS_RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} + \text{OS\_RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} ___________________________ @@ -116,16 +116,16 @@ ________________________ FBAR_SPEED and OBAR_SPEED are the lengths of the average forecast and observed wind vectors. Note that this is *not* the same as the average forecast and observed wind speeds (*ie.,* the length of an average vector :math:`\neq` the average length of the vector). -.. math:: \text{FBAR_SPEED } = | \mathbf{F}_a | +.. math:: \text{FBAR\_SPEED } = | \mathbf{F}_a | - \text{OBAR_SPEED } = | \mathbf{O}_a | + \text{OBAR\_SPEED } = | \mathbf{O}_a | ________________________ VDIFF_SPEED is the length (*ie. speed*) of the vector difference between the average forecast and average observed wind vectors. -.. math:: \text{VDIFF_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | +.. math:: \text{VDIFF\_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or , equivalently, that :math:`| \text{SPEED_ERR} | \leq \text{VDIFF_SPEED}`. @@ -134,30 +134,30 @@ _________________________ VDIFF_DIR is the direction of the vector difference of the average forecast and average observed wind vectors. Note that this is {\it not} the same as the difference in direction of the average forecast and average observed wind vectors. This latter quantity would be FDIR :math:`-` ODIR. -.. math:: \text{VDIFF_DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) +.. math:: \text{VDIFF\_DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) _________________________ SPEED_ERR is the difference in the lengths (speeds) of the average forecast and average observed wind vectors. (See the discussion of VDIFF_SPEED above.) -.. math:: \text{SPEED_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR_SPEED } - \text{ OBAR_SPEED} +.. math:: \text{SPEED\_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBA\R_SPEED } - \text{ OBAR\_SPEED} ___________________________ SPEED_ABSERR is the absolute value of SPEED_ERR. Note that we have SPEED_ABSERR :math:`\leq` VDIFF_SPEED (see the discussion of VDIFF_SPEED above). -.. math:: \text{SPEED_ABSERR } = | \text{SPEED_ERR} | +.. math:: \text{SPEED\_ABSERR } = | \text{SPEED\_ERR} | __________________________ DIR_ERR is the signed angle between the directions of the average forecast and average observed wind vectors. Positive if the forecast vector is counterclockwise from the observed vector. -.. math:: \text{DIR_ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) +.. math:: \text{DIR\_ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) __________________________ DIR_ABSERR is the absolute value of DIR_ERR. In other words, it's an unsigned angle rather than a signed angle. -.. math:: \text{DIR_ABSERR } = | \text{DIR_ERR}| +.. math:: \text{DIR\_ABSERR } = | \text{DIR\_ERR}| From 0abeda0569f8d2a7f449726cfb0ce5b1dad991d8 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 16:30:33 -0600 Subject: [PATCH 017/200] Remove underscores from variables in math mode --- met/docs/Users_Guide/appendixC.rst | 4 ++-- met/docs/Users_Guide/appendixG.rst | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 1622b06201..5d63c87204 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -147,7 +147,7 @@ Called "H_RATE" in FHO output :numref:`table_PS_format_info_FHO` H_RATE is defined as -.. math:: \text{H\_RATE } = \frac{n_{11}}{T}. +.. math:: \text{H RATE } = \frac{n_{11}}{T}. H_RATE is equivalent to the H value computed by the NCEP verification system. H_RATE ranges from 0 to 1; a perfect forecast would have H_RATE = 1. @@ -581,7 +581,7 @@ The anomaly correlation coefficient is equivalent to the Pearson correlation coe The centered anomaly correlation coefficient (ANOM_CORR) which includes the mean error is defined as: -.. math:: \text{ANOM\_CORR } = \frac{ \bar{[(f - c) - \bar{(f - c)}][(a - c) - \bar{(a - c)}]}}{ \sqrt{ \bar{( (f - c) - \bar{(f - c)})^2} \bar{( (a - c) - \bar{(a - c)})^2}}} +.. math:: \text{ANOM CORR } = \frac{ \bar{[(f - c) - \bar{(f - c)}][(a - c) - \bar{(a - c)}]}}{ \sqrt{ \bar{( (f - c) - \bar{(f - c)})^2} \bar{( (a - c) - \bar{(a - c)})^2}}} The uncentered anomaly correlation coefficient (ANOM_CORR_UNCNTR) which does not include the mean errors is defined as: diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index 9510b78b02..18cb7be2ab 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -82,9 +82,9 @@ _________________________ FS_RMS and OS_RMS are the root-mean-square values of the forecast and observed wind speeds. -.. math:: \text{FS\_RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} +.. math:: \text{FS RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} - \text{OS\_RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} + \text{OS RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} ___________________________ @@ -116,16 +116,16 @@ ________________________ FBAR_SPEED and OBAR_SPEED are the lengths of the average forecast and observed wind vectors. Note that this is *not* the same as the average forecast and observed wind speeds (*ie.,* the length of an average vector :math:`\neq` the average length of the vector). -.. math:: \text{FBAR\_SPEED } = | \mathbf{F}_a | +.. math:: \text{FBAR SPEED } = | \mathbf{F}_a | - \text{OBAR\_SPEED } = | \mathbf{O}_a | + \text{OBAR SPEED } = | \mathbf{O}_a | ________________________ VDIFF_SPEED is the length (*ie. speed*) of the vector difference between the average forecast and average observed wind vectors. -.. math:: \text{VDIFF\_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | +.. math:: \text{VDIFF SPEED } = | \mathbf{F}_a - \mathbf{O}_a | Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or , equivalently, that :math:`| \text{SPEED_ERR} | \leq \text{VDIFF_SPEED}`. @@ -134,30 +134,30 @@ _________________________ VDIFF_DIR is the direction of the vector difference of the average forecast and average observed wind vectors. Note that this is {\it not} the same as the difference in direction of the average forecast and average observed wind vectors. This latter quantity would be FDIR :math:`-` ODIR. -.. math:: \text{VDIFF\_DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) +.. math:: \text{VDIFF DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) _________________________ SPEED_ERR is the difference in the lengths (speeds) of the average forecast and average observed wind vectors. (See the discussion of VDIFF_SPEED above.) -.. math:: \text{SPEED\_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBA\R_SPEED } - \text{ OBAR\_SPEED} +.. math:: \text{SPEED ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBA\R_SPEED } - \text{ OBAR SPEED} ___________________________ SPEED_ABSERR is the absolute value of SPEED_ERR. Note that we have SPEED_ABSERR :math:`\leq` VDIFF_SPEED (see the discussion of VDIFF_SPEED above). -.. math:: \text{SPEED\_ABSERR } = | \text{SPEED\_ERR} | +.. math:: \text{SPEED ABSERR } = | \text{SPEED ERR} | __________________________ DIR_ERR is the signed angle between the directions of the average forecast and average observed wind vectors. Positive if the forecast vector is counterclockwise from the observed vector. -.. math:: \text{DIR\_ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) +.. math:: \text{DIR ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) __________________________ DIR_ABSERR is the absolute value of DIR_ERR. In other words, it's an unsigned angle rather than a signed angle. -.. math:: \text{DIR\_ABSERR } = | \text{DIR\_ERR}| +.. math:: \text{DIR ABSERR } = | \text{DIR ERR}| From 1c72343adb603835740d5e383a14e7964033684f Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 17:07:18 -0600 Subject: [PATCH 018/200] Replace bar with overline in some equations --- met/docs/Users_Guide/appendixC.rst | 6 +++--- met/docs/Users_Guide/appendixG.rst | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 5d63c87204..f8765ad985 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -147,7 +147,7 @@ Called "H_RATE" in FHO output :numref:`table_PS_format_info_FHO` H_RATE is defined as -.. math:: \text{H RATE } = \frac{n_{11}}{T}. +.. math:: \text{H\_RATE } = \frac{n_{11}}{T}. H_RATE is equivalent to the H value computed by the NCEP verification system. H_RATE ranges from 0 to 1; a perfect forecast would have H_RATE = 1. @@ -581,11 +581,11 @@ The anomaly correlation coefficient is equivalent to the Pearson correlation coe The centered anomaly correlation coefficient (ANOM_CORR) which includes the mean error is defined as: -.. math:: \text{ANOM CORR } = \frac{ \bar{[(f - c) - \bar{(f - c)}][(a - c) - \bar{(a - c)}]}}{ \sqrt{ \bar{( (f - c) - \bar{(f - c)})^2} \bar{( (a - c) - \bar{(a - c)})^2}}} +.. math:: \text{ANOM\_CORR } = \frac{ \overline{[(f - c) - \overline{(f - c)}][(a - c) - \overline{(a - c)}]}}{ \sqrt{ \overline{( (f - c) - \overline{(f - c)})^2} \overline{( (a - c) - \overline{(a - c)})^2}}} The uncentered anomaly correlation coefficient (ANOM_CORR_UNCNTR) which does not include the mean errors is defined as: -.. math:: \text{Anomaly Correlation Raw } = \frac{ \bar{(f - c)(a - c)}}{ \sqrt{\bar{(f - c)^2} \bar{(a - c)^2}}} +.. math:: \text{Anomaly Correlation Raw } = \frac{ \overline{(f - c)(a - c)}}{ \sqrt{\overline{(f - c)^2} \overline{(a - c)^2}}} Anomaly correlation can range between -1 and 1; a value of 1 indicates perfect correlation and a value of -1 indicates perfect negative correlation. A value of 0 indicates that the forecast and observed anomalies are not correlated. diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index 18cb7be2ab..fec4a52341 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -82,9 +82,9 @@ _________________________ FS_RMS and OS_RMS are the root-mean-square values of the forecast and observed wind speeds. -.. math:: \text{FS RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} +.. math:: \text{FS\_RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} - \text{OS RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} + \text{OS\_RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} ___________________________ @@ -116,16 +116,16 @@ ________________________ FBAR_SPEED and OBAR_SPEED are the lengths of the average forecast and observed wind vectors. Note that this is *not* the same as the average forecast and observed wind speeds (*ie.,* the length of an average vector :math:`\neq` the average length of the vector). -.. math:: \text{FBAR SPEED } = | \mathbf{F}_a | +.. math:: \text{FBAR\_SPEED } = | \mathbf{F}_a | - \text{OBAR SPEED } = | \mathbf{O}_a | + \text{OBAR\_SPEED } = | \mathbf{O}_a | ________________________ VDIFF_SPEED is the length (*ie. speed*) of the vector difference between the average forecast and average observed wind vectors. -.. math:: \text{VDIFF SPEED } = | \mathbf{F}_a - \mathbf{O}_a | +.. math:: \text{VDIFF\_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or , equivalently, that :math:`| \text{SPEED_ERR} | \leq \text{VDIFF_SPEED}`. @@ -134,30 +134,30 @@ _________________________ VDIFF_DIR is the direction of the vector difference of the average forecast and average observed wind vectors. Note that this is {\it not} the same as the difference in direction of the average forecast and average observed wind vectors. This latter quantity would be FDIR :math:`-` ODIR. -.. math:: \text{VDIFF DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) +.. math:: \text{VDIFF\_DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) _________________________ SPEED_ERR is the difference in the lengths (speeds) of the average forecast and average observed wind vectors. (See the discussion of VDIFF_SPEED above.) -.. math:: \text{SPEED ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBA\R_SPEED } - \text{ OBAR SPEED} +.. math:: \text{SPEED_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR_SPEED } - \text{ OBAR_SPEED} ___________________________ SPEED_ABSERR is the absolute value of SPEED_ERR. Note that we have SPEED_ABSERR :math:`\leq` VDIFF_SPEED (see the discussion of VDIFF_SPEED above). -.. math:: \text{SPEED ABSERR } = | \text{SPEED ERR} | +.. math:: \text{SPEED_ABSERR } = | \text{SPEED_ERR} | __________________________ DIR_ERR is the signed angle between the directions of the average forecast and average observed wind vectors. Positive if the forecast vector is counterclockwise from the observed vector. -.. math:: \text{DIR ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) +.. math:: \text{DIR_ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) __________________________ DIR_ABSERR is the absolute value of DIR_ERR. In other words, it's an unsigned angle rather than a signed angle. -.. math:: \text{DIR ABSERR } = | \text{DIR ERR}| +.. math:: \text{DIR_ABSERR } = | \text{DIR_ERR}| From 31f10c0af027cc799ee3359881392883c6053327 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 17:24:24 -0600 Subject: [PATCH 019/200] Test derefencing underscores in tables --- met/docs/Users_Guide/grid-stat.rst | 52 +++++++++++++++--------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/met/docs/Users_Guide/grid-stat.rst b/met/docs/Users_Guide/grid-stat.rst index b05ec4ad7d..2385a8789b 100644 --- a/met/docs/Users_Guide/grid-stat.rst +++ b/met/docs/Users_Guide/grid-stat.rst @@ -714,10 +714,10 @@ The format of the STAT and ASCII output of the Grid-Stat tool are the same as th - S1 - S1 score * - 31 - - S1_OG + - S1\_OG - S1 score with respect to observed gradient * - 32 - - FGOG_RATIO + - FGOG\_RATIO - Ratio of forecast and observed gradients * - 33 - DX @@ -760,50 +760,50 @@ The format of the STAT and ASCII output of the Grid-Stat tool are the same as th - HAUSDORFF - Hausdorff Distance * - 31 - - MED_FO + - MED\_FO - Mean-error Distance from observation to forecast * - 32 - - MED_OF + - MED\_OF - Mean-error Distance from forecast to observation * - 33 - - MED_MIN - - Minimum of MED_FO and MED_OF + - MED\_MIN + - Minimum of MED\_FO and MED\_OF * - 34 - - MED_MAX - - Maximum of MED_FO and MED_OF + - MED\_MAX + - Maximum of MED\_FO and MED\_OF * - 35 - - MED_MEAN - - Mean of MED_FO and MED_OF + - MED\_MEAN + - Mean of MED\_FO and MED\_OF * - 36 - - FOM_FO + - FOM\_FO - Pratt's Figure of Merit from observation to forecast * - 37 - - FOM_OF + - FOM\_OF - Pratt's Figure of Merit from forecast to observation * - 38 - - FOM_MIN - - Minimum of FOM_FO and FOM_OF + - FOM\_MIN + - Minimum of FOM\_FO and FOM\_OF * - 39 - - FOM_MAX - - Maximum of FOM_FO and FOM_OF + - FOM\_MAX + - Maximum of FOM\_FO and FOM\_OF * - 40 - - FOM_MEAN - - Mean of FOM_FO and FOM_OF + - FOM\_MEAN + - Mean of FOM\_FO and FOM\_OF * - 41 - - ZHU_FO + - ZHU\_FO - Zhu's Measure from observation to forecast * - 42 - - ZHU_OF + - ZHU\_OF - Zhu's Measure from forecast to observation * - 43 - - ZHU_MIN - - Minimum of ZHU_FO and ZHU_OF + - ZHU\_MIN + - Minimum of ZHU\_FO and ZHU\_OF * - 44 - - ZHU_MAX - - Maximum of ZHU_FO and ZHU_OF + - ZHU\_MAX + - Maximum of ZHU\_FO and ZHU\_OF * - 45 - - ZHU_MEAN - - Mean of ZHU_FO and ZHU_OF + - ZHU\_MEAN + - Mean of ZHU\_FO and ZHU\_OF If requested using the **nc_pairs_flag** dictionary in the configuration file, a NetCDF file containing the matched pair and forecast minus observation difference fields for each combination of variable type/level and masking region applied will be generated. The contents of this file are determined by the contents of the nc_pairs_flag dictionary. The output NetCDF file is named similarly to the other output files: **grid_stat_PREFIX_ HHMMSSL_YYYYMMDD_HHMMSSV_pairs.nc**. Commonly available NetCDF utilities such as ncdump or ncview may be used to view the contents of the output file. From b06e622af64c8a09cda7363d17048f5ac1fb8ad0 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 17:43:33 -0600 Subject: [PATCH 020/200] Test math changes in grid stat --- met/docs/Users_Guide/grid-stat.rst | 54 +++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/met/docs/Users_Guide/grid-stat.rst b/met/docs/Users_Guide/grid-stat.rst index 2385a8789b..68e7ae4353 100644 --- a/met/docs/Users_Guide/grid-stat.rst +++ b/met/docs/Users_Guide/grid-stat.rst @@ -90,7 +90,7 @@ Differences are computed in both of the horizontal grid directions and is not a Distance Maps ~~~~~~~~~~~~~ -The following methods can all be computed efficiently by utilizing fast algorithms developed for calculating distance maps. A distance map results from calculating the shortest distance from every grid point, :math:`s=(x,y)`, in the domain, :math:`D`, to the nearest one-valued grid point. In each of the following, it is understood that they are calculated between event areas :math:`A`, from one field and observation event areas :math:`B` from another. If the measure is applied to a feature within a field, then the distance map is still calculated over the entire original domain. Some of the distance map statistics are computed over the entire distance map, while others use only parts of it. +The following methods can all be computed efficiently by utilizing fast algorithms developed for calculating distance maps. A distance map results from calculating the shortest distance from every grid point, **s=(x,y)**, in the domain, **D**, to the nearest one-valued grid point. In each of the following, it is understood that they are calculated between event areas **A**, from one field and observation event areas **B** from another. If the measure is applied to a feature within a field, then the distance map is still calculated over the entire original domain. Some of the distance map statistics are computed over the entire distance map, while others use only parts of it. Because these methods rely on the distance map, it is helpful to understand precisely what such maps do. :numref:`grid-stat_fig1` demonstrates the path of the shortest distance to the nearest event point in the event area A marked by the gray rectangle in the diagram. Note that the arrows all point to a grid point on the boundary of the event area A as it would be a longer distance to any point in its interior. :numref:`grid-stat_fig2` demonstrates the shortest distances from every grid point inside a second event area marked by the gray circle labeled B to the same event area A as in :numref:`grid-stat_fig1`. Note that all of the distances are to points on a small subsection (indicated by the yellow stretch) of the subset A. @@ -714,10 +714,10 @@ The format of the STAT and ASCII output of the Grid-Stat tool are the same as th - S1 - S1 score * - 31 - - S1\_OG + - S1_OG - S1 score with respect to observed gradient * - 32 - - FGOG\_RATIO + - FGOG_RATIO - Ratio of forecast and observed gradients * - 33 - DX @@ -760,50 +760,50 @@ The format of the STAT and ASCII output of the Grid-Stat tool are the same as th - HAUSDORFF - Hausdorff Distance * - 31 - - MED\_FO + - MED_FO - Mean-error Distance from observation to forecast * - 32 - - MED\_OF + - MED_OF - Mean-error Distance from forecast to observation * - 33 - - MED\_MIN - - Minimum of MED\_FO and MED\_OF + - MED_MIN + - Minimum of MED_FO and MED_OF * - 34 - - MED\_MAX - - Maximum of MED\_FO and MED\_OF + - MED_MAX + - Maximum of MED_FO and MED_OF * - 35 - - MED\_MEAN - - Mean of MED\_FO and MED\_OF + - MED_MEAN + - Mean of MED_FO and MED_OF * - 36 - - FOM\_FO + - FOM_FO - Pratt's Figure of Merit from observation to forecast * - 37 - - FOM\_OF + - FOM_OF - Pratt's Figure of Merit from forecast to observation * - 38 - - FOM\_MIN - - Minimum of FOM\_FO and FOM\_OF + - FOM_MIN + - Minimum of FOM_FO and FOM_OF * - 39 - - FOM\_MAX - - Maximum of FOM\_FO and FOM\_OF + - FOM_MAX + - Maximum of FOM_FO and FOM_OF * - 40 - - FOM\_MEAN - - Mean of FOM\_FO and FOM\_OF + - FOM_MEAN + - Mean of FOM_FO and FOM_OF * - 41 - - ZHU\_FO + - ZHU_FO - Zhu's Measure from observation to forecast * - 42 - - ZHU\_OF + - ZHU_OF - Zhu's Measure from forecast to observation * - 43 - - ZHU\_MIN - - Minimum of ZHU\_FO and ZHU\_OF + - ZHU_MIN + - Minimum of ZHU_FO and ZHU_OF * - 44 - - ZHU\_MAX - - Maximum of ZHU\_FO and ZHU\_OF + - ZHU_MAX + - Maximum of ZHU_FO and ZHU_OF * - 45 - - ZHU\_MEAN - - Mean of ZHU\_FO and ZHU\_OF + - ZHU_MEAN + - Mean of ZHU_FO and ZHU_OF If requested using the **nc_pairs_flag** dictionary in the configuration file, a NetCDF file containing the matched pair and forecast minus observation difference fields for each combination of variable type/level and masking region applied will be generated. The contents of this file are determined by the contents of the nc_pairs_flag dictionary. The output NetCDF file is named similarly to the other output files: **grid_stat_PREFIX_ HHMMSSL_YYYYMMDD_HHMMSSV_pairs.nc**. Commonly available NetCDF utilities such as ncdump or ncview may be used to view the contents of the output file. From 7138029df7605eff624a04ad801ce9467384f8ec Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 17:49:19 -0600 Subject: [PATCH 021/200] Test math formatting --- met/docs/Users_Guide/grid-stat.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/grid-stat.rst b/met/docs/Users_Guide/grid-stat.rst index 68e7ae4353..3852ee2ae9 100644 --- a/met/docs/Users_Guide/grid-stat.rst +++ b/met/docs/Users_Guide/grid-stat.rst @@ -291,7 +291,7 @@ ____________________ zhu_weight = 0.5; } -The **distance_map** entry is a dictionary containing options related to the distance map statistics in the **DMAP** output line type. The **baddeley_p** entry is an integer specifying the exponent used in the Lp-norm when computing the Baddeley :math:`\Delta` metric. The **baddeley_max_dist** entry is a floating point number specifying the maximum allowable distance for each distance map. Any distances larger than this number will be reset to this constant. A value of **NA** indicates that no maximum distance value should be used. The **fom_alpha** entry is a floating point number specifying the scaling constant to be used when computing Pratt's Figure of Merit. The **zhu_weight** specifies a value between 0 and 1 to define the importance of the RMSE of the binary fields (i.e. amount of overlap) versus the mean-error distance (MED). The default value of 0.5 gives equal weighting. This configuration option may be set separately in each **obs.field** entry. +The **distance_map** entry is a dictionary containing options related to the distance map statistics in the **DMAP** output line type. The **baddeley_p** entry is an integer specifying the exponent used in the Lp-norm when computing the Baddeley :math:`$\Delta$` metric. The **baddeley_max_dist** entry is a floating point number specifying the maximum allowable distance for each distance map. Any distances larger than this number will be reset to this constant. A value of **NA** indicates that no maximum distance value should be used. The **fom_alpha** entry is a floating point number specifying the scaling constant to be used when computing Pratt's Figure of Merit. The **zhu_weight** specifies a value between 0 and 1 to define the importance of the RMSE of the binary fields (i.e. amount of overlap) versus the mean-error distance (MED). The default value of 0.5 gives equal weighting. This configuration option may be set separately in each **obs.field** entry. _____________________ @@ -755,7 +755,7 @@ The format of the STAT and ASCII output of the Grid-Stat tool are the same as th - Frequency Bias * - 29 - BADDELEY - - Baddeley's :math:`\Delta` Metric + - Baddeley's :math:`$\Delta$` Metric * - 30 - HAUSDORFF - Hausdorff Distance From d84f3e05e43240a9f788d16899b0f97b5f096549 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Fri, 25 Jun 2021 17:57:53 -0600 Subject: [PATCH 022/200] Test math formatting --- met/docs/Users_Guide/grid-stat.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/grid-stat.rst b/met/docs/Users_Guide/grid-stat.rst index 3852ee2ae9..f626f77ef8 100644 --- a/met/docs/Users_Guide/grid-stat.rst +++ b/met/docs/Users_Guide/grid-stat.rst @@ -291,7 +291,7 @@ ____________________ zhu_weight = 0.5; } -The **distance_map** entry is a dictionary containing options related to the distance map statistics in the **DMAP** output line type. The **baddeley_p** entry is an integer specifying the exponent used in the Lp-norm when computing the Baddeley :math:`$\Delta$` metric. The **baddeley_max_dist** entry is a floating point number specifying the maximum allowable distance for each distance map. Any distances larger than this number will be reset to this constant. A value of **NA** indicates that no maximum distance value should be used. The **fom_alpha** entry is a floating point number specifying the scaling constant to be used when computing Pratt's Figure of Merit. The **zhu_weight** specifies a value between 0 and 1 to define the importance of the RMSE of the binary fields (i.e. amount of overlap) versus the mean-error distance (MED). The default value of 0.5 gives equal weighting. This configuration option may be set separately in each **obs.field** entry. +The **distance_map** entry is a dictionary containing options related to the distance map statistics in the **DMAP** output line type. The **baddeley_p** entry is an integer specifying the exponent used in the Lp-norm when computing the Baddeley Delta metric. The **baddeley_max_dist** entry is a floating point number specifying the maximum allowable distance for each distance map. Any distances larger than this number will be reset to this constant. A value of **NA** indicates that no maximum distance value should be used. The **fom_alpha** entry is a floating point number specifying the scaling constant to be used when computing Pratt's Figure of Merit. The **zhu_weight** specifies a value between 0 and 1 to define the importance of the RMSE of the binary fields (i.e. amount of overlap) versus the mean-error distance (MED). The default value of 0.5 gives equal weighting. This configuration option may be set separately in each **obs.field** entry. _____________________ @@ -755,7 +755,7 @@ The format of the STAT and ASCII output of the Grid-Stat tool are the same as th - Frequency Bias * - 29 - BADDELEY - - Baddeley's :math:`$\Delta$` Metric + - Baddeley's Delta Metric * - 30 - HAUSDORFF - Hausdorff Distance From 8294247cad7d881c4397d95f77836487a6cb0055 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 7 Jul 2021 10:46:52 -0600 Subject: [PATCH 023/200] #1838 Added log message for lat/lon values --- met/src/libcode/vx_data2d_nccf/nccf_file.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/met/src/libcode/vx_data2d_nccf/nccf_file.cc b/met/src/libcode/vx_data2d_nccf/nccf_file.cc index f948800ef1..4de72e0f44 100644 --- a/met/src/libcode/vx_data2d_nccf/nccf_file.cc +++ b/met/src/libcode/vx_data2d_nccf/nccf_file.cc @@ -2909,6 +2909,11 @@ void NcCfFile::get_grid_from_lat_lon_vars(NcVar *lat_var, NcVar *lon_var, double dlat = lat_values[1] - lat_values[0]; double dlon = rescale_lon(lon_values[1] - lon_values[0]); + mlog << Debug(7) << method_name << " -> lat[0]=" << lat_values[0] + << " lat[" << (lat_counts-1) << "]=" << lat_values[lat_counts-1] + << " dlat=" << dlat << " lon[0]=" << lon_values[0] + << " lon[" << (lon_counts-1) << "]=" << lon_values[lon_counts-1] + << " dlon=" << dlon << "\n"; ConcatString point_nccf; bool skip_sanity_check = get_att_value_string(_ncFile, nc_att_met_point_nccf, point_nccf); From c51f80e1e9dcb29f5d6b7f5877d5392003560383 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 7 Jul 2021 10:47:27 -0600 Subject: [PATCH 024/200] #1838 Give warning if the first and lat lat/lon is same --- met/src/tools/other/point2grid/point2grid.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/met/src/tools/other/point2grid/point2grid.cc b/met/src/tools/other/point2grid/point2grid.cc index 8f718b0e2a..54df583858 100644 --- a/met/src/tools/other/point2grid/point2grid.cc +++ b/met/src/tools/other/point2grid/point2grid.cc @@ -1930,6 +1930,7 @@ static bool get_grid_mapping(Grid fr_grid, Grid to_grid, IntArray *cellMapping, exit(1); } else if (data_size > 0) { + int last_idx = data_size - 1; float *latitudes = new float[data_size]; float *longitudes = new float[data_size]; status = get_nc_data(&var_lat, latitudes); @@ -1939,6 +1940,13 @@ static bool get_grid_mapping(Grid fr_grid, Grid to_grid, IntArray *cellMapping, latitudes, longitudes, from_lat_count, from_lon_count, skip_times, !fr_grid.get_swap_to_north()); + if (is_eq(latitudes[0], latitudes[last_idx]) || + is_eq(longitudes[0], longitudes[last_idx])) { + mlog << Warning << "\n" << method_name << "same latitude or longitude. lat[0]=" + << latitudes[0] << " lat[" << last_idx << "]=" << latitudes[last_idx] + << " lon[0]=" << longitudes[0] << " lon[" << last_idx << "]=" + << longitudes[last_idx] << "\n\n"; + } } if( latitudes ) delete [] latitudes; if( longitudes ) delete [] longitudes; From 55a8ae8898f64ec46bf9e8f501464305d08f1e29 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 7 Jul 2021 10:48:56 -0600 Subject: [PATCH 025/200] #1838 Support the double data type variable on reading float type values --- met/src/libcode/vx_nc_util/nc_utils.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/met/src/libcode/vx_nc_util/nc_utils.cc b/met/src/libcode/vx_nc_util/nc_utils.cc index d45a49f8b6..eb066df60a 100644 --- a/met/src/libcode/vx_nc_util/nc_utils.cc +++ b/met/src/libcode/vx_nc_util/nc_utils.cc @@ -1433,6 +1433,18 @@ bool get_nc_data(NcVar *var, float *data) { if (NcType::nc_FLOAT == type_id) { var->getVar(data); } + else if (NcType::nc_DOUBLE == type_id) { + int cell_count = 1; + for (int idx=0; idxgetDimCount();idx++) { + cell_count *= get_dim_size(var, idx); + } + double *double_data = new double[cell_count]; + var->getVar(double_data); + for (int idx=0; idxgetDimCount();idx++) { From 8ba6df21adfc4e5aa02c628112223a2cbfb5d911 Mon Sep 17 00:00:00 2001 From: jprestop Date: Thu, 8 Jul 2021 12:25:38 -0600 Subject: [PATCH 026/200] Feature 1833 develop discussions (#1849) * Per #1833, changed references to met_help to Discussions. * Per #1833, fixed typo and removed an unnecessary word --- met/configure.ac | 2 +- met/data/wrappers/read_tmp_ascii.py | 2 +- met/docs/Users_Guide/appendixA.rst | 6 +++--- met/docs/Users_Guide/index.rst | 2 +- met/docs/Users_Guide/overview.rst | 4 ++-- met/docs/Users_Guide/tc-pairs.rst | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/met/configure.ac b/met/configure.ac index dac13bfa64..cbe955c398 100644 --- a/met/configure.ac +++ b/met/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([MET], [m4_esyscmd_s(echo ${MET_BUILD_VERSION:-development})], [met_help@ucar.edu], [], [http://dtcenter.org/community-code/model-evaluation-tools-met]) +AC_INIT([MET], [m4_esyscmd_s(echo ${MET_BUILD_VERSION:-development})], [https://github.com/dtcenter/METplus/discussions], [], [http://dtcenter.org/community-code/model-evaluation-tools-met]) AC_CONFIG_SRCDIR([src/tools/tc_utils/tc_dland/tc_dland.cc]) AC_CONFIG_HEADERS([config.h]) diff --git a/met/data/wrappers/read_tmp_ascii.py b/met/data/wrappers/read_tmp_ascii.py index 66c008e3cd..fb7eb7b4e7 100644 --- a/met/data/wrappers/read_tmp_ascii.py +++ b/met/data/wrappers/read_tmp_ascii.py @@ -16,7 +16,7 @@ __author__ = 'David Fillmore' __version__ = '1.0.0' -__email__ = 'met_help@ucar.edu' + import argparse diff --git a/met/docs/Users_Guide/appendixA.rst b/met/docs/Users_Guide/appendixA.rst index e8e5973e9d..9a0d619648 100644 --- a/met/docs/Users_Guide/appendixA.rst +++ b/met/docs/Users_Guide/appendixA.rst @@ -36,7 +36,7 @@ A. No - it will not. In the future, we may add options to allow additional model **Q. How do I get help if my questions are not answered in the User's Guide?** -A. First, look on our `MET User's Guide website `_. If that doesn't answer your question, then email: met_help@ucar.edu. +A. First, look on our `MET User's Guide website `_. If that doesn't answer your question, create a post in the `METplus GitHub Discussions Forum `_. **Q. Where are the graphics?** @@ -94,9 +94,9 @@ The first place to look for help with individual commands is this user's guide o Where to get help _________________ -If none of the above suggestions have helped solve your problem, help is available through: met_help@ucar.edu +If none of the above suggestions have helped solve your problem, help is available through the `METplus GitHub Discussions Forum `_. How to contribute code ______________________ -If you have code you would like to contribute, we will gladly consider your contribution. Please send email to: met_help@ucar.edu +If you have code you would like to contribute, we will gladly consider your contribution. Please create a post in the `METplus GitHub Discussions Forum `_. diff --git a/met/docs/Users_Guide/index.rst b/met/docs/Users_Guide/index.rst index 40151728e5..6f62391dc6 100644 --- a/met/docs/Users_Guide/index.rst +++ b/met/docs/Users_Guide/index.rst @@ -6,7 +6,7 @@ User's Guide This User's guide is provided as an aid to users of the Model Evaluation Tools (MET). MET is a set of verification tools developed by the Developmental Testbed Center (DTC) for use by the numerical weather prediction community to help them assess and evaluate the performance of numerical weather predictions. It is also the core component of the unified METplus verification framework. More details about METplus can be found on the `METplus website `_. -It is important to note here that MET is an evolving software package. This documentation describes the |release| release dated |release_date|. Previous releases of MET have occurred each year since 2008. Intermediate releases may include bug fixes. MET is also able to accept new modules contributed by the community. If you have code you would like to contribute, we will gladly consider your contribution. Please send an email to: `met_help@ucar.edu `__. We will then determine the maturity of the new verification method and coordinate the inclusion of the new module in a future version. +It is important to note here that MET is an evolving software package. This documentation describes the |release| release dated |release_date|. Previous releases of MET have occurred each year since 2008. Intermediate releases may include bug fixes. MET is also able to accept new modules contributed by the community. If you have code you would like to contribute, we will gladly consider your contribution. Please create a post in the `METplus GitHub Discussions Forum `_. We will then determine the maturity of the new verification method and coordinate the inclusion of the new module in a future version. **Model Evaluation Tools (MET) TERMS OF USE - IMPORTANT!** diff --git a/met/docs/Users_Guide/overview.rst b/met/docs/Users_Guide/overview.rst index 733255d409..ac1d55c067 100644 --- a/met/docs/Users_Guide/overview.rst +++ b/met/docs/Users_Guide/overview.rst @@ -81,13 +81,13 @@ MET is an evolving verification software package. New capabilities are planned i Code support ____________ -MET support is provided through a MET-help email address: met_help@ucar.edu. We will endeavor to respond to requests for help in a timely fashion. In addition, information about MET and tools that can be used with MET are provided on the `MET web page `_. +MET support is provided through the `METplus GitHub Discussions Forum `_. We will endeavor to respond to requests for help in a timely fashion. In addition, information about MET and tools that can be used with MET are provided on the `MET web page `_. We welcome comments and suggestions for improvements to MET, especially information regarding errors. Comments may be submitted using the MET Feedback form available on the MET website. In addition, comments on this document would be greatly appreciated. While we cannot promise to incorporate all suggested changes, we will certainly take all suggestions into consideration. **-help** and **-version** command line options are available for all of the MET tools. Typing the name of the tool with no command line options also produces the usage statement. -The MET package is a "living" set of tools. Our goal is to continually enhance it and add to its capabilities. Because our time, resources, and talents are limited, we welcome contributed code for future versions of MET. These contributions may represent new verification methodologies, new analysis tools, or new plotting functions. For more information on contributing code to MET, please contact met_help@ucar.edu. +The MET package is a "living" set of tools. Our goal is to continually enhance it and add to its capabilities. Because our time, resources, and talents are limited, we welcome contributed code for future versions of MET. These contributions may represent new verification methodologies, new analysis tools, or new plotting functions. For more information on contributing code to MET, please create a post in the `METplus GitHub Discussions Forum `_. Fortify _______ diff --git a/met/docs/Users_Guide/tc-pairs.rst b/met/docs/Users_Guide/tc-pairs.rst index 24afaf814a..de8ff0f957 100644 --- a/met/docs/Users_Guide/tc-pairs.rst +++ b/met/docs/Users_Guide/tc-pairs.rst @@ -222,7 +222,7 @@ ____________________ time_offset = -14400; } -The **watch_warn** field specifies the file name and time applied offset to the **watch_warn** flag. The **file_name** string specifies the path of the watch/warning file to be used to determine when a watch or warning is in effect during the forecast initialization and verification times. The default file is named **wwpts_us.txt**, which is found in the installed *share/met/tc_data/* directory within the MET build. The **time_offset** string is the time window (in seconds) assigned to the watch/warning. Due to the non-uniform time watches and warnings are issued, a time window is assigned for which watch/warnings are included in the verification for each valid time. The default watch/warn file is static, and therefore may not include warned storms beyond the current MET code release date; therefore users may wish to contact met_help@ucar.edu to obtain the most recent watch/warning file if the static file does not contain storms of interest. +The **watch_warn** field specifies the file name and time applied offset to the **watch_warn** flag. The **file_name** string specifies the path of the watch/warning file to be used to determine when a watch or warning is in effect during the forecast initialization and verification times. The default file is named **wwpts_us.txt**, which is found in the installed *share/met/tc_data/* directory within the MET build. The **time_offset** string is the time window (in seconds) assigned to the watch/warning. Due to the non-uniform time watches and warnings are issued, a time window is assigned for which watch/warnings are included in the verification for each valid time. The default watch/warn file is static, and therefore may not include warned storms beyond the current MET code release date; therefore users may wish to create a post in the `METplus GitHub Discussions Forum `_ in order to obtain the most recent watch/warning file if the static file does not contain storms of interest. .. code-block:: none From 66bd0ec6cbc311e59ece1a730c1be75d492c78c5 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Tue, 13 Jul 2021 16:37:17 -0600 Subject: [PATCH 027/200] #1852 Removed unused nc_buf_size. Make cur and dim to the same size (called API handles 2D or 3D) --- met/src/tools/other/madis2nc/madis2nc.cc | 600 +++++++++++------------ 1 file changed, 288 insertions(+), 312 deletions(-) diff --git a/met/src/tools/other/madis2nc/madis2nc.cc b/met/src/tools/other/madis2nc/madis2nc.cc index 02ca9e6095..ba85dbffd0 100644 --- a/met/src/tools/other/madis2nc/madis2nc.cc +++ b/met/src/tools/other/madis2nc/madis2nc.cc @@ -70,7 +70,6 @@ using namespace netCDF; static const int FIELD_COUNT = 50; static const int BUFFER_SIZE = OBS_BUFFER_SIZE / FIELD_COUNT; -static int nc_buf_size; static MetNcPointObsOut nc_point_obs; static vector< Observation > obs_vector; static vector< ConcatString > md_files; @@ -867,9 +866,9 @@ void process_madis_metar(NcFile *&f_in) { // Arrays of longs for indexing into NetCDF variables // long *cur = new long [2]; - long *dim = new long [1]; + long *dim = new long [2]; cur[0] = cur[1] = 0; - dim[0] = 1; + dim[0] = dim[1] = 1; int hdr_idx = 0; processed_count = 0; @@ -878,7 +877,6 @@ void process_madis_metar(NcFile *&f_in) { // Loop through each record and get the header data. // for(i_hdr_s=rec_beg; i_hdr_s BUFFER_SIZE) ? BUFFER_SIZE: (my_rec_end - i_hdr_s); dim[0] = buf_size; cur[0] = i_hdr_s; @@ -921,9 +919,6 @@ void process_madis_metar(NcFile *&f_in) { char hdr_typ_arr[buf_size][hdr_typ_len]; char hdr_sid_arr[buf_size][hdr_sid_len]; - nc_buf_size = buf_size * FIELD_COUNT; - if (nc_buf_size > BUFFER_SIZE) nc_buf_size = BUFFER_SIZE; - get_nc_data(&in_hdr_vld_var, &tmp_dbl_arr[0], buf_size, i_hdr_s); get_nc_data(&in_hdr_lat_var, &hdr_lat_arr[0], buf_size, i_hdr_s); get_nc_data(&in_hdr_lon_var, &hdr_lon_arr[0], buf_size, i_hdr_s); @@ -973,11 +968,11 @@ void process_madis_metar(NcFile *&f_in) { get_filtered_nc_data(precip24Hour_var, precip24Hour, buf_size, i_hdr_s, "precip24Hour" ); get_filtered_nc_data(snowCover_var, snowCover, buf_size, i_hdr_s, "snowCover" ); - dim2D[0] = buf_size; - dim2D[1] = hdr_typ_len; - get_nc_data(&in_hdr_typ_var, (char *)&hdr_typ_arr[0], dim2D, cur); - dim2D[1] = hdr_sid_len; - get_nc_data(&in_hdr_sid_var, (char *)&hdr_sid_arr[0], dim2D, cur); + dim[0] = buf_size; + dim[1] = hdr_typ_len; + get_nc_data(&in_hdr_typ_var, (char *)&hdr_typ_arr[0], dim, cur); + dim[1] = hdr_sid_len; + get_nc_data(&in_hdr_sid_var, (char *)&hdr_sid_arr[0], dim, cur); for (i_idx=0; i_idx BUFFER_SIZE) ? BUFFER_SIZE: (my_rec_end - i_hdr_s); int nlvl_manLevel[buf_size]; @@ -1443,9 +1436,6 @@ void process_madis_raob(NcFile *&f_in) { //char *hdr_typ_arr_ptr = &hdr_typ_arr[0]; //char *hdr_sid_arr_ptr = &hdr_sid_arr[0]; - nc_buf_size = buf_size * FIELD_COUNT; - if (nc_buf_size > BUFFER_SIZE) nc_buf_size = BUFFER_SIZE; - cur[0] = i_hdr_s; dim[0] = buf_size; @@ -1462,97 +1452,95 @@ void process_madis_raob(NcFile *&f_in) { get_nc_data(&in_hdr_lon_var, hdr_lon_arr, buf_size, i_hdr_s); get_filtered_nc_data(in_hdr_elv_var, hdr_elv_arr, buf_size, i_hdr_s, "eleveation"); - dim2D[0] = buf_size; - //dim2D[1] = hdr_typ_len; - //get_nc_data(in_hdr_typ_var, (char *)&hdr_typ_arr[0], dim2D, cur); - dim2D[1] = hdr_sid_len; - get_nc_data(&in_hdr_sid_var, (char *)&hdr_sid_arr, dim2D, cur); - - dim3D[0] = buf_size; - dim3D[1] = maxlvl_manLevel; - if (IS_VALID_NC(prManQty_var)) get_nc_data(&prManQty_var, (char *)&prManQty, dim3D, cur); - else memset(prManQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(htManQty_var)) get_nc_data(&htManQty_var, (char *)&htManQty, dim3D, cur); - else memset(htManQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(tpManQty_var)) get_nc_data(&tpManQty_var, (char *)&tpManQty, dim3D, cur); - else memset(tpManQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(tdManQty_var)) get_nc_data(&tdManQty_var, (char *)&tdManQty, dim3D, cur); - else memset(tdManQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(wdManQty_var)) get_nc_data(&wdManQty_var, (char *)&wdManQty, dim3D, cur); - else memset(wdManQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(wsManQty_var)) get_nc_data(&wsManQty_var, (char *)&wsManQty, dim3D, cur); - else memset(wsManQty, 0, buf_size*dim3D[1]*sizeof(char)); - dim3D[1] = maxlvl_sigTLevel; - if (IS_VALID_NC(prSigTQty_var)) get_nc_data(&prSigTQty_var, (char *)&prSigTQty, dim3D, cur); - else memset(prSigTQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(tpSigTQty_var)) get_nc_data(&tpSigTQty_var, (char *)&tpSigTQty, dim3D, cur); - else memset(tpSigTQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(tdSigTQty_var)) get_nc_data(&tdSigTQty_var, (char *)&tdSigTQty, dim3D, cur); - else memset(tdSigTQty, 0, buf_size*dim3D[1]*sizeof(char)); - dim3D[1] = maxlvl_sigWLevel; - if (IS_VALID_NC(htSigWQty_var)) get_nc_data(&htSigWQty_var, (char *)&htSigWQty, dim3D, cur); - else memset(htSigWQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(wdSigWQty_var)) get_nc_data(&wdSigWQty_var, (char *)&wdSigWQty, dim3D, cur); - else memset(wdSigWQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(wsSigWQty_var)) get_nc_data(&wsSigWQty_var, (char *)&wsSigWQty, dim3D, cur); - else memset(wsSigWQty, 0, buf_size*dim3D[1]*sizeof(char)); - dim3D[1] = maxlvl_sigPresWLevel; - if (IS_VALID_NC(prSigWQty_var )) get_nc_data(&prSigWQty_var , (char *)&prSigWQty, dim3D, cur); - else memset(prSigWQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(wdSigPrWQty_var)) get_nc_data(&wdSigPrWQty_var, (char *)&wdSigPrWQty, dim3D, cur); - else memset(wdSigPrWQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(wsSigPrWQty_var)) get_nc_data(&wsSigPrWQty_var, (char *)&wsSigPrWQty, dim3D, cur); - else memset(wsSigPrWQty, 0, buf_size*dim3D[1]*sizeof(char)); - dim3D[1] = maxlvl_mTropNum; - if (IS_VALID_NC(prTropQty_var)) get_nc_data(&prTropQty_var, (char *)&prTropQty, dim3D, cur); - else memset(prTropQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(tpTropQty_var)) get_nc_data(&tpTropQty_var, (char *)&tpTropQty, dim3D, cur); - else memset(tpTropQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(tdTropQty_var)) get_nc_data(&tdTropQty_var, (char *)&tdTropQty, dim3D, cur); - else memset(tdTropQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(wdTropQty_var)) get_nc_data(&wdTropQty_var, (char *)&wdTropQty, dim3D, cur); - else memset(wdTropQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(wsTropQty_var)) get_nc_data(&wsTropQty_var, (char *)&wsTropQty, dim3D, cur); - else memset(wsTropQty, 0, buf_size*dim3D[1]*sizeof(char)); - dim3D[1] = maxlvl_mWndNum; - if (IS_VALID_NC(prMaxWQty_var)) get_nc_data(&prMaxWQty_var, (char *)&prMaxWQty, dim3D, cur); - else memset(prMaxWQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(wdMaxWQty_var)) get_nc_data(&wdMaxWQty_var, (char *)&wdMaxWQty, dim3D, cur); - else memset(wdMaxWQty, 0, buf_size*dim3D[1]*sizeof(char)); - if (IS_VALID_NC(wsMaxWQty_var)) get_nc_data(&wsMaxWQty_var, (char *)&wsMaxWQty, dim3D, cur); - else memset(wsMaxWQty, 0, buf_size*dim3D[1]*sizeof(char)); - - dim3D[1] = maxlvl_manLevel; - get_filtered_nc_data_2d(prMan_var, (float *)&prMan[0], dim3D, cur, "prMan"); - get_filtered_nc_data_2d(htMan_var, (float *)&htMan[0], dim3D, cur, "htMan"); - get_filtered_nc_data_2d(tpMan_var, (float *)&tpMan[0], dim3D, cur, "tpMan"); - get_filtered_nc_data_2d(tdMan_var, (float *)&tdMan[0], dim3D, cur, "tdMan"); - get_filtered_nc_data_2d(wdMan_var, (float *)&wdMan[0], dim3D, cur, "wdMan"); - get_filtered_nc_data_2d(wsMan_var, (float *)&wsMan[0], dim3D, cur, "wsMan"); - dim3D[1] = maxlvl_sigTLevel; - get_filtered_nc_data_2d(prSigT_var, (float *)&prSigT, dim3D, cur, "prSigT"); - get_filtered_nc_data_2d(tpSigT_var, (float *)&tpSigT, dim3D, cur, "tpSigT"); - get_filtered_nc_data_2d(tdSigT_var, (float *)&tdSigT, dim3D, cur, "tdSigT"); - dim3D[1] = maxlvl_sigWLevel; - get_filtered_nc_data_2d(htSigW_var, (float *)&htSigW, dim3D, cur, "htSigW"); - get_filtered_nc_data_2d(wdSigW_var, (float *)&wdSigW, dim3D, cur, "wdSigW"); - get_filtered_nc_data_2d(wsSigW_var, (float *)&wsSigW, dim3D, cur, "wsSigW"); - dim3D[1] = maxlvl_sigPresWLevel; - get_filtered_nc_data_2d(prSigW_var , (float *)&prSigW, dim3D, cur, "prSigW"); - get_filtered_nc_data_2d(wdSigPrW_var, (float *)&wdSigPrW, dim3D, cur, "wdSigPrW"); - get_filtered_nc_data_2d(wsSigPrW_var, (float *)&wsSigPrW, dim3D, cur, "wsSigPrW"); - dim3D[1] = maxlvl_mTropNum; - get_filtered_nc_data_2d(prTrop_var, (float *)&prTrop, dim3D, cur, "prTrop"); - get_filtered_nc_data_2d(tpTrop_var, (float *)&tpTrop, dim3D, cur, "tpTrop"); - get_filtered_nc_data_2d(tdTrop_var, (float *)&tdTrop, dim3D, cur, "tdTrop"); - get_filtered_nc_data_2d(wdTrop_var, (float *)&wdTrop, dim3D, cur, "wdTrop"); - get_filtered_nc_data_2d(wsTrop_var, (float *)&wsTrop, dim3D, cur, "wsTrop"); - dim3D[1] = maxlvl_mWndNum; - get_filtered_nc_data_2d(prMaxW_var, (float *)&prMaxW, dim3D, cur, "prMaxW"); - get_filtered_nc_data_2d(wdMaxW_var, (float *)&wdMaxW, dim3D, cur, "wdMaxW"); - get_filtered_nc_data_2d(wsMaxW_var, (float *)&wsMaxW, dim3D, cur, "wsMaxW"); + dim[0] = buf_size; + //dim[1] = hdr_typ_len; + //get_nc_data(in_hdr_typ_var, (char *)&hdr_typ_arr[0], dim, cur); + dim[1] = hdr_sid_len; + get_nc_data(&in_hdr_sid_var, (char *)&hdr_sid_arr, dim, cur); - dim[0] = 1; + dim[0] = buf_size; + dim[1] = maxlvl_manLevel; + if (IS_VALID_NC(prManQty_var)) get_nc_data(&prManQty_var, (char *)&prManQty, dim, cur); + else memset(prManQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(htManQty_var)) get_nc_data(&htManQty_var, (char *)&htManQty, dim, cur); + else memset(htManQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(tpManQty_var)) get_nc_data(&tpManQty_var, (char *)&tpManQty, dim, cur); + else memset(tpManQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(tdManQty_var)) get_nc_data(&tdManQty_var, (char *)&tdManQty, dim, cur); + else memset(tdManQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(wdManQty_var)) get_nc_data(&wdManQty_var, (char *)&wdManQty, dim, cur); + else memset(wdManQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(wsManQty_var)) get_nc_data(&wsManQty_var, (char *)&wsManQty, dim, cur); + else memset(wsManQty, 0, buf_size*dim[1]*sizeof(char)); + dim[1] = maxlvl_sigTLevel; + if (IS_VALID_NC(prSigTQty_var)) get_nc_data(&prSigTQty_var, (char *)&prSigTQty, dim, cur); + else memset(prSigTQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(tpSigTQty_var)) get_nc_data(&tpSigTQty_var, (char *)&tpSigTQty, dim, cur); + else memset(tpSigTQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(tdSigTQty_var)) get_nc_data(&tdSigTQty_var, (char *)&tdSigTQty, dim, cur); + else memset(tdSigTQty, 0, buf_size*dim[1]*sizeof(char)); + dim[1] = maxlvl_sigWLevel; + if (IS_VALID_NC(htSigWQty_var)) get_nc_data(&htSigWQty_var, (char *)&htSigWQty, dim, cur); + else memset(htSigWQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(wdSigWQty_var)) get_nc_data(&wdSigWQty_var, (char *)&wdSigWQty, dim, cur); + else memset(wdSigWQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(wsSigWQty_var)) get_nc_data(&wsSigWQty_var, (char *)&wsSigWQty, dim, cur); + else memset(wsSigWQty, 0, buf_size*dim[1]*sizeof(char)); + dim[1] = maxlvl_sigPresWLevel; + if (IS_VALID_NC(prSigWQty_var )) get_nc_data(&prSigWQty_var , (char *)&prSigWQty, dim, cur); + else memset(prSigWQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(wdSigPrWQty_var)) get_nc_data(&wdSigPrWQty_var, (char *)&wdSigPrWQty, dim, cur); + else memset(wdSigPrWQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(wsSigPrWQty_var)) get_nc_data(&wsSigPrWQty_var, (char *)&wsSigPrWQty, dim, cur); + else memset(wsSigPrWQty, 0, buf_size*dim[1]*sizeof(char)); + dim[1] = maxlvl_mTropNum; + if (IS_VALID_NC(prTropQty_var)) get_nc_data(&prTropQty_var, (char *)&prTropQty, dim, cur); + else memset(prTropQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(tpTropQty_var)) get_nc_data(&tpTropQty_var, (char *)&tpTropQty, dim, cur); + else memset(tpTropQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(tdTropQty_var)) get_nc_data(&tdTropQty_var, (char *)&tdTropQty, dim, cur); + else memset(tdTropQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(wdTropQty_var)) get_nc_data(&wdTropQty_var, (char *)&wdTropQty, dim, cur); + else memset(wdTropQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(wsTropQty_var)) get_nc_data(&wsTropQty_var, (char *)&wsTropQty, dim, cur); + else memset(wsTropQty, 0, buf_size*dim[1]*sizeof(char)); + dim[1] = maxlvl_mWndNum; + if (IS_VALID_NC(prMaxWQty_var)) get_nc_data(&prMaxWQty_var, (char *)&prMaxWQty, dim, cur); + else memset(prMaxWQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(wdMaxWQty_var)) get_nc_data(&wdMaxWQty_var, (char *)&wdMaxWQty, dim, cur); + else memset(wdMaxWQty, 0, buf_size*dim[1]*sizeof(char)); + if (IS_VALID_NC(wsMaxWQty_var)) get_nc_data(&wsMaxWQty_var, (char *)&wsMaxWQty, dim, cur); + else memset(wsMaxWQty, 0, buf_size*dim[1]*sizeof(char)); + + dim[1] = maxlvl_manLevel; + get_filtered_nc_data_2d(prMan_var, (float *)&prMan[0], dim, cur, "prMan"); + get_filtered_nc_data_2d(htMan_var, (float *)&htMan[0], dim, cur, "htMan"); + get_filtered_nc_data_2d(tpMan_var, (float *)&tpMan[0], dim, cur, "tpMan"); + get_filtered_nc_data_2d(tdMan_var, (float *)&tdMan[0], dim, cur, "tdMan"); + get_filtered_nc_data_2d(wdMan_var, (float *)&wdMan[0], dim, cur, "wdMan"); + get_filtered_nc_data_2d(wsMan_var, (float *)&wsMan[0], dim, cur, "wsMan"); + dim[1] = maxlvl_sigTLevel; + get_filtered_nc_data_2d(prSigT_var, (float *)&prSigT, dim, cur, "prSigT"); + get_filtered_nc_data_2d(tpSigT_var, (float *)&tpSigT, dim, cur, "tpSigT"); + get_filtered_nc_data_2d(tdSigT_var, (float *)&tdSigT, dim, cur, "tdSigT"); + dim[1] = maxlvl_sigWLevel; + get_filtered_nc_data_2d(htSigW_var, (float *)&htSigW, dim, cur, "htSigW"); + get_filtered_nc_data_2d(wdSigW_var, (float *)&wdSigW, dim, cur, "wdSigW"); + get_filtered_nc_data_2d(wsSigW_var, (float *)&wsSigW, dim, cur, "wsSigW"); + dim[1] = maxlvl_sigPresWLevel; + get_filtered_nc_data_2d(prSigW_var , (float *)&prSigW, dim, cur, "prSigW"); + get_filtered_nc_data_2d(wdSigPrW_var, (float *)&wdSigPrW, dim, cur, "wdSigPrW"); + get_filtered_nc_data_2d(wsSigPrW_var, (float *)&wsSigPrW, dim, cur, "wsSigPrW"); + dim[1] = maxlvl_mTropNum; + get_filtered_nc_data_2d(prTrop_var, (float *)&prTrop, dim, cur, "prTrop"); + get_filtered_nc_data_2d(tpTrop_var, (float *)&tpTrop, dim, cur, "tpTrop"); + get_filtered_nc_data_2d(tdTrop_var, (float *)&tdTrop, dim, cur, "tdTrop"); + get_filtered_nc_data_2d(wdTrop_var, (float *)&wdTrop, dim, cur, "wdTrop"); + get_filtered_nc_data_2d(wsTrop_var, (float *)&wsTrop, dim, cur, "wsTrop"); + dim[1] = maxlvl_mWndNum; + get_filtered_nc_data_2d(prMaxW_var, (float *)&prMaxW, dim, cur, "prMaxW"); + get_filtered_nc_data_2d(wdMaxW_var, (float *)&wdMaxW, dim, cur, "wdMaxW"); + get_filtered_nc_data_2d(wsMaxW_var, (float *)&wsMaxW, dim, cur, "wsMaxW"); for (int i_idx=0; i_idx BUFFER_SIZE) nc_buf_size = BUFFER_SIZE; - cur[0] = i_hdr_s; dim[0] = buf_size; get_nc_data(&in_hdr_vld_var, tmp_dbl_arr, buf_size, i_hdr_s); @@ -2211,14 +2196,14 @@ void process_madis_profiler(NcFile *&f_in) { // Wind U obs_arr[4] = uComponent_arr[i_idx][i_lvl]; count += process_obs(33, conversion, obs_arr, uComponentQty_arr[i_idx][i_lvl], - in_uComponent_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_uComponent_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Wind V obs_arr[4] = vComponent_arr[i_idx][i_lvl]; count += process_obs(34, conversion, obs_arr, vComponentQty_arr[i_idx][i_lvl], - in_vComponent_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_vComponent_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); } // end for i_lvl @@ -2357,9 +2342,9 @@ void process_madis_maritime(NcFile *&f_in) { // // Arrays of longs for indexing into NetCDF variables // - long *cur = new long [3]; + long *cur = new long [3]; // NetCDF API handles 2D or 3D cur[0] = cur[1] = cur[2] = 0; - long *dim = new long [3]; + long *dim = new long [3]; // NetCDF API handles 2D or 3D dim[0] = dim[1] = dim[2] = 1; int hdr_idx = 0; @@ -2406,9 +2391,6 @@ void process_madis_maritime(NcFile *&f_in) { char precip18HourQty_arr[buf_size]; char precip24HourQty_arr[buf_size]; - nc_buf_size = buf_size * FIELD_COUNT; - if (nc_buf_size > BUFFER_SIZE) nc_buf_size = BUFFER_SIZE; - cur[0] = i_hdr_s; dim[0] = buf_size; get_nc_data(&in_hdr_vld_var, tmp_dbl_arr, buf_size, i_hdr_s); @@ -2534,73 +2516,73 @@ void process_madis_maritime(NcFile *&f_in) { // Wind Direction obs_arr[4] = windDir_arr[i_idx]; count += process_obs(31, conversion, obs_arr, windDirQty_arr[i_idx], - in_windDir_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_windDir_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Wind Speed obs_arr[4] = windSpeed_arr[i_idx]; count += process_obs(32, conversion, obs_arr, windSpeedQty_arr[i_idx], - in_windSpeed_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_windSpeed_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Temperature obs_arr[4] = temperature_arr[i_idx]; count += process_obs(11, conversion, obs_arr, temperatureQty_arr[i_idx], - in_temperature_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_temperature_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Dew Point temperature obs_arr[4] = dewpoint_arr[i_idx]; count += process_obs(17, conversion, obs_arr, dewpointQty_arr[i_idx], - in_dewpoint_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_dewpoint_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Pressure reduced to MSL obs_arr[4] = seaLevelPress_arr[i_idx]; count += process_obs(2, conversion, obs_arr, seaLevelPressQty_arr[i_idx], - in_seaLevelPress_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_seaLevelPress_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Surface wind gust obs_arr[4] = windGust_arr[i_idx]; count += process_obs(180, conversion, obs_arr, windGustQty_arr[i_idx], - in_windGust_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_windGust_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // APCP_01 obs_arr[2] = 3600; obs_arr[4] = precip1Hour_arr[i_idx]; count += process_obs(61, conversion, obs_arr, precip1HourQty_arr[i_idx], - in_precip1Hour_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_precip1Hour_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // APCP_06 obs_arr[2] = 21600; obs_arr[4] = precip6Hour_arr[i_idx]; count += process_obs(61, conversion, obs_arr, precip6HourQty_arr[i_idx], - in_precip6Hour_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_precip6Hour_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // APCP_12 obs_arr[2] = 43200; obs_arr[4] = precip12Hour_arr[i_idx]; count += process_obs(61, conversion, obs_arr, precip12HourQty_arr[i_idx], - in_precip12Hour_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_precip12Hour_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // APCP_18 obs_arr[2] = 64800; obs_arr[4] = precip18Hour_arr[i_idx]; count += process_obs(61, conversion, obs_arr, precip18HourQty_arr[i_idx], - in_precip18Hour_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_precip18Hour_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // APCP_24 obs_arr[2] = 86400; obs_arr[4] = precip24Hour_arr[i_idx]; count += process_obs(61, conversion, obs_arr, precip24HourQty_arr[i_idx], - in_precip24Hour_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_precip24Hour_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); } @@ -2779,7 +2761,7 @@ void process_madis_mesonet(NcFile *&f_in) { long *cur = new long [2]; cur[0] = cur[1] = 0; long *dim = new long [2]; - dim[0] = 1; + dim[0] = dim[1] = 1; int hdr_idx = 0; @@ -2847,9 +2829,6 @@ void process_madis_mesonet(NcFile *&f_in) { char windDir10Qty_arr[buf_size]; char windSpeed10Qty_arr[buf_size]; - nc_buf_size = buf_size * FIELD_COUNT; - if (nc_buf_size > BUFFER_SIZE) nc_buf_size = BUFFER_SIZE; - cur[0] = i_hdr_s; dim[0] = buf_size; @@ -2994,46 +2973,46 @@ void process_madis_mesonet(NcFile *&f_in) { // Temperature obs_arr[4] = temperature_arr[i_idx]; count += process_obs(11, conversion, obs_arr, temperatureQty_arr[i_idx], - in_temperature_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_temperature_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Dewpoint obs_arr[4] = dewpoint_arr[i_idx]; count += process_obs(17, conversion, obs_arr, dewpointQty_arr[i_idx], - in_dewpoint_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_dewpoint_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Relative Humidity obs_arr[4] = relHumidity_arr[i_idx]; count += process_obs(52, conversion, obs_arr, relHumidityQty_arr[i_idx], - in_relHumidity_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_relHumidity_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Station Pressure obs_arr[4] = stationPressure_arr[i_idx]; count += process_obs(1, conversion, obs_arr, stationPressureQty_arr[i_idx], - in_stationPressure_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_stationPressure_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Sea Level Pressure obs_arr[4] = seaLevelPressure_arr[i_idx]; count += process_obs(2, conversion, obs_arr, seaLevelPressureQty_arr[i_idx], - in_seaLevelPressure_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_seaLevelPressure_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Wind Direction obs_arr[4] = windDir_arr[i_idx]; count += process_obs(31, conversion, obs_arr, windDirQty_arr[i_idx], - in_windDir_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_windDir_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); wdir = obs_arr[4]; // Wind Speed obs_arr[4] = windSpeed_arr[i_idx]; char qty = windSpeedQty_arr[i_idx]; count += process_obs(32, conversion, obs_arr, qty, - in_windSpeed_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_windSpeed_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); wind = obs_arr[4]; // Convert the wind direction and speed into U and V components @@ -3042,105 +3021,105 @@ void process_madis_mesonet(NcFile *&f_in) { // Write U-component of wind obs_arr[4] = ugrd; count += process_obs(33, conversion, obs_arr, qty, in_windSpeed_var, - hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Write V-component of wind obs_arr[4] = vgrd; count += process_obs(34, conversion, obs_arr, qty, in_windSpeed_var, - hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Wind Gust obs_arr[4] = windGust_arr[i_idx]; count += process_obs(180, conversion, obs_arr, windGustQty_arr[i_idx], - in_windGust_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_windGust_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Visibility obs_arr[4] = visibility_arr[i_idx]; count += process_obs(20, conversion, obs_arr, visibilityQty_arr[i_idx], - in_visibility_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_visibility_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Precipitation Rate // Convert input meters/second to output millimeters/second obs_arr[4] = precipRate_arr[i_idx]; count += process_obs(59, 1000.0, obs_arr, precipRateQty_arr[i_idx], - in_precipRate_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_precipRate_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Solar Radiation obs_arr[4] = solarRadiation_arr[i_idx]; count += process_obs(250, conversion, obs_arr, solarRadiationQty_arr[i_idx], - in_solarRadiation_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_solarRadiation_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Sea Surface Temperature obs_arr[4] = seaSurfaceTemp_arr[i_idx]; count += process_obs(80, conversion, obs_arr, seaSurfaceTempQty_arr[i_idx], - in_seaSurfaceTemp_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_seaSurfaceTemp_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Precipitable Water // Convert input cm to output mm obs_arr[4] = totalColumnPWV_arr[i_idx]; count += process_obs(54, 10.0, obs_arr, totalColumnPWVQty_arr[i_idx], - in_totalColumnPWV_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_totalColumnPWV_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Soil Temperature obs_arr[4] = soilTemperature_arr[i_idx]; count += process_obs(85, conversion, obs_arr, soilTemperatureQty_arr[i_idx], - in_soilTemperature_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_soilTemperature_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Minimum Temperature obs_arr[4] = minTemp24Hour_arr[i_idx]; count += process_obs(16, conversion, obs_arr, minTemp24HourQty_arr[i_idx], - in_minTemp24Hour_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_minTemp24Hour_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Maximum Temperature obs_arr[4] = maxTemp24Hour_arr[i_idx]; count += process_obs(15, conversion, obs_arr, maxTemp24HourQty_arr[i_idx], - in_maxTemp24Hour_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_maxTemp24Hour_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Precipitation - 3 Hour obs_arr[2] = 3.0*sec_per_hour; obs_arr[4] = precip3hr_arr[i_idx]; count += process_obs(61, conversion, obs_arr, precip3hrQty_arr[i_idx], - in_precip3hr_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_precip3hr_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Precipitation - 6 Hour obs_arr[2] = 6.0*sec_per_hour; obs_arr[4] = precip6hr_arr[i_idx]; count += process_obs(61, conversion, obs_arr, precip6hrQty_arr[i_idx], - in_precip6hr_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_precip6hr_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Precipitation - 12 Hour obs_arr[2] = 12.0*sec_per_hour; obs_arr[4] = precip12hr_arr[i_idx]; count += process_obs(61, conversion, obs_arr, precip12hrQty_arr[i_idx], - in_precip12hr_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_precip12hr_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Precipitation - 10 minutes obs_arr[2] = 600; obs_arr[4] = precip10min_arr[i_idx]; count += process_obs(61, conversion, obs_arr, precip10minQty_arr[i_idx], - in_precip10min_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_precip10min_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Precipitation - 1 minutes obs_arr[2] = 60; obs_arr[4] = precip1min_arr[i_idx]; count += process_obs(61, conversion, obs_arr, precip1minQty_arr[i_idx], - in_precip1min_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_precip1min_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Set the level to bad data and the height to 10 meters obs_arr[2] = bad_data_float; @@ -3149,16 +3128,16 @@ void process_madis_mesonet(NcFile *&f_in) { // 10m Wind Direction obs_arr[4] = windDir10_arr[i_idx]; count += process_obs(31, conversion, obs_arr, windDir10Qty_arr[i_idx], - in_windDir10_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_windDir10_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); wdir = obs_arr[4]; // 10m Wind Speed qty = windSpeed10Qty_arr[i_idx]; obs_arr[4] = windSpeed10_arr[i_idx]; count += process_obs(32, conversion, obs_arr, qty, in_windSpeed10_var, - hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); wind = obs_arr[4]; // Convert the wind direction and speed into U and V components @@ -3167,8 +3146,8 @@ void process_madis_mesonet(NcFile *&f_in) { // Write U-component of 10m wind obs_arr[4] = ugrd; count += process_obs(33, conversion, obs_arr, qty, in_windSpeed10_var, - hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Write V-component of 10m wind obs_arr[4] = vgrd; @@ -3176,8 +3155,8 @@ void process_madis_mesonet(NcFile *&f_in) { // hdr_typ, hdr_sid, hdr_vld, // hdr_arr[0], hdr_arr[1], hdr_arr[2]); process_obs(34, conversion, obs_arr, qty, in_windSpeed10_var, - hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); } @@ -3272,10 +3251,10 @@ void process_madis_acarsProfiles(NcFile *&f_in) { // // Arrays of longs for indexing into NetCDF variables // - long *cur = new long [3]; - cur[0] = cur[1] = cur[2] = 0; - long *dim = new long [3]; - dim[0] = dim[1] = dim[2] = 1; + long *cur = new long [2]; + cur[0] = cur[1] = 0; + long *dim = new long [2]; + dim[0] = dim[1] = 1; // // Get the number of levels @@ -3348,9 +3327,6 @@ void process_madis_acarsProfiles(NcFile *&f_in) { char windSpeedQty_arr[buf_size][maxLevels]; char altitudeQty_arr[buf_size][maxLevels]; - nc_buf_size = buf_size * FIELD_COUNT; - if (nc_buf_size > BUFFER_SIZE) nc_buf_size = BUFFER_SIZE; - cur[0] = i_hdr_s; dim[0] = buf_size; dim[1] = maxLevels; @@ -3491,28 +3467,28 @@ void process_madis_acarsProfiles(NcFile *&f_in) { // Temperature obs_arr[4] = temperature_arr[i_idx][i_lvl]; count += process_obs(11, conversion, obs_arr, temperatureQty_arr[i_idx][i_lvl], - in_temperature_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_temperature_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Dewpoint obs_arr[4] = dewpoint_arr[i_idx][i_lvl]; count += process_obs(17, conversion, obs_arr, dewpointQty_arr[i_idx][i_lvl], - in_dewpoint_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_dewpoint_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Wind Direction obs_arr[4] = windDir_arr[i_idx][i_lvl]; count += process_obs(31, conversion, obs_arr, windDirQty_arr[i_idx][i_lvl], - in_windDir_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_windDir_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); wdir = obs_arr[4]; // Wind Speed obs_arr[4] = windSpeed_arr[i_idx][i_lvl]; qty = windSpeedQty_arr[i_idx][i_lvl]; count += process_obs(32, conversion, obs_arr, qty, - in_windSpeed_var, hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + in_windSpeed_var, hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); wind = obs_arr[4]; // Convert the wind direction and speed into U and V components @@ -3521,17 +3497,17 @@ void process_madis_acarsProfiles(NcFile *&f_in) { // Write U-component of wind obs_arr[4] = ugrd; count += process_obs(33, conversion, obs_arr, qty, in_windSpeed_var, - hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); // Write V-component of wind obs_arr[4] = vgrd; //count += process_obs(34, conversion, obs_arr, qty, in_windSpeed_var, - // hdr_typ, hdr_sid, hdr_vld, - // hdr_arr[0], hdr_arr[1], hdr_arr[2]); + // hdr_typ, hdr_sid, hdr_vld, + // hdr_arr[0], hdr_arr[1], hdr_arr[2]); process_obs(34, conversion, obs_arr, qty, in_windSpeed_var, - hdr_typ, hdr_sid, hdr_vld, - hdr_arr[0], hdr_arr[1], hdr_arr[2]); + hdr_typ, hdr_sid, hdr_vld, + hdr_arr[0], hdr_arr[1], hdr_arr[2]); } // end for i_lvl } From 6bbf9006853ec93db430e5403497a0dbc5bab4ce Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Tue, 13 Jul 2021 16:38:08 -0600 Subject: [PATCH 028/200] #1852 Check the start and count before calling NetCDF API --- met/src/libcode/vx_nc_util/nc_utils.cc | 105 +++++++++++++++++++------ 1 file changed, 83 insertions(+), 22 deletions(-) diff --git a/met/src/libcode/vx_nc_util/nc_utils.cc b/met/src/libcode/vx_nc_util/nc_utils.cc index eb066df60a..5ee664a17e 100644 --- a/met/src/libcode/vx_nc_util/nc_utils.cc +++ b/met/src/libcode/vx_nc_util/nc_utils.cc @@ -1030,7 +1030,7 @@ char get_char_val(NcVar *var, const int index) { //////////////////////////////////////////////////////////////////////// ConcatString* get_string_val(NcFile * nc, const char * var_name, const int index, - const int len, ConcatString &tmp_cs) { + const int len, ConcatString &tmp_cs) { NcVar var = get_var(nc, var_name); return (get_string_val(&var, index, len, tmp_cs)); @@ -1039,10 +1039,22 @@ ConcatString* get_string_val(NcFile * nc, const char * var_name, const int index //////////////////////////////////////////////////////////////////////// ConcatString* get_string_val(NcVar *var, const int index, - const int len, ConcatString &tmp_cs) { + const int len, ConcatString &tmp_cs) { + int dim_idx = 0; char tmp_str[len]; std::vector start; std::vector count; + const char *method_name = "get_string_val() "; + + int dim_size = get_dim_size(var, dim_idx); + if ((index+len) > dim_size) { + NcDim nc_dim = get_nc_dim(var, dim_idx); + mlog << Error << "\n" << method_name << "The requested start offset and count (" + << index << ", " << len << ") exceeds the dimension[" << dim_idx << "]=" << dim_size << " " + << (IS_VALID_NC(nc_dim) ? GET_NC_NAME(nc_dim) : " ") + << " for the variable " << GET_NC_NAME_P(var) << ".\n\n"; + exit(1); + } // // Retrieve the character array value from the NetCDF variable. @@ -1074,9 +1086,21 @@ int get_int_var(NcVar * var, const int index) { int k; std::vector start; std::vector count; + const char *method_name = "get_int_var() "; k = bad_data_int; if (IS_VALID_NC_P(var)) { + int dim_idx = 0; + int dim_size = get_dim_size(var, dim_idx); + if (index > dim_size) { + NcDim nc_dim = get_nc_dim(var, dim_idx); + mlog << Error << "\n" << method_name << "The requested start offset (" + << index << ") exceeds the dimension[" << dim_idx << "]=" << dim_size << " " + << (IS_VALID_NC(nc_dim) ? GET_NC_NAME(nc_dim) : " ") + << " for the variable " << GET_NC_NAME_P(var) << ".\n\n"; + exit(1); + } + start.push_back(index); count.push_back(1); var->getVar(start, count, &k); @@ -1095,6 +1119,17 @@ double get_nc_time(NcVar * var, const int index) { k = bad_data_double; if (IS_VALID_NC_P(var)) { + int dim_idx = 0; + int dim_size = get_dim_size(var, dim_idx); + if (index > dim_size) { + NcDim nc_dim = get_nc_dim(var, dim_idx); + mlog << Error << "\n" << method_name << "The requested start offset (" + << index << ") exceeds the dimension[" << dim_idx << "]=" << dim_size << " " + << (IS_VALID_NC(nc_dim) ? GET_NC_NAME(nc_dim) : " ") + << " for the variable " << GET_NC_NAME_P(var) << ".\n\n"; + exit(1); + } + start.push_back(index); count.push_back(1); @@ -1160,9 +1195,21 @@ float get_float_var(NcVar * var, const int index) { float k; std::vector start; std::vector count; + const char *method_name = "get_float_var() -> "; k = bad_data_float; if (IS_VALID_NC_P(var)) { + int dim_idx = 0; + int dim_size = get_dim_size(var, dim_idx); + if (index > dim_size) { + NcDim nc_dim = get_nc_dim(var, dim_idx); + mlog << Error << "\n" << method_name << "The requested start offset (" + << index << ") exceeds the dimension[" << dim_idx << "]=" << dim_size << " " + << (IS_VALID_NC(nc_dim) ? GET_NC_NAME(nc_dim) : " ") + << " for the variable " << GET_NC_NAME_P(var) << ".\n\n"; + exit(1); + } + start.push_back(index); count.push_back(1); var->getVar(start, count, &k); @@ -1228,6 +1275,7 @@ bool get_nc_data(NcVar *var, int *data) { template bool _get_nc_data(NcVar *var, T *data, T bad_data, const long *curs) { bool return_status = false; + const char *method_name = "_get_nc_data(const long *curs) "; if (IS_VALID_NC_P(var)) { std::vector start; @@ -1235,6 +1283,15 @@ bool _get_nc_data(NcVar *var, T *data, T bad_data, const long *curs) { const int dimC = get_dim_count(var); for (int idx = 0 ; idx < dimC; idx++) { + int dim_size = get_dim_size(var, idx); + if (curs[idx] > dim_size) { + NcDim nc_dim = get_nc_dim(var, idx); + mlog << Error << "\n" << method_name << "The requested start offset (" + << curs[idx] << ") exceeds the dimension[" << idx << "]=" << dim_size << " " + << (IS_VALID_NC(nc_dim) ? GET_NC_NAME(nc_dim) : " ") + << " for the variable " << GET_NC_NAME_P(var) << ".\n\n"; + exit(1); + } start.push_back((size_t)curs[idx]); count.push_back((size_t)1); } @@ -1265,12 +1322,23 @@ bool get_nc_data(NcVar *var, int *data, const long *curs) { template bool _get_nc_data(NcVar *var, T *data, T bad_data, const long dim, const long cur) { bool return_status = false; + const char *method_name = "_get_nc_data(const long dim, const long cur) "; if (IS_VALID_NC_P(var)) { + int dim_idx = 0; std::vector start; std::vector count; start.push_back((size_t)cur); count.push_back((size_t)dim); + int dim_size = get_dim_size(var, dim_idx); + if ((cur+dim) > dim_size) { + NcDim nc_dim = get_nc_dim(var, dim_idx); + mlog << Error << "\n" << method_name << "The requested start offset and count (" + << cur << ", " << dim << ") exceeds the dimension[" << dim_idx << "]=" << dim_size << " " + << (IS_VALID_NC(nc_dim) ? GET_NC_NAME(nc_dim) : " ") + << " for the variable " << GET_NC_NAME_P(var) << ".\n\n"; + exit(1); + } for (int idx1=0; idx1 start; - std::vector count; - start.push_back((size_t)cur); - count.push_back((size_t)dim); - - for (int idx1=0; idx1getVar(start, count, data); - return_status = true; - } - return(return_status); + return(_get_nc_data(var, data, bad_data_int, dim, cur)); } //////////////////////////////////////////////////////////////////////// @@ -1316,6 +1365,7 @@ bool get_nc_data(NcVar *var, int *data, const long dim, const long cur) { template bool _get_nc_data(NcVar *var, T *data, T bad_data, const long *dims, const long *curs) { bool return_status = false; + const char *method_name = "_get_nc_data(const long *dims, const long *curs) "; if (IS_VALID_NC_P(var)) { std::vector start; @@ -1324,6 +1374,17 @@ bool _get_nc_data(NcVar *var, T *data, T bad_data, const long *dims, const long int data_size = 1; int dimC = get_dim_count(var); for (int idx = 0 ; idx < dimC; idx++) { + int dim_size = get_dim_size(var, idx); + if ((curs[idx]+dims[idx]) > dim_size) { + NcDim nc_dim = get_nc_dim(var, idx); + mlog << Error << "\n" << method_name << "The requested start offset and count (" + << curs[idx] << ", " << dims[idx] << ") exceeds the dimension[" + << idx << "]=" << dim_size << " " + << (IS_VALID_NC(nc_dim) ? GET_NC_NAME(nc_dim) : " ") + << " for the variable " << GET_NC_NAME_P(var) << ".\n\n"; + exit(1); + } + start.push_back((size_t)curs[idx]); count.push_back((size_t)dims[idx]); data_size *= dims[idx]; From 599181a748826b7cca5b1659c581b0332354b6f2 Mon Sep 17 00:00:00 2001 From: Seth Linden Date: Thu, 15 Jul 2021 11:18:13 -0600 Subject: [PATCH 029/200] Feature 1746 wavelet stat (#1851) * For issue #1746 modified code to allow users to pass in an empty list (or NA) for forecast and observation thresholds in order to skip applying the threhsolds, but it will still compute stats with the raw fields. SL * For issue #1746, added new unit test that uses a config file that has empty lists for the forecast and observation thresholds. SL * For issue #1746 Added some content related to allowing users to set forecast and observation cat thresholds to an empty list in order to skip the binary masking (and consider all grid-points for stats). SL * Per #1746, cleaning up for consistent indentation. * Per #1746, cleaning up for consistent indentation. * Per #1746, add a revision history note, update the plotting range in the postscript output to be [-n,n] where n is the maximum value of the maximum absolute difference and 1.0, and also fix a bug. When the NA threshold comes AFTER a real threshold, the resulting data and difference values were not being updated. * Per #1746, change the Wavelet-Stat config file values in the the wvlt_plot dictionary by setting plot_min = plot_max = 0.0. That enables the default logic of the tool to take effect. Choose the plotting range of the wavelet plots as [-n,n], where n is the maximum of 1.0 and the maximum absolute difference. * Per #1746, used apply_fcst_thresh where it should have been apply_obs_thresh. * Per issue #1746, modified some content related to users being able to skip applying the categorical threhsolds by putting an empty list or NA in the configuration file. SL * Per issue #1746 Added some warnings if the forecast threshold is set to NA but the observation threshold is not NA (a numeric threshold) and vice versa. SL * Per #1746, fix a couple of typos and tweak wording in the wavelet-stat chapter. * Per #1746, loop over each pair of fcst/obs thresholds to check for inconsistent use of the NA threshold type. * Per #1746, a bit of code cleanup replacing calls to n_elements() with n() to make the code more concise. * Per #1746, need to reinitialize apply_fcst_thresh and apply_obs_thresh to true inside the loop since the NA threshold can appear anywhere in the list of thresholds. Co-authored-by: Seth Linden Co-authored-by: John Halley Gotway --- met/data/config/WaveletStatConfig_default | 4 +- met/docs/Users_Guide/wavelet-stat.rst | 19 ++- met/scripts/config/WaveletStatConfig_APCP_12 | 8 +- .../tools/core/wavelet_stat/wavelet_stat.cc | 83 +++++++---- .../wavelet_stat/wavelet_stat_conf_info.cc | 41 +++++- test/config/WaveletStatConfig | 4 +- test/config/WaveletStatConfig_no_thresholds | 139 ++++++++++++++++++ test/config/WaveletStatConfig_python | 4 +- test/config/WaveletStatConfig_python_mixed | 4 +- test/xml/unit_wavelet_stat.xml | 27 +++- 10 files changed, 283 insertions(+), 50 deletions(-) create mode 100644 test/config/WaveletStatConfig_no_thresholds diff --git a/met/data/config/WaveletStatConfig_default b/met/data/config/WaveletStatConfig_default index 5a50fe2f0d..6a7356c7ee 100644 --- a/met/data/config/WaveletStatConfig_default +++ b/met/data/config/WaveletStatConfig_default @@ -131,8 +131,8 @@ obs_raw_plot = { wvlt_plot = { color_table = "MET_BASE/colortables/NCL_colortables/BlWhRe.ctable"; - plot_min = -1.0; - plot_max = 1.0; + plot_min = 0.0; + plot_max = 0.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/met/docs/Users_Guide/wavelet-stat.rst b/met/docs/Users_Guide/wavelet-stat.rst index ae26221f34..19db97d1ed 100644 --- a/met/docs/Users_Guide/wavelet-stat.rst +++ b/met/docs/Users_Guide/wavelet-stat.rst @@ -30,7 +30,7 @@ The method The Intensity Scale approach can be summarized in the following 5 steps: -1. For each threshold, the forecast and observation fields are transformed into binary fields: where the grid-point precipitation value meets the threshold criteria it is assigned 1, where the threshold criteria are not met it is assigned 0. :numref:`wavelet-stat_NIMROD_3h_fcst` illustrates an example of a forecast and observation fields, and their corresponding binary fields for a threshold of 1mm/h. This case shows an intense storm of the scale of 160 km displaced almost its entire length. The displacement error is clearly visible from the binary field difference and the contingency table image obtained for the same threshold :numref:`contingency_table_counts`. +1. For each threshold, the forecast and observation fields are transformed into binary fields: where the grid-point precipitation value meets the threshold criteria it is assigned 1, where the threshold criteria are not met it is assigned 0. This can also be done with no thresholds indicated at all and in that case the grid-point values are not transformed to binary fields and instead the raw data is used as is for statistics. :numref:`wavelet-stat_NIMROD_3h_fcst` illustrates an example of a forecast and observation fields, and their corresponding binary fields for a threshold of 1mm/h. This case shows an intense storm of the scale of 160 km displaced almost its entire length. The displacement error is clearly visible from the binary field difference and the contingency table image obtained for the same threshold :numref:`contingency_table_counts`. 2. The binary forecast and observation fields obtained from the thresholding are then decomposed into the sum of components on different scales, by using a 2D Haar wavelet filter (:numref:`wavelet-stat_NIMROD_diff`). Note that the scale components are fields, and their sum adds up to the original binary field. For a forecast defined over square domain of **2ⁿ x 2ⁿ** grid-points, the scale components are **n+1: n** mother wavelet components + the largest father wavelet (or scale-function) component. The **n** mother wavelet components have resolution equal to **1, 2, 4, ...** :math:`\mathbf{2^{n-1}}` grid-points. The largest father wavelet component is a constant field over the **2ⁿ x 2ⁿ** grid-point domain with value equal to the field mean. @@ -230,6 +230,23 @@ _______________________ .. code-block:: none + // Empty list of thresholds + cat_thresh = []; + + // Or explicitly set the NA threshold type + cat_thresh = [>0.0, >=5.0, NA]; + + +The **cat_thresh** option defines an array of thresholds for each field defined in the fcst and obs dictionaries. The number of forecast and observation categorical thresholds must match. If set to an empty list, the thresholds will not be applied (no binary masking) and all the raw grid-point values will be used for downstream statistics. + +If the array of thresholds is an empty list, the application will set the threshold to NA internally and skip applying the thresholds. If the threshold is set to NA explicitly in the list, the application will also skip applying the threshold. + +Since the application has the ability to loop through multiple thresholds (for multiple fields), a user can include NA in the list of thresholds to produce statistics for the raw data values for the given field. + +_______________________ + +.. code-block:: none + grid_decomp_flag = AUTO; tile = { diff --git a/met/scripts/config/WaveletStatConfig_APCP_12 b/met/scripts/config/WaveletStatConfig_APCP_12 index 8abdaddb57..67079ef1c7 100644 --- a/met/scripts/config/WaveletStatConfig_APCP_12 +++ b/met/scripts/config/WaveletStatConfig_APCP_12 @@ -50,7 +50,7 @@ fcst = { { name = "APCP"; level = [ "A12" ]; - cat_thresh = [ >0.0, >=5.0 ]; + cat_thresh = [ >0.0, >=5.0, NA ]; } ]; } @@ -59,7 +59,7 @@ obs = { { name = "APCP_12"; level = [ "(*,*)" ]; - cat_thresh = [ >0.0, >=5.0 ]; + cat_thresh = [ >0.0, >=5.0, NA ]; } ]; } @@ -137,8 +137,8 @@ obs_raw_plot = { wvlt_plot = { color_table = "MET_BASE/colortables/NCL_colortables/BlWhRe.ctable"; - plot_min = -1.0; - plot_max = 1.0; + plot_min = 0.0; + plot_max = 0.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/met/src/tools/core/wavelet_stat/wavelet_stat.cc b/met/src/tools/core/wavelet_stat/wavelet_stat.cc index e557d039a0..c2dbc61635 100644 --- a/met/src/tools/core/wavelet_stat/wavelet_stat.cc +++ b/met/src/tools/core/wavelet_stat/wavelet_stat.cc @@ -35,7 +35,8 @@ // 010 02/25/15 Halley Gotway Add automated regridding. // 011 05/15/17 Prestopnik P. Add shape to regrid options. // 012 04/08/19 Halley Gotway Add percentile thresholds. -// 012 04/01/19 Fillmore Add FCST and OBS units. +// 013 04/01/19 Fillmore Add FCST and OBS units. +// 014 07/09/21 Linden MET #1746 Skip thresholding. // //////////////////////////////////////////////////////////////////////// @@ -113,8 +114,8 @@ static double mean_array(double *, int); static void plot_ps_raw(const DataPlane &, const DataPlane &, const DataPlane &, const DataPlane &, int); -static void plot_ps_wvlt(const double *, int, int, int, ISCInfo &, - int, int); +static void plot_ps_wvlt(const double *, const double, int, int, int, + ISCInfo &, int, int); static double compute_percentage(double, double); static void set_plot_dims(int, int); @@ -419,7 +420,7 @@ void process_scores() { // Allocate memory for ISCInfo objects sized as [n_tile][n_thresh] isc_info = new ISCInfo * [conf_info.get_n_tile()]; for(j=0; j " << "the forecast and observation arrays must have equal " << "length.\n\n"; @@ -962,7 +964,7 @@ void do_intensity_scale(const NumArray &f_na, const NumArray &o_na, ns = conf_info.get_n_scale(); // Set up the ISCInfo thresholds and n_scale - n_isc = conf_info.fcat_ta[i_vx].n_elements(); + n_isc = conf_info.fcat_ta[i_vx].n(); for(i=0; imagic_str() << " " << fcst_thresh_str << " versus " << conf_info.obs_info[i_vx]->magic_str() << " " << obs_thresh_str << ".\n"; - // Apply the threshold to each point to create 0/1 mask fields - for(j=0; j mad) mad = fabs(diff[j]); } // end for j // Compute the contingency table for the binary fields @@ -1023,15 +1044,15 @@ void do_intensity_scale(const NumArray &f_na, const NumArray &o_na, isc_info[i].compute_isc(-1); // Write the thresholded binary fields to NetCDF - if ( conf_info.nc_info.do_raw || conf_info.nc_info.do_diff ) { + if(conf_info.nc_info.do_raw || conf_info.nc_info.do_diff ) { write_nc_wav(conf_info.nc_info, f_dat, o_dat, n, i_vx, i_tile, -1, isc_info[i].fthresh, isc_info[i].othresh); } // Write the thresholded binary difference field to PostScript - if ( ! (conf_info.nc_info.all_false()) ) { - plot_ps_wvlt(diff, n, i_vx, i_tile, isc_info[i], -1, ns); + if(!conf_info.nc_info.all_false()) { + plot_ps_wvlt(diff, mad, n, i_vx, i_tile, isc_info[i], -1, ns); } // Initialize the discrete wavelet transforms @@ -1102,7 +1123,7 @@ void do_intensity_scale(const NumArray &f_na, const NumArray &o_na, isc_info[i].compute_isc(j); // Write the decomposed fields for this scale to NetCDF - if ( ! (conf_info.nc_info.all_false()) ) { + if(!conf_info.nc_info.all_false()) { write_nc_wav(conf_info.nc_info, f_scl, o_scl, n, i_vx, i_tile, j, isc_info[i].fthresh, @@ -1114,7 +1135,7 @@ void do_intensity_scale(const NumArray &f_na, const NumArray &o_na, // Write the decomposed difference field for this scale to PostScript if(conf_info.ps_plot_flag) { - plot_ps_wvlt(diff, n, i_vx, i_tile, isc_info[i], j, ns); + plot_ps_wvlt(diff, mad, n, i_vx, i_tile, isc_info[i], j, ns); } } // end for j @@ -2265,7 +2286,8 @@ void plot_ps_raw(const DataPlane &fcst_dp, //////////////////////////////////////////////////////////////////////// -void plot_ps_wvlt(const double *diff, int n, int i_vx, int i_tile, +void plot_ps_wvlt(const double *diff, double mad, + int n, int i_vx, int i_tile, ISCInfo &isc_info, int i_scale, int n_scale) { ConcatString label; @@ -2286,12 +2308,6 @@ void plot_ps_wvlt(const double *diff, int n, int i_vx, int i_tile, v_tab = v_tab_cen; } - // - // The min and max plotting values should default to [-1.0, 1.0] - // for the decomposed wavelet difference fields. - // - wvlt_ct.rescale(-1.0, 1.0, bad_data_double); - // // If the wvlt_plot_min or wvlt_plot_max value is set in the // config file, rescale the colortable to the requested range. @@ -2302,6 +2318,15 @@ void plot_ps_wvlt(const double *diff, int n, int i_vx, int i_tile, conf_info.wvlt_pi.plot_max, bad_data_double); } + // + // Otherwise, rescale the colortable to [-d, d] where d is the maximum + // absolute difference and at least 1.0. If thresholds have been applied, + // the plotting range should be [-1.0, 1.0]. + // + else { + double max_plot_val = max(1.0, mad); + wvlt_ct.rescale(-1.0*max_plot_val, max_plot_val, bad_data_double); + } // // Set the fill color. If a fill value is not specified in the range @@ -2331,10 +2356,10 @@ void plot_ps_wvlt(const double *diff, int n, int i_vx, int i_tile, v_tab -= 1.0*plot_text_sep; ps_out->write_centered_text(1, 1, h_tab_cen, v_tab, 0.5, 0.5, label.c_str()); if(i_scale == -1) - label.format("Tile %i, Binary, Difference (F-0)", + label.format("Tile %i, Binary, Difference (F-O)", i_tile+1); else - label.format("Tile %i, Scale %i, Difference (F-0)", + label.format("Tile %i, Scale %i, Difference (F-O)", i_tile+1, i_scale+1); v_tab -= 2.0*plot_text_sep; diff --git a/met/src/tools/core/wavelet_stat/wavelet_stat_conf_info.cc b/met/src/tools/core/wavelet_stat/wavelet_stat_conf_info.cc index 087d1fbaba..103f203280 100644 --- a/met/src/tools/core/wavelet_stat/wavelet_stat_conf_info.cc +++ b/met/src/tools/core/wavelet_stat/wavelet_stat_conf_info.cc @@ -135,7 +135,7 @@ void WaveletStatConfInfo::read_config(const char *default_file_name, void WaveletStatConfInfo::process_config(GrdFileType ftype, GrdFileType otype) { - int i, n; + int i, j, n; VarInfoFactory info_factory; mapoutput_map; Dictionary *fcst_dict = (Dictionary *) 0; @@ -144,6 +144,9 @@ void WaveletStatConfInfo::process_config(GrdFileType ftype, Dictionary i_fdict, i_odict; gsl_wavelet_type type; + SingleThresh st_NA; + st_NA.set_na(); + // Dump the contents of the config file if(mlog.verbosity_level() >= 5) conf.dump(cout); @@ -250,10 +253,23 @@ void WaveletStatConfInfo::process_config(GrdFileType ftype, << "Forecast categorical thresholds: " << fcat_ta[i].get_str() << "\n" << "Observed categorical thresholds: " << ocat_ta[i].get_str() << "\n"; } + + // If the forecast threshold array is an empty list (or NA) + // Add the NA threshold type to the list for downstream iteration + if(fcat_ta[i].n() == 0) { + mlog << Debug(2) << "Found empty list for forecast threshold, setting threshold type to NA.\n"; + fcat_ta[i].add(st_NA); + } + + // If the observation threshold array is an empty list (or NA) + // Add the NA threshold type to the list for downstream iteration + if(ocat_ta[i].n() == 0) { + mlog << Debug(2) << "Found empty list for observation threshold, setting threshold type to NA.\n"; + ocat_ta[i].add(st_NA); + } // Check for the same number of fcst and obs thresholds - if(fcat_ta[i].n_elements() != ocat_ta[i].n_elements()) { - + if(fcat_ta[i].n() != ocat_ta[i].n()) { mlog << Error << "\nWaveletStatConfInfo::process_config() -> " << "The number of thresholds for each field in \"fcst." << conf_key_cat_thresh @@ -262,8 +278,19 @@ void WaveletStatConfInfo::process_config(GrdFileType ftype, exit(1); } + // Send a warning about inconsistent use of the NA threshold + for(j=0; j " + << "Skipping thresholding for the forecast (" << fcat_ta[i][j].get_str() + << ") or observation (" << ocat_ta[i][j].get_str() + << ") but not the other may produce unexpected results!\n\n"; + } + } + // Keep track of the maximum number of thresholds - if(fcat_ta[i].n_elements() > max_n_thresh) max_n_thresh = fcat_ta[i].n_elements(); + if(fcat_ta[i].n() > max_n_thresh) max_n_thresh = fcat_ta[i].n(); } // end for i @@ -505,7 +532,7 @@ void WaveletStatConfInfo::process_tiles(const Grid &grid) { case(GridDecompType_Tile): // Number of tiles based on the user-specified locations - n_tile = tile_xll.n_elements(); + n_tile = tile_xll.n(); msg << "\nTiling Method: Apply " << n_tile << " tile(s) specified in the configuration file " @@ -641,9 +668,9 @@ int WaveletStatConfInfo::n_isc_row() { // Compute the number of output lines for each verification field for(i=0,n=0; i 1) n += (n_scale + 2) * fcat_ta[i].n_elements(); + if(n_tile > 1) n += (n_scale + 2) * fcat_ta[i].n(); } return(n); diff --git a/test/config/WaveletStatConfig b/test/config/WaveletStatConfig index b9a3983bdf..06963c8f51 100644 --- a/test/config/WaveletStatConfig +++ b/test/config/WaveletStatConfig @@ -127,8 +127,8 @@ obs_raw_plot = { wvlt_plot = { color_table = "MET_BASE/colortables/NCL_colortables/BlWhRe.ctable"; - plot_min = -1.0; - plot_max = 1.0; + plot_min = 0.0; + plot_max = 0.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/WaveletStatConfig_no_thresholds b/test/config/WaveletStatConfig_no_thresholds new file mode 100644 index 0000000000..42e02ca680 --- /dev/null +++ b/test/config/WaveletStatConfig_no_thresholds @@ -0,0 +1,139 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Wavelet-Stat configuration file. +// +// For additional information, please see the MET User's Guide. +// +//////////////////////////////////////////////////////////////////////////////// + +// +// Output model name to be written +// +model = "WRF"; + +// +// Output description to be written +// May be set separately in each "obs.field" entry +// +desc = "NA"; + +// +// Output observation type to be written +// +obtype = "MC_PCP"; + +//////////////////////////////////////////////////////////////////////////////// + +// +// Verification grid +// +regrid = { + to_grid = NONE; + method = NEAREST; + width = 1; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Forecast and observation fields to be verified +// +fcst = { + field = [ + { + name = "APCP"; + level = [ "A12" ]; + cat_thresh = []; + } + ]; +} +obs = { + field = [ + { + name = "APCP_12"; + level = [ "(*,*)" ]; + cat_thresh = []; + } + ]; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Handle missing data +// +mask_missing_flag = NONE; + +//////////////////////////////////////////////////////////////////////////////// + +// +// Decompose the field into dyadic tiles +// +grid_decomp_flag = AUTO; + +tile = { + width = 0; + location = [ + { + x_ll = 0; + y_ll = 0; + } + ]; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Wavelet to be used for the decomposition +// +wavelet = { + type = HAAR; + member = 2; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Statistical output types +// +output_flag = { + isc = BOTH; +} + +// +// NetCDF matched pairs and PostScript output files +// +nc_pairs_flag = TRUE; +ps_plot_flag = TRUE; + +//////////////////////////////////////////////////////////////////////////////// + +// +// Plotting information +// +met_data_dir = "MET_BASE"; + +fcst_raw_plot = { + color_table = "MET_BASE/colortables/met_default.ctable"; + plot_min = 0.0; + plot_max = 0.0; +} + +obs_raw_plot = { + color_table = "MET_BASE/colortables/met_default.ctable"; + plot_min = 0.0; + plot_max = 0.0; +} + +wvlt_plot = { + color_table = "MET_BASE/colortables/NCL_colortables/BlWhRe.ctable"; + plot_min = 0.0; + plot_max = 0.0; +} + +//////////////////////////////////////////////////////////////////////////////// + +output_prefix = "${OUTPUT_PREFIX}"; +version = "V10.1.0"; + +//////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/WaveletStatConfig_python b/test/config/WaveletStatConfig_python index 28df2065a8..b9e2d62f04 100644 --- a/test/config/WaveletStatConfig_python +++ b/test/config/WaveletStatConfig_python @@ -118,8 +118,8 @@ obs_raw_plot = { wvlt_plot = { color_table = "MET_BASE/colortables/NCL_colortables/BlWhRe.ctable"; - plot_min = -1.0; - plot_max = 1.0; + plot_min = 0.0; + plot_max = 0.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/WaveletStatConfig_python_mixed b/test/config/WaveletStatConfig_python_mixed index a5e09298b7..899766b007 100644 --- a/test/config/WaveletStatConfig_python_mixed +++ b/test/config/WaveletStatConfig_python_mixed @@ -127,8 +127,8 @@ obs_raw_plot = { wvlt_plot = { color_table = "MET_BASE/colortables/NCL_colortables/BlWhRe.ctable"; - plot_min = -1.0; - plot_max = 1.0; + plot_min = 0.0; + plot_max = 0.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/xml/unit_wavelet_stat.xml b/test/xml/unit_wavelet_stat.xml index 0b4d33510d..9e5f6efdd9 100644 --- a/test/xml/unit_wavelet_stat.xml +++ b/test/xml/unit_wavelet_stat.xml @@ -15,7 +15,10 @@ &TEST_DIR; true - + + + + &MET_BIN;/wavelet_stat @@ -35,5 +38,27 @@ + + + + + + &MET_BIN;/wavelet_stat + + OUTPUT_PREFIX GRIB1_NAM_STAGE4_NO_THRESH + + \ + &DATA_DIR_MODEL;/grib1/nam_st4/nam_2012040900_F012_gSt4.grib \ + &OUTPUT_DIR;/pcp_combine/stage4_2012040912_F012_APCP12.nc \ + &CONFIG_DIR;/WaveletStatConfig_no_thresholds \ + -outdir &OUTPUT_DIR;/wavelet_stat -v 1 + + + &OUTPUT_DIR;/wavelet_stat/wavelet_stat_GRIB1_NAM_STAGE4_NO_THRESH_120000L_20120409_120000V.stat + &OUTPUT_DIR;/wavelet_stat/wavelet_stat_GRIB1_NAM_STAGE4_NO_THRESH_120000L_20120409_120000V_isc.txt + &OUTPUT_DIR;/wavelet_stat/wavelet_stat_GRIB1_NAM_STAGE4_NO_THRESH_120000L_20120409_120000V.nc + &OUTPUT_DIR;/wavelet_stat/wavelet_stat_GRIB1_NAM_STAGE4_NO_THRESH_120000L_20120409_120000V.ps + + From 31acbe8b09c0870aa23ac6be88840b789fe03bb6 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 16:28:18 -0600 Subject: [PATCH 030/200] Add sphinx.ext.pngmath to conf.py --- met/docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/docs/conf.py b/met/docs/conf.py index 9474c4b5d7..621c39910d 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -32,7 +32,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx'] +extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx, sphinx.ext.pngmath'] # settings for ReadTheDocs PDF creation latex_engine = 'pdflatex' From 9f5fd593a9f6dea5dbde4ea1e8b4fa2a4810c10d Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 16:30:16 -0600 Subject: [PATCH 031/200] Fix typo in conf.py --- met/docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/docs/conf.py b/met/docs/conf.py index 621c39910d..e0897c234d 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -32,7 +32,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx, sphinx.ext.pngmath'] +extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx', 'sphinx.ext.pngmath'] # settings for ReadTheDocs PDF creation latex_engine = 'pdflatex' From 5dbbc306e1a00956621e29c0cba7ed44ac736850 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 16:33:16 -0600 Subject: [PATCH 032/200] Add sphinx.ext.mathjax to conf.py --- met/docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/docs/conf.py b/met/docs/conf.py index e0897c234d..8608e1145a 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -32,7 +32,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx', 'sphinx.ext.pngmath'] +extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx', 'sphinx.ext.mathjax'] # settings for ReadTheDocs PDF creation latex_engine = 'pdflatex' From 028b3543c126f54a31c8a597fe6e35cb998cc54d Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 16:36:12 -0600 Subject: [PATCH 033/200] Add sphinx.ext.imgmath to conf.py --- met/docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/docs/conf.py b/met/docs/conf.py index 8608e1145a..fa729f2d60 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -32,7 +32,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx', 'sphinx.ext.mathjax'] +extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx', 'sphinx.ext.imgmathZZ'] # settings for ReadTheDocs PDF creation latex_engine = 'pdflatex' From e5eeeb3b89e965106ff04839826c136e88530671 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 16:37:55 -0600 Subject: [PATCH 034/200] Fix typo in conf.py --- met/docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/docs/conf.py b/met/docs/conf.py index fa729f2d60..c62a8fa449 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -32,7 +32,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx', 'sphinx.ext.imgmathZZ'] +extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx', 'sphinx.ext.imgmath'] # settings for ReadTheDocs PDF creation latex_engine = 'pdflatex' From 12be58d2458ff05914fa8bb856ec1d0fce41b444 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 16:56:24 -0600 Subject: [PATCH 035/200] Change math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 74 ++++++++++++++++-------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index f8765ad985..2ee552d5f5 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -607,15 +607,16 @@ Called "FBAR", "OBAR", "FOBAR", "FFBAR", and "OOBAR" in SL1L2 output :numref:`ta These statistics are simply the 1st and 2nd moments of the forecasts, observations and errors: -.. math:: \text{FBAR} = \text{Mean}(f) = \bar{f} = \frac{1}{n} \sum_{i=1}^n f_i +.. math:: + \text{FBAR} = \text{Mean}(f) = \bar{f} = \frac{1}{n} \sum_{i=1}^n f_i - \text{OBAR} = \text{Mean}(o) = \bar{o} = \frac{1}{n} \sum_{i=1}^n o_i + \text{OBAR} = \text{Mean}(o) = \bar{o} = \frac{1}{n} \sum_{i=1}^n o_i - \text{FOBAR} = \text{Mean}(fo) = \bar{fo} = \frac{1}{n} \sum_{i=1}^n f_i o_i + \text{FOBAR} = \text{Mean}(fo) = \bar{fo} = \frac{1}{n} \sum_{i=1}^n f_i o_i - \text{FFBAR} = \text{Mean}(f^2) = \bar{f}^2 = \frac{1}{n} \sum_{i=1}^n f_i^2 + \text{FFBAR} = \text{Mean}(f^2) = \bar{f}^2 = \frac{1}{n} \sum_{i=1}^n f_i^2 - \text{OOBAR} = \text{Mean}(o^2) = \bar{o}^2 = \frac{1}{n} \sum_{i=1}^n o_i^2 + \text{OOBAR} = \text{Mean}(o^2) = \bar{o}^2 = \frac{1}{n} \sum_{i=1}^n o_i^2 Some of the other statistics for continuous forecasts (e.g., RMSE) can be derived from these moments. @@ -626,15 +627,16 @@ Called "FABAR", "OABAR", "FOABAR", "FFABAR", "OOABAR" in SAL1L2 output :numref:` Computation of these statistics requires a climatological value, c. These statistics are the 1st and 2nd moments of the scalar anomalies. The moments are defined as: -.. math:: \text{FABAR} = \text{Mean}(f - c) = \bar{f - c} = \frac{1}{n} \sum_{i=1}^n (f_i - c) +.. math:: + \text{FABAR} = \text{Mean}(f - c) = \bar{f - c} = \frac{1}{n} \sum_{i=1}^n (f_i - c) - \text{OABAR} = \text{Mean}(o - c) = \bar{o - c} = \frac{1}{n} \sum_{i=1}^n (o_i - c) + \text{OABAR} = \text{Mean}(o - c) = \bar{o - c} = \frac{1}{n} \sum_{i=1}^n (o_i - c) - \text{FOABAR} = \text{Mean}[(f - c)(o - c)] = \bar{(f - c)(o - c)} = \frac{1}{n} \sum_{i=1}^n (f_i - c)(o_i - c) + \text{FOABAR} = \text{Mean}[(f - c)(o - c)] = \bar{(f - c)(o - c)} = \frac{1}{n} \sum_{i=1}^n (f_i - c)(o_i - c) - \text{FFABAR} = \text{Mean}[(f - c)^2] = \bar{(f - c)}^2 = \frac{1}{n} \sum_{i=1}^n (f_i - c)^2 + \text{FFABAR} = \text{Mean}[(f - c)^2] = \bar{(f - c)}^2 = \frac{1}{n} \sum_{i=1}^n (f_i - c)^2 - \text{OOABAR} = \text{Mean}[(o - c)^2] = \bar{(o - c)}^2 = \frac{1}{n} \sum_{i=1}^n (o_i - c)^2 + \text{OOABAR} = \text{Mean}[(o - c)^2] = \bar{(o - c)}^2 = \frac{1}{n} \sum_{i=1}^n (o_i - c)^2 Vector L1 and L2 values ~~~~~~~~~~~~~~~~~~~~~~~ @@ -643,19 +645,20 @@ Called "UFBAR", "VFBAR", "UOBAR", "VOBAR", "UVFOBAR", "UVFFBAR", "UVOOBAR" in VL These statistics are the moments for wind vector values, where **u** is the E-W wind component and **v** is the N-S wind component ( :math:`u_f` is the forecast E-W wind component; :math:`u_o` is the observed E-W wind component; :math:`v_f` is the forecast N-S wind component; and :math:`v_o` is the observed N-S wind component). The following measures are computed: -.. math:: \text{UFBAR} = \text{Mean}(u_f) = \bar{u}_f = \frac{1}{n} \sum_{i=1}^n u_{fi} +.. math:: + \text{UFBAR} = \text{Mean}(u_f) = \bar{u}_f = \frac{1}{n} \sum_{i=1}^n u_{fi} - \text{VFBAR} = \text{Mean}(v_f) = \bar{v}_f = \frac{1}{n} \sum_{i=1}^n v_{fi} + \text{VFBAR} = \text{Mean}(v_f) = \bar{v}_f = \frac{1}{n} \sum_{i=1}^n v_{fi} - \text{UOBAR} = \text{Mean}(u_o) = \bar{u}_o = \frac{1}{n} \sum_{i=1}^n u_{oi} + \text{UOBAR} = \text{Mean}(u_o) = \bar{u}_o = \frac{1}{n} \sum_{i=1}^n u_{oi} - \text{VOBAR} = \text{Mean}(v_o) = \bar{v}_o = \frac{1}{n} \sum_{i=1}^n v_{oi} + \text{VOBAR} = \text{Mean}(v_o) = \bar{v}_o = \frac{1}{n} \sum_{i=1}^n v_{oi} - \text{UVFOBAR} = \text{Mean}(u_f u_o + v_f v_o) = \frac{1}{n} \sum_{i=1}^n (u_{fi} u_{oi} + v_{fi} v_{oi}) + \text{UVFOBAR} = \text{Mean}(u_f u_o + v_f v_o) = \frac{1}{n} \sum_{i=1}^n (u_{fi} u_{oi} + v_{fi} v_{oi}) - \text{UVFFBAR} = \text{Mean}(u_f^2 + v_f^2) = \frac{1}{n} \sum_{i=1}^n (u_{fi}^2 + v_{fi}^2) + \text{UVFFBAR} = \text{Mean}(u_f^2 + v_f^2) = \frac{1}{n} \sum_{i=1}^n (u_{fi}^2 + v_{fi}^2) - \text{UVOOBAR} = \text{Mean}(u_o^2 + v_o^2) = \frac{1}{n} \sum_{i=1}^n (u_{oi}^2 + v_{oi}^2) + \text{UVOOBAR} = \text{Mean}(u_o^2 + v_o^2) = \frac{1}{n} \sum_{i=1}^n (u_{oi}^2 + v_{oi}^2) Vector anomaly L1 and L2 values ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -664,20 +667,21 @@ Called "UFABAR", "VFABAR", "UOABAR", "VOABAR", "UVFOABAR", "UVFFABAR", "UVOOABAR These statistics require climatological values for the wind vector components, :math:`u_c \text{ and } v_c`. The measures are defined below: -.. math:: \text{UFABAR} = \text{Mean}(u_f - u_c) = \frac{1}{n} \sum_{i=1}^n (u_{fi} - u_c) +.. math:: + \text{UFABAR} = \text{Mean}(u_f - u_c) = \frac{1}{n} \sum_{i=1}^n (u_{fi} - u_c) - \text{VFBAR} = \text{Mean}(v_f - v_c) = \frac{1}{n} \sum_{i=1}^n (v_{fi} - v_c) + \text{VFBAR} = \text{Mean}(v_f - v_c) = \frac{1}{n} \sum_{i=1}^n (v_{fi} - v_c) - \text{UOABAR} = \text{Mean}(u_o - u_c) = \frac{1}{n} \sum_{i=1}^n (u_{oi} - u_c) + \text{UOABAR} = \text{Mean}(u_o - u_c) = \frac{1}{n} \sum_{i=1}^n (u_{oi} - u_c) - \text{VOABAR} = \text{Mean}(v_o - v_c) = \frac{1}{n} \sum_{i=1}^n (v_{oi} - v_c) + \text{VOABAR} = \text{Mean}(v_o - v_c) = \frac{1}{n} \sum_{i=1}^n (v_{oi} - v_c) - \text{UVFOABAR} &= \text{Mean}[(u_f - u_c)(u_o - u_c) + (v_f - v_c)(v_o - v_c)] \\ - &= \frac{1}{n} \sum_{i=1}^n (u_{fi} - u_c) + (u_{oi} - u_c) + (v_{fi} - v_c)(v_{oi} - v_c) + \text{UVFOABAR} &= \text{Mean}[(u_f - u_c)(u_o - u_c) + (v_f - v_c)(v_o - v_c)] \\ + &= \frac{1}{n} \sum_{i=1}^n (u_{fi} - u_c) + (u_{oi} - u_c) + (v_{fi} - v_c)(v_{oi} - v_c) - \text{UVFFABAR} = \text{Mean}[(u_f - u_c)^2 + (v_f - v_c)^2] = \frac{1}{n} \sum_{i=1}^n ((u_{fi} - u_c)^2 + (v_{fi} - v_c)^2) + \text{UVFFABAR} = \text{Mean}[(u_f - u_c)^2 + (v_f - v_c)^2] = \frac{1}{n} \sum_{i=1}^n ((u_{fi} - u_c)^2 + (v_{fi} - v_c)^2) - \text{UVOOABAR} = \text{Mean}[(u_o - u_c)^2 + (v_o - v_c)^2] = \frac{1}{n} \sum_{i=1}^n ((u_{oi} - u_c)^2 + (v_{oi} - v_c)^2) + \text{UVOOABAR} = \text{Mean}[(u_o - u_c)^2 + (v_o - v_c)^2] = \frac{1}{n} \sum_{i=1}^n ((u_{oi} - u_c)^2 + (v_{oi} - v_c)^2) Gradient values ~~~~~~~~~~~~~~~ @@ -686,25 +690,27 @@ Called "TOTAL", "FGBAR", "OGBAR", "MGBAR", "EGBAR", "S1", "S1_OG", and "FGOG_RAT These statistics are only computed by the Grid-Stat tool and require vectors. Here :math:`\nabla` is the gradient operator, which in this applications signifies the difference between adjacent grid points in both the grid-x and grid-y directions. TOTAL is the count of grid locations used in the calculations. The remaining measures are defined below: -.. math:: \text{FGBAR} = \text{Mean}|\nabla f| = \frac{1}{n} \sum_{i=1}^n | \nabla f_i| +.. math:: + \text{FGBAR} = \text{Mean}|\nabla f| = \frac{1}{n} \sum_{i=1}^n | \nabla f_i| - \text{OGBAR} = \text{Mean}|\nabla o| = \frac{1}{n} \sum_{i=1}^n | \nabla o_i| + \text{OGBAR} = \text{Mean}|\nabla o| = \frac{1}{n} \sum_{i=1}^n | \nabla o_i| - \text{MGBAR} = \text{Max(FGBAR, OGBAR)} + \text{MGBAR} = \text{Max(FGBAR, OGBAR)} - \text{EGBAR} = \text{Mean}|\nabla f - \nabla o| = \frac{1}{n} \sum_{i=1}^n | \nabla f_i - \nabla o_i| + \text{EGBAR} = \text{Mean}|\nabla f - \nabla o| = \frac{1}{n} \sum_{i=1}^n | \nabla f_i - \nabla o_i| - \text{S1} = 100 \frac{\sum_{i=1}^n (w_i (e_g))}{\sum_{i=1}^n (w_i (G_L))}_i , + \text{S1} = 100 \frac{\sum_{i=1}^n (w_i (e_g))}{\sum_{i=1}^n (w_i (G_L))}_i , where the weights are applied at each grid location, with values assigned according to the weight option specified in the configuration file. The components of the :math:`S1` equation are as follows: -.. math:: e_g = (| \frac{\delta}{\delta x}(f - o)| + | \frac{\delta}{\delta y}(f - o)|) +.. math:: + e_g = (| \frac{\delta}{\delta x}(f - o)| + | \frac{\delta}{\delta y}(f - o)|) - G_L = \text{max}(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max}(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) + G_L = \text{max}(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max}(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) - \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} + \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} - \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} + \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} MET verification measures for probabilistic forecasts _____________________________________________________ From 43bbf74be3d5c507399e03dbc6c9f8e1d4ea6755 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 17:04:44 -0600 Subject: [PATCH 036/200] Temporarily disable equations with errors in Appendix C --- met/docs/Users_Guide/appendixC.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 2ee552d5f5..74b5ffc005 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -704,9 +704,9 @@ These statistics are only computed by the Grid-Stat tool and require vectors. He where the weights are applied at each grid location, with values assigned according to the weight option specified in the configuration file. The components of the :math:`S1` equation are as follows: .. math:: - e_g = (| \frac{\delta}{\delta x}(f - o)| + | \frac{\delta}{\delta y}(f - o)|) +.. e_g = (| \frac{\delta}{\delta x}(f - o)| + | \frac{\delta}{\delta y}(f - o)|) - G_L = \text{max}(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max}(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) +.. G_L = \text{max}(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max}(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} From 131564f8fe5afb31a6860339a8a98d8488198d08 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 17:11:55 -0600 Subject: [PATCH 037/200] Remove sphinx.ext.imgmath in conf.py --- met/docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/docs/conf.py b/met/docs/conf.py index c62a8fa449..9474c4b5d7 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -32,7 +32,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx', 'sphinx.ext.imgmath'] +extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx'] # settings for ReadTheDocs PDF creation latex_engine = 'pdflatex' From 6291a90aabb2f8b32b89f12535aa8a6ced01e91a Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 17:15:55 -0600 Subject: [PATCH 038/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 74b5ffc005..6440c299ce 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -708,6 +708,7 @@ where the weights are applied at each grid location, with values assigned accord .. G_L = \text{max}(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max}(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) +.. math:: \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} From 5889356130e4eda57915e691961db4505c1f01f4 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 17:18:25 -0600 Subject: [PATCH 039/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 6440c299ce..e8908db437 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -706,9 +706,9 @@ where the weights are applied at each grid location, with values assigned accord .. math:: .. e_g = (| \frac{\delta}{\delta x}(f - o)| + | \frac{\delta}{\delta y}(f - o)|) -.. G_L = \text{max}(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max}(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) - .. math:: + G_L = \text{max}(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max}(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) + \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} From 12e7c92153e3562c1eb697cdcdd372d6a3409e3e Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 17:22:00 -0600 Subject: [PATCH 040/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index e8908db437..6440c299ce 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -706,9 +706,9 @@ where the weights are applied at each grid location, with values assigned accord .. math:: .. e_g = (| \frac{\delta}{\delta x}(f - o)| + | \frac{\delta}{\delta y}(f - o)|) -.. math:: - G_L = \text{max}(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max}(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) +.. G_L = \text{max}(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max}(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) +.. math:: \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} From 8d0ea3397741e25e5ddc90655f7dfbb1fd9ee125 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 17:25:56 -0600 Subject: [PATCH 041/200] Add sphinx.ext.imgmath to conf.py --- met/docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/docs/conf.py b/met/docs/conf.py index 9474c4b5d7..c62a8fa449 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -32,7 +32,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx'] +extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx', 'sphinx.ext.imgmath'] # settings for ReadTheDocs PDF creation latex_engine = 'pdflatex' From eb177c49c685cd60bc5678c8ad5ff881f6657d2a Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 17:30:58 -0600 Subject: [PATCH 042/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 6440c299ce..0542e2c9a0 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -703,10 +703,10 @@ These statistics are only computed by the Grid-Stat tool and require vectors. He where the weights are applied at each grid location, with values assigned according to the weight option specified in the configuration file. The components of the :math:`S1` equation are as follows: -.. math:: -.. e_g = (| \frac{\delta}{\delta x}(f - o)| + | \frac{\delta}{\delta y}(f - o)|) - -.. G_L = \text{max}(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max}(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) +.. + e_g = (| \frac{\delta}{\delta x}(f - o)| + | \frac{\delta}{\delta y}(f - o)|) +.. + G_L = \text{max}(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max}(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) .. math:: \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} From bc513d80fc9c8d33843d77d533ae9b4cf25d6c11 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 17:36:53 -0600 Subject: [PATCH 043/200] Temporarily disable equations with errors in Appendix C --- met/docs/Users_Guide/appendixC.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 0542e2c9a0..5d182a4895 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -705,12 +705,14 @@ where the weights are applied at each grid location, with values assigned accord .. e_g = (| \frac{\delta}{\delta x}(f - o)| + | \frac{\delta}{\delta y}(f - o)|) + .. G_L = \text{max}(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max}(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) -.. math:: +.. \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} +.. \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} MET verification measures for probabilistic forecasts From 29d5b0c42bc26048bb024b469ab3fc653f6b339d Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 17:40:50 -0600 Subject: [PATCH 044/200] Remove sphinx.ext.imgmath in conf.py --- met/docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/docs/conf.py b/met/docs/conf.py index c62a8fa449..9474c4b5d7 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -32,7 +32,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx', 'sphinx.ext.imgmath'] +extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx'] # settings for ReadTheDocs PDF creation latex_engine = 'pdflatex' From 42320f97003fb6ccd4de7294f1bc1b31c55a3056 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 17:50:49 -0600 Subject: [PATCH 045/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 5d182a4895..afca48de67 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -707,13 +707,12 @@ where the weights are applied at each grid location, with values assigned accord e_g = (| \frac{\delta}{\delta x}(f - o)| + | \frac{\delta}{\delta y}(f - o)|) .. - G_L = \text{max}(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max}(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) + G_L = \text{max }(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max }(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) -.. - \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} +.. math:: + \text{S1_OG} = \frac{\text{EGBAR }}{\text{OGBAR }} -.. - \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} + \text{FGOG_RATIO} = \frac{\text{FGBAR }}{\text{OGBAR }} MET verification measures for probabilistic forecasts _____________________________________________________ From e725857c0cd064cd67b81dbb8fc5cfc5cde41d0a Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 17:55:15 -0600 Subject: [PATCH 046/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index afca48de67..4dd2cbb7ec 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -710,9 +710,9 @@ where the weights are applied at each grid location, with values assigned accord G_L = \text{max }(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max }(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) .. math:: - \text{S1_OG} = \frac{\text{EGBAR }}{\text{OGBAR }} + \text{S1_OG } = \frac{\text{EGBAR }}{\text{OGBAR }} - \text{FGOG_RATIO} = \frac{\text{FGBAR }}{\text{OGBAR }} + \text{FGOG_RATIO } = \frac{\text{FGBAR }}{\text{OGBAR }} MET verification measures for probabilistic forecasts _____________________________________________________ From 62a0bc0f303223effd66b2e9b2b4f399726010da Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 15 Jul 2021 17:58:00 -0600 Subject: [PATCH 047/200] Temporarily disable equations with errors --- met/docs/Users_Guide/appendixC.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 4dd2cbb7ec..b1aabba118 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -709,10 +709,11 @@ where the weights are applied at each grid location, with values assigned accord .. G_L = \text{max }(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max }(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) -.. math:: - \text{S1_OG } = \frac{\text{EGBAR }}{\text{OGBAR }} +.. + \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} - \text{FGOG_RATIO } = \frac{\text{FGBAR }}{\text{OGBAR }} +.. + \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} MET verification measures for probabilistic forecasts _____________________________________________________ From ef6ad4c2cfa578d9df9201690c57263bee68afcd Mon Sep 17 00:00:00 2001 From: johnhg Date: Fri, 16 Jul 2021 10:15:11 -0600 Subject: [PATCH 048/200] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b6e40f7ea..1c504e4d69 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,4 @@ 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). -Please see the [MET website](https://dtcenter.org/community-code/model-evaluation-tools-met) for more information. Support for the METplus components is provided through the [METplus Discussions](https://github.com/dtcenter/METplus/discussions) forum. Users are welcome and encouraged to answer or address each other's questions there! For more information, please read "[Welcome to the METplus Components Discussions](https://github.com/dtcenter/METplus/discussions/939)". +Please see the [MET website](https://dtcenter.org/community-code/model-evaluation-tools-met) and the [MET User's Guide](https://met.readthedocs.io/en/latest) for more information. Support for the METplus components is provided through the [METplus Discussions](https://github.com/dtcenter/METplus/discussions) forum. Users are welcome and encouraged to answer or address each other's questions there! For more information, please read "[Welcome to the METplus Components Discussions](https://github.com/dtcenter/METplus/discussions/939)". From c853259823321c0857378a6129d9f74df3bd3030 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 15:35:15 -0600 Subject: [PATCH 049/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index b1aabba118..baf83ea3ac 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -703,8 +703,8 @@ These statistics are only computed by the Grid-Stat tool and require vectors. He where the weights are applied at each grid location, with values assigned according to the weight option specified in the configuration file. The components of the :math:`S1` equation are as follows: -.. - e_g = (| \frac{\delta}{\delta x}(f - o)| + | \frac{\delta}{\delta y}(f - o)|) +.. math:: + \text{e_g} = (| \frac{\delta}{\delta x}(f - o)| + | \frac{\delta}{\delta y}(f - o)|) .. G_L = \text{max }(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max }(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) From b0b386993550b06cb67a1576f345868108ae1c3b Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 15:46:03 -0600 Subject: [PATCH 050/200] Add usepackage{amssymb} to conf.py --- met/docs/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/met/docs/conf.py b/met/docs/conf.py index 9474c4b5d7..9d193d4961 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -58,6 +58,7 @@ \usepackage{charter} \usepackage[defaultsans]{lato} \usepackage{inconsolata} + \usepackage{amssymb} \setcounter{secnumdepth}{4} \setcounter{tocdepth}{4} ''', From e08d1d334574f554e21c67bb9e8cc104e639c2f5 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 15:50:33 -0600 Subject: [PATCH 051/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 2 +- met/docs/conf.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index baf83ea3ac..9ba21cf1b8 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -704,7 +704,7 @@ These statistics are only computed by the Grid-Stat tool and require vectors. He where the weights are applied at each grid location, with values assigned according to the weight option specified in the configuration file. The components of the :math:`S1` equation are as follows: .. math:: - \text{e_g} = (| \frac{\delta}{\delta x}(f - o)| + | \frac{\delta}{\delta y}(f - o)|) + \text{e_g} = (\| \frac{$\delta}{\delta x}(f - o)\| + \| \frac{\delta}{\delta y}(f - o)\|) .. G_L = \text{max }(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max }(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) diff --git a/met/docs/conf.py b/met/docs/conf.py index 9d193d4961..9474c4b5d7 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -58,7 +58,6 @@ \usepackage{charter} \usepackage[defaultsans]{lato} \usepackage{inconsolata} - \usepackage{amssymb} \setcounter{secnumdepth}{4} \setcounter{tocdepth}{4} ''', From 0a5762ff306f429ec62797f0def2646773ad95ef Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 15:55:26 -0600 Subject: [PATCH 052/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 9ba21cf1b8..632aaa81e1 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -704,7 +704,7 @@ These statistics are only computed by the Grid-Stat tool and require vectors. He where the weights are applied at each grid location, with values assigned according to the weight option specified in the configuration file. The components of the :math:`S1` equation are as follows: .. math:: - \text{e_g} = (\| \frac{$\delta}{\delta x}(f - o)\| + \| \frac{\delta}{\delta y}(f - o)\|) + \text{e_g} = (\vert \frac{$\delta}{\delta x}(f - o)\vert + \vert \frac{\delta}{\delta y}(f - o)\vert) .. G_L = \text{max }(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max }(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) From 18ecff56e12fb20452381b3c7822e7a4febe4373 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 16:00:52 -0600 Subject: [PATCH 053/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 632aaa81e1..3f2ce410c6 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -704,7 +704,7 @@ These statistics are only computed by the Grid-Stat tool and require vectors. He where the weights are applied at each grid location, with values assigned according to the weight option specified in the configuration file. The components of the :math:`S1` equation are as follows: .. math:: - \text{e_g} = (\vert \frac{$\delta}{\delta x}(f - o)\vert + \vert \frac{\delta}{\delta y}(f - o)\vert) + e_g = (\vert \frac{$\delta}{\delta x}(f - o)\vert + \vert \frac{\delta}{\delta y}(f - o)\vert) .. G_L = \text{max }(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max }(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) From 5d46cdb1812469cfd499bb9d0630329c357b89be Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 16:05:53 -0600 Subject: [PATCH 054/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 3f2ce410c6..c67fdb4c66 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -704,7 +704,7 @@ These statistics are only computed by the Grid-Stat tool and require vectors. He where the weights are applied at each grid location, with values assigned according to the weight option specified in the configuration file. The components of the :math:`S1` equation are as follows: .. math:: - e_g = (\vert \frac{$\delta}{\delta x}(f - o)\vert + \vert \frac{\delta}{\delta y}(f - o)\vert) + e_g = (\vert \frac{\delta}{\delta x}(f - o)\vert + \vert \frac{\delta}{\delta y}(f - o)\vert) .. G_L = \text{max }(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max }(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) From 5c4bde2ed9190c1e194bb56ad9610aa2e3c41cd2 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 16:11:10 -0600 Subject: [PATCH 055/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index c67fdb4c66..93768357c1 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -706,13 +706,10 @@ where the weights are applied at each grid location, with values assigned accord .. math:: e_g = (\vert \frac{\delta}{\delta x}(f - o)\vert + \vert \frac{\delta}{\delta y}(f - o)\vert) -.. - G_L = \text{max }(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max }(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) + G_L = \text{max }(\vert \frac{\delta f}{\delta x}\vert,\vert \frac{\delta o}{\delta x}\vert) + \text{max }(\vert \frac{\delta f}{\delta y}\vert,\vert \frac{\delta o}{\delta y}|) -.. \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} -.. \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} MET verification measures for probabilistic forecasts From 98d874bcb1d7eebb6610fe34b03f3a126f9ab22c Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 16:14:34 -0600 Subject: [PATCH 056/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 93768357c1..be34acb1cf 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -706,8 +706,10 @@ where the weights are applied at each grid location, with values assigned accord .. math:: e_g = (\vert \frac{\delta}{\delta x}(f - o)\vert + \vert \frac{\delta}{\delta y}(f - o)\vert) +.. G_L = \text{max }(\vert \frac{\delta f}{\delta x}\vert,\vert \frac{\delta o}{\delta x}\vert) + \text{max }(\vert \frac{\delta f}{\delta y}\vert,\vert \frac{\delta o}{\delta y}|) +.. math:: \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} From 6c9ad33828d82f30d482d3f5ec9c3b51d4f997e0 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 16:19:11 -0600 Subject: [PATCH 057/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index be34acb1cf..544eee43bb 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -706,12 +706,12 @@ where the weights are applied at each grid location, with values assigned accord .. math:: e_g = (\vert \frac{\delta}{\delta x}(f - o)\vert + \vert \frac{\delta}{\delta y}(f - o)\vert) -.. G_L = \text{max }(\vert \frac{\delta f}{\delta x}\vert,\vert \frac{\delta o}{\delta x}\vert) + \text{max }(\vert \frac{\delta f}{\delta y}\vert,\vert \frac{\delta o}{\delta y}|) -.. math:: +.. \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} +.. \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} MET verification measures for probabilistic forecasts From 7bf9ca8f922b82bda704c3517525df1a7a49385f Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 16:27:24 -0600 Subject: [PATCH 058/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 544eee43bb..5051846228 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -708,8 +708,7 @@ where the weights are applied at each grid location, with values assigned accord G_L = \text{max }(\vert \frac{\delta f}{\delta x}\vert,\vert \frac{\delta o}{\delta x}\vert) + \text{max }(\vert \frac{\delta f}{\delta y}\vert,\vert \frac{\delta o}{\delta y}|) -.. - \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} + \text{S1_OG } = \frac{\text{EGBAR}}{\text{OGBAR}} .. \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} From 2d63c97588c7647436ac95c53314be7bf3de724f Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 16:31:37 -0600 Subject: [PATCH 059/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 5051846228..66ac3e75f3 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -708,10 +708,9 @@ where the weights are applied at each grid location, with values assigned accord G_L = \text{max }(\vert \frac{\delta f}{\delta x}\vert,\vert \frac{\delta o}{\delta x}\vert) + \text{max }(\vert \frac{\delta f}{\delta y}\vert,\vert \frac{\delta o}{\delta y}|) - \text{S1_OG } = \frac{\text{EGBAR}}{\text{OGBAR}} + \text{S1\_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} -.. - \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} + \text{FGOG\_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} MET verification measures for probabilistic forecasts _____________________________________________________ From fc374436e51123783369866bc335b086bbf21a6f Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 16:40:50 -0600 Subject: [PATCH 060/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 66ac3e75f3..f5fca85b7f 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -708,9 +708,9 @@ where the weights are applied at each grid location, with values assigned accord G_L = \text{max }(\vert \frac{\delta f}{\delta x}\vert,\vert \frac{\delta o}{\delta x}\vert) + \text{max }(\vert \frac{\delta f}{\delta y}\vert,\vert \frac{\delta o}{\delta y}|) - \text{S1\_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} + \text{S1\underline{ }OG} = \frac{\text{EGBAR}}{\text{OGBAR}} - \text{FGOG\_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} + \text{FGOG\underline{ }RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} MET verification measures for probabilistic forecasts _____________________________________________________ From 0a67133e63474e2f9f8f010bb4dd7719f32d47f2 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 16:44:34 -0600 Subject: [PATCH 061/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index f5fca85b7f..0d129a7c1f 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -708,9 +708,9 @@ where the weights are applied at each grid location, with values assigned accord G_L = \text{max }(\vert \frac{\delta f}{\delta x}\vert,\vert \frac{\delta o}{\delta x}\vert) + \text{max }(\vert \frac{\delta f}{\delta y}\vert,\vert \frac{\delta o}{\delta y}|) - \text{S1\underline{ }OG} = \frac{\text{EGBAR}}{\text{OGBAR}} + \text{S1\_OG } = \frac{\text{EGBAR}}{\text{OGBAR}} - \text{FGOG\underline{ }RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} + \text{FGOG\_RATIO } = \frac{\text{FGBAR}}{\text{OGBAR}} MET verification measures for probabilistic forecasts _____________________________________________________ From 43fdddcbb3b279f557745512073181987b32570e Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 16:50:34 -0600 Subject: [PATCH 062/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 0d129a7c1f..c388fc56a3 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -708,9 +708,9 @@ where the weights are applied at each grid location, with values assigned accord G_L = \text{max }(\vert \frac{\delta f}{\delta x}\vert,\vert \frac{\delta o}{\delta x}\vert) + \text{max }(\vert \frac{\delta f}{\delta y}\vert,\vert \frac{\delta o}{\delta y}|) - \text{S1\_OG } = \frac{\text{EGBAR}}{\text{OGBAR}} + \text{S1}\textunderscore\text{OG} = \frac{\text{EGBAR}}{\text{OGBAR}} - \text{FGOG\_RATIO } = \frac{\text{FGBAR}}{\text{OGBAR}} + \text{FGOG}\textunderscore\text{RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} MET verification measures for probabilistic forecasts _____________________________________________________ From f6677b1ffa38eef9c49eb5a7d2c09b6c816329c7 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 16:53:58 -0600 Subject: [PATCH 063/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index c388fc56a3..9f07c6dc22 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -708,9 +708,9 @@ where the weights are applied at each grid location, with values assigned accord G_L = \text{max }(\vert \frac{\delta f}{\delta x}\vert,\vert \frac{\delta o}{\delta x}\vert) + \text{max }(\vert \frac{\delta f}{\delta y}\vert,\vert \frac{\delta o}{\delta y}|) - \text{S1}\textunderscore\text{OG} = \frac{\text{EGBAR}}{\text{OGBAR}} + \text{S1\\_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} - \text{FGOG}\textunderscore\text{RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} + \text{FGOG\\_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} MET verification measures for probabilistic forecasts _____________________________________________________ From 4d6b96077b6ca83658613e59489ef84047dc3d03 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 17:01:44 -0600 Subject: [PATCH 064/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 9f07c6dc22..dc89e661f7 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -708,9 +708,9 @@ where the weights are applied at each grid location, with values assigned accord G_L = \text{max }(\vert \frac{\delta f}{\delta x}\vert,\vert \frac{\delta o}{\delta x}\vert) + \text{max }(\vert \frac{\delta f}{\delta y}\vert,\vert \frac{\delta o}{\delta y}|) - \text{S1\\_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} + \text{S1}$\_$\text{OG} = \frac{\text{EGBAR}}{\text{OGBAR}} - \text{FGOG\\_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} + \text{FGOG}$\_$\text{RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} MET verification measures for probabilistic forecasts _____________________________________________________ From d5a876fbc6971ff80c82346f6d43f15468b2ca45 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 17:59:48 -0600 Subject: [PATCH 065/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index dc89e661f7..8a9693b9f0 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -708,9 +708,21 @@ where the weights are applied at each grid location, with values assigned accord G_L = \text{max }(\vert \frac{\delta f}{\delta x}\vert,\vert \frac{\delta o}{\delta x}\vert) + \text{max }(\vert \frac{\delta f}{\delta y}\vert,\vert \frac{\delta o}{\delta y}|) - \text{S1}$\_$\text{OG} = \frac{\text{EGBAR}}{\text{OGBAR}} - \text{FGOG}$\_$\text{RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} +.. only:: latex + + .. math:: + \text{S1\_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} + + \text{FGOG\_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} + +.. only:: html + + .. math:: + \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} + + \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} + MET verification measures for probabilistic forecasts _____________________________________________________ From bb2c471e4011281b329b536a17890fb1beab66dc Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 18:24:40 -0600 Subject: [PATCH 066/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 16 +++++- met/docs/Users_Guide/appendixG.rst | 87 +++++++++++++++++++++++++----- 2 files changed, 87 insertions(+), 16 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 8a9693b9f0..52c5988566 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -147,8 +147,13 @@ Called "H_RATE" in FHO output :numref:`table_PS_format_info_FHO` H_RATE is defined as -.. math:: \text{H\_RATE } = \frac{n_{11}}{T}. +.. only:: latex + + .. math:: \text{H\_RATE } = \frac{n_{11}}{T}. +.. only:: html + + .. math:: \text{H_RATE } = \frac{n_{11}}{T}. H_RATE is equivalent to the H value computed by the NCEP verification system. H_RATE ranges from 0 to 1; a perfect forecast would have H_RATE = 1. @@ -581,7 +586,13 @@ The anomaly correlation coefficient is equivalent to the Pearson correlation coe The centered anomaly correlation coefficient (ANOM_CORR) which includes the mean error is defined as: -.. math:: \text{ANOM\_CORR } = \frac{ \overline{[(f - c) - \overline{(f - c)}][(a - c) - \overline{(a - c)}]}}{ \sqrt{ \overline{( (f - c) - \overline{(f - c)})^2} \overline{( (a - c) - \overline{(a - c)})^2}}} +.. only:: latex + + .. math:: \text{ANOM\_CORR } = \frac{ \overline{[(f - c) - \overline{(f - c)}][(a - c) - \overline{(a - c)}]}}{ \sqrt{ \overline{( (f - c) - \overline{(f - c)})^2} \overline{( (a - c) - \overline{(a - c)})^2}}} + +.. only:: html + + .. math:: \text{ANOM_CORR } = \frac{ \overline{[(f - c) - \overline{(f - c)}][(a - c) - \overline{(a - c)}]}}{ \sqrt{ \overline{( (f - c) - \overline{(f - c)})^2} \overline{( (a - c) - \overline{(a - c)})^2}}} The uncentered anomaly correlation coefficient (ANOM_CORR_UNCNTR) which does not include the mean errors is defined as: @@ -712,6 +723,7 @@ where the weights are applied at each grid location, with values assigned accord .. only:: latex .. math:: + \text{S1\_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} \text{FGOG\_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index fec4a52341..5808d27546 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -73,26 +73,42 @@ _________________________ FBAR and OBAR are the average values of the forecast and observed wind speed. -.. math:: \text{FBAR} = \frac{1}{N} \sum_i s_{fi} +.. math:: + + \text{FBAR} = \frac{1}{N} \sum_i s_{fi} - \text{OBAR} = {1 \over N} \sum_i s_{oi} + \text{OBAR} = {1 \over N} \sum_i s_{oi} _________________________ FS_RMS and OS_RMS are the root-mean-square values of the forecast and observed wind speeds. -.. math:: \text{FS\_RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} +.. only:: latex + + .. math:: + + \text{FS\_RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} + + \text{OS\_RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} + +.. only:: html - \text{OS\_RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} + .. math:: + + \text{FS_RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} + + \text{OS_RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} ___________________________ MSVE and RMSVE are, respectively, the mean squared, and root mean squared, lengths of the vector difference between the forecast and observed wind vectors. -.. math:: \text{MSVE} = \frac{1}{N} \sum_i | \mathbf{F}_i - \mathbf{O}_i|^2 +.. math:: + + \text{MSVE} = \frac{1}{N} \sum_i | \mathbf{F}_i - \mathbf{O}_i|^2 - \text{RMSVE} = \sqrt{MSVE} + \text{RMSVE} = \sqrt{MSVE} ____________________________ @@ -116,16 +132,35 @@ ________________________ FBAR_SPEED and OBAR_SPEED are the lengths of the average forecast and observed wind vectors. Note that this is *not* the same as the average forecast and observed wind speeds (*ie.,* the length of an average vector :math:`\neq` the average length of the vector). -.. math:: \text{FBAR\_SPEED } = | \mathbf{F}_a | - - \text{OBAR\_SPEED } = | \mathbf{O}_a | +.. only:: latex + + .. math:: + + \text{FBAR\_SPEED } = | \mathbf{F}_a | + + \text{OBAR\_SPEED } = | \mathbf{O}_a | + +.. only:: html + + .. math:: + + \text{FBAR_SPEED } = | \mathbf{F}_a | + + \text{OBAR_SPEED } = | \mathbf{O}_a | + ________________________ VDIFF_SPEED is the length (*ie. speed*) of the vector difference between the average forecast and average observed wind vectors. -.. math:: \text{VDIFF\_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | +.. only:: latex + + .. math:: \text{VDIFF\_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | + +.. only:: html + + .. math:: \text{VDIFF_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or , equivalently, that :math:`| \text{SPEED_ERR} | \leq \text{VDIFF_SPEED}`. @@ -134,7 +169,13 @@ _________________________ VDIFF_DIR is the direction of the vector difference of the average forecast and average observed wind vectors. Note that this is {\it not} the same as the difference in direction of the average forecast and average observed wind vectors. This latter quantity would be FDIR :math:`-` ODIR. -.. math:: \text{VDIFF\_DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) +.. only:: latex + + .. math:: \text{VDIFF\_DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) + +.. only:: html + + .. math:: \text{VDIFF_DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) _________________________ @@ -148,16 +189,34 @@ ___________________________ SPEED_ABSERR is the absolute value of SPEED_ERR. Note that we have SPEED_ABSERR :math:`\leq` VDIFF_SPEED (see the discussion of VDIFF_SPEED above). -.. math:: \text{SPEED_ABSERR } = | \text{SPEED_ERR} | +.. only:: latex + + .. math:: \text{SPEED\_ABSERR } = | \text{SPEED_ERR} | + +.. only:: html + + .. math:: \text{SPEED_ABSERR } = | \text{SPEED_ERR} | __________________________ DIR_ERR is the signed angle between the directions of the average forecast and average observed wind vectors. Positive if the forecast vector is counterclockwise from the observed vector. -.. math:: \text{DIR_ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) +.. only:: latex + + .. math:: \text{DIR\_ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) + +.. only:: html + + .. math:: \text{DIR_ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) __________________________ DIR_ABSERR is the absolute value of DIR_ERR. In other words, it's an unsigned angle rather than a signed angle. -.. math:: \text{DIR_ABSERR } = | \text{DIR_ERR}| +.. only:: latex + + .. math:: \text{DIR\_ABSERR } = | \text{DIR_ERR}| + +.. only:: html + + .. math:: \text{DIR\_ABSERR } = | \text{DIR_ERR}| From 6f483c28e22fa4c0469bcf22c232952878f93428 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 18:33:02 -0600 Subject: [PATCH 067/200] Modify math formatting in Appendix C --- met/docs/Users_Guide/appendixC.rst | 10 ++++++++-- met/docs/Users_Guide/appendixG.rst | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 52c5988566..082dcc208c 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -257,7 +257,13 @@ where A more general format that uses percentages is provided by Ou (:ref:`Ou, 2016 `), -.. math:: \text{HSS(\%) } = 100 \ast \frac{(H - E)}{(T - E)} +.. only:: latex + + .. math:: \text{HSS(\%) } = 100 \ast \frac{(H - E)}{(T - E)} + +.. only:: html + + .. math:: \text{HSS(%) } = 100 \ast \frac{(H - E)}{(T - E)} where H is the number of forecasts in the correct category and E is the expected number of forecasts by chance. @@ -723,7 +729,7 @@ where the weights are applied at each grid location, with values assigned accord .. only:: latex .. math:: - + \text{S1\_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} \text{FGOG\_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index 5808d27546..d43231a398 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -219,4 +219,4 @@ DIR_ABSERR is the absolute value of DIR_ERR. In other words, it's an unsigned an .. only:: html - .. math:: \text{DIR\_ABSERR } = | \text{DIR_ERR}| + .. math:: \text{DIR_ABSERR } = | \text{DIR_ERR}| From ff85a53591196480aacacb06a436a386935fed64 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 18:40:38 -0600 Subject: [PATCH 068/200] Fix warnings in wavelet-stat.rst --- met/docs/Users_Guide/wavelet-stat.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/met/docs/Users_Guide/wavelet-stat.rst b/met/docs/Users_Guide/wavelet-stat.rst index 0f4bf9a281..394eed2b1e 100644 --- a/met/docs/Users_Guide/wavelet-stat.rst +++ b/met/docs/Users_Guide/wavelet-stat.rst @@ -460,11 +460,11 @@ The dimensions and variables included in the wavelet_stat NetCDF files are descr * - NetCDF Dimension - Description * - x - - Dimension of the tile which equals :math:`\mathbf{2^n} + - Dimension of the tile which equals :math:`\mathbf{2^n}` * - y - - Dimension of the tile which equals :math:`\mathbf{2^n} + - Dimension of the tile which equals :math:`\mathbf{2^n}` * - scale - - Dimension for the number of scales. This is set to **n+2**, where :math:`\mathbf{2^n} is the tile dimension. The 2 extra scales are for the binary image and the wavelet averaged over the whole tile. + - Dimension for the number of scales. This is set to **n+2**, where :math:`\mathbf{2^n}` is the tile dimension. The 2 extra scales are for the binary image and the wavelet averaged over the whole tile. * - tile - Dimension for the number of tiles used From b44b743544129312f516c3affabb0ea8ab494106 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Mon, 19 Jul 2021 18:54:22 -0600 Subject: [PATCH 069/200] Omit Indices and tables in PDF version of User Guide --- met/docs/Users_Guide/index.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/met/docs/Users_Guide/index.rst b/met/docs/Users_Guide/index.rst index 40151728e5..7395984836 100644 --- a/met/docs/Users_Guide/index.rst +++ b/met/docs/Users_Guide/index.rst @@ -79,11 +79,12 @@ The National Center for Atmospheric Research (NCAR) is sponsored by NSF. The DTC appendixF appendixG +.. only:: html -Indices and tables -================== + Indices and tables + ================== -* :ref:`genindex` -* :ref:`search` + * :ref:`genindex` + * :ref:`search` From 44acf1594610c07480af7ee40cc3a1b3079dbfdf Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Tue, 20 Jul 2021 09:37:03 -0600 Subject: [PATCH 070/200] Modify math formatting in Appendix G --- met/docs/Users_Guide/appendixG.rst | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index d43231a398..89193c3fe3 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -162,7 +162,15 @@ VDIFF_SPEED is the length (*ie. speed*) of the vector difference between the ave .. math:: \text{VDIFF_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | -Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or , equivalently, that :math:`| \text{SPEED_ERR} | \leq \text{VDIFF_SPEED}`. +Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math: `| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or , equivalently, that + +.. only:: latex + + :math: `| \text{SPEED\_ERR} | \leq \text{VDIFF\_SPEED}`. + +.. only:: html + + :math: `| \text{SPEED_ERR} | \leq \text{VDIFF_SPEED}`. _________________________ @@ -182,7 +190,14 @@ _________________________ SPEED_ERR is the difference in the lengths (speeds) of the average forecast and average observed wind vectors. (See the discussion of VDIFF_SPEED above.) -.. math:: \text{SPEED_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR_SPEED } - \text{ OBAR_SPEED} +.. only:: latex + + .. math:: \text{SPEED\_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR\_SPEED } - \text{ OBAR\_SPEED} + +.. only:: html + + .. math:: \text{SPEED_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR_SPEED } - \text{ OBAR_SPEED} + ___________________________ From fbf538a1182f840078a4970eb2c9f49ccf029071 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Tue, 20 Jul 2021 09:42:20 -0600 Subject: [PATCH 071/200] Modify math formatting in Appendix E --- met/docs/Users_Guide/appendixE.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/docs/Users_Guide/appendixE.rst b/met/docs/Users_Guide/appendixE.rst index e5967f61f4..a50afe1703 100644 --- a/met/docs/Users_Guide/appendixE.rst +++ b/met/docs/Users_Guide/appendixE.rst @@ -59,7 +59,7 @@ The other interpolation parameter is **interp_width**. This specifies the width interp_width = 5; -The value must be odd and ≥ 1. If a value of 1 is specified, then nearest neighbor interpolation will be used regardless of the value assigned to **interp_method**. +The value must be odd and :math:`\geqq` 1. If a value of 1 is specified, then nearest neighbor interpolation will be used regardless of the value assigned to **interp_method**. The fact that an interpolation box is used has one subtle implication-the "To" grid is effectively fattened by half the width of the interpolation box. This means that even for a "To" grid that is entirely contained in one hemisphere, if it comes close to the equator, this virtual fattening may be enough to push it over the equator, and the user will then have to provide input WWMCA files for both hemispheres, even though the "To" grid doesn't cross the equator. The WWMCA-Regrid tool should detect this situation and complain to the user if not given the correct input files. From 3a48e02a05817ec7947af8b751bb18ecfb4fc297 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Tue, 20 Jul 2021 09:55:20 -0600 Subject: [PATCH 072/200] Modify math formatting in Appendix G --- met/docs/Users_Guide/appendixG.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index 89193c3fe3..45358c7217 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -162,15 +162,15 @@ VDIFF_SPEED is the length (*ie. speed*) of the vector difference between the ave .. math:: \text{VDIFF_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | -Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math: `| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or , equivalently, that +Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or , equivalently, that .. only:: latex - :math: `| \text{SPEED\_ERR} | \leq \text{VDIFF\_SPEED}`. + .. math:: `| \text{SPEED\_ERR} | \leq \text{VDIFF\_SPEED}`. .. only:: html - :math: `| \text{SPEED_ERR} | \leq \text{VDIFF_SPEED}`. + .. math:: `| \text{SPEED_ERR} | \leq \text{VDIFF_SPEED}`. _________________________ From 17f92d1ef236cee23a2c799ae2e78382fc80237c Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Tue, 20 Jul 2021 10:00:25 -0600 Subject: [PATCH 073/200] Modify math formatting in Appendix G --- met/docs/Users_Guide/appendixG.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index 45358c7217..f16cf28bf8 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -166,11 +166,11 @@ Note that this is *not* the same as the difference in lengths (speeds) of the av .. only:: latex - .. math:: `| \text{SPEED\_ERR} | \leq \text{VDIFF\_SPEED}`. + :math:`| \text{SPEED\_ERR} | \leq \text{VDIFF\_SPEED}`. .. only:: html - .. math:: `| \text{SPEED_ERR} | \leq \text{VDIFF_SPEED}`. + :math:`| \text{SPEED_ERR} | \leq \text{VDIFF_SPEED}`. _________________________ From 5a6b32fd59ec95364965a6e61b6c38832eb83838 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Tue, 20 Jul 2021 10:09:54 -0600 Subject: [PATCH 074/200] Modify math formatting in Appendix G --- met/docs/Users_Guide/appendixG.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index f16cf28bf8..474b458404 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -166,11 +166,11 @@ Note that this is *not* the same as the difference in lengths (speeds) of the av .. only:: latex - :math:`| \text{SPEED\_ERR} | \leq \text{VDIFF\_SPEED}`. + .. math:: | \text{SPEED\_ERR} | \leq \text{VDIFF\_SPEED.} .. only:: html - :math:`| \text{SPEED_ERR} | \leq \text{VDIFF_SPEED}`. + .. math:: | \text{SPEED_ERR} | \leq \text{VDIFF_SPEED.} _________________________ From be071603083a1bbf6abea928c6143ffd576168a3 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Tue, 20 Jul 2021 10:13:00 -0600 Subject: [PATCH 075/200] Modify math formatting in Appendix G --- met/docs/Users_Guide/appendixG.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index 474b458404..2310958779 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -166,10 +166,12 @@ Note that this is *not* the same as the difference in lengths (speeds) of the av .. only:: latex +.. .. math:: | \text{SPEED\_ERR} | \leq \text{VDIFF\_SPEED.} .. only:: html +.. .. math:: | \text{SPEED_ERR} | \leq \text{VDIFF_SPEED.} _________________________ From a05d22191b6bb22ffb4732ab5bc18c85fa8aa466 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Tue, 20 Jul 2021 10:27:05 -0600 Subject: [PATCH 076/200] Modify math formatting in Appendix G --- met/docs/Users_Guide/appendixG.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index 2310958779..3dfc146514 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -166,13 +166,11 @@ Note that this is *not* the same as the difference in lengths (speeds) of the av .. only:: latex -.. - .. math:: | \text{SPEED\_ERR} | \leq \text{VDIFF\_SPEED.} + .. math:: \vert \text{SPEED\_ERR} \vert \leq \text{VDIFF\_SPEED.} .. only:: html -.. - .. math:: | \text{SPEED_ERR} | \leq \text{VDIFF_SPEED.} + .. math:: \vert \text{SPEED_ERR} \vert \leq \text{VDIFF_SPEED.} _________________________ From 7c912c57307a2d86c7bb61c65e6b3dee315d1b29 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Tue, 20 Jul 2021 10:30:32 -0600 Subject: [PATCH 077/200] Modify math formatting in Appendix G --- met/docs/Users_Guide/appendixG.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index 3dfc146514..9037fb2023 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -206,11 +206,11 @@ SPEED_ABSERR is the absolute value of SPEED_ERR. Note that we have SPEED_ABSERR .. only:: latex - .. math:: \text{SPEED\_ABSERR } = | \text{SPEED_ERR} | + .. math:: \text{SPEED\_ABSERR } = \vert \text{SPEED_ERR} \vert .. only:: html - .. math:: \text{SPEED_ABSERR } = | \text{SPEED_ERR} | + .. math:: \text{SPEED_ABSERR } = \vert \text{SPEED_ERR} \vert __________________________ @@ -230,8 +230,8 @@ DIR_ABSERR is the absolute value of DIR_ERR. In other words, it's an unsigned an .. only:: latex - .. math:: \text{DIR\_ABSERR } = | \text{DIR_ERR}| + .. math:: \text{DIR\_ABSERR } = \vert \text{DIR_ERR} \vert .. only:: html - .. math:: \text{DIR_ABSERR } = | \text{DIR_ERR}| + .. math:: \text{DIR_ABSERR } = \vert \text{DIR_ERR} \vert From c39558fa07cad0eb385391e00ffa7a716b92ce78 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Tue, 20 Jul 2021 10:36:19 -0600 Subject: [PATCH 078/200] Modify math formatting in Appendix G --- met/docs/Users_Guide/appendixG.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index 9037fb2023..539a521d1a 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -166,11 +166,11 @@ Note that this is *not* the same as the difference in lengths (speeds) of the av .. only:: latex - .. math:: \vert \text{SPEED\_ERR} \vert \leq \text{VDIFF\_SPEED.} + .. math:: \vert \text{SPEED\_ERR } \vert \leq \text{VDIFF\_SPEED. } .. only:: html - .. math:: \vert \text{SPEED_ERR} \vert \leq \text{VDIFF_SPEED.} + .. math:: \vert \text{SPEED_ERR } \vert \leq \text{VDIFF_SPEED. } _________________________ @@ -192,11 +192,11 @@ SPEED_ERR is the difference in the lengths (speeds) of the average forecast and .. only:: latex - .. math:: \text{SPEED\_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR\_SPEED } - \text{ OBAR\_SPEED} + .. math:: \text{SPEED\_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR\_SPEED } - \text{ OBAR\_SPEED } .. only:: html - .. math:: \text{SPEED_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR_SPEED } - \text{ OBAR_SPEED} + .. math:: \text{SPEED_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR_SPEED } - \text{ OBAR_SPEED } ___________________________ @@ -206,11 +206,11 @@ SPEED_ABSERR is the absolute value of SPEED_ERR. Note that we have SPEED_ABSERR .. only:: latex - .. math:: \text{SPEED\_ABSERR } = \vert \text{SPEED_ERR} \vert + .. math:: \text{SPEED\_ABSERR } = \vert \text{SPEED\_ERR } \vert .. only:: html - .. math:: \text{SPEED_ABSERR } = \vert \text{SPEED_ERR} \vert + .. math:: \text{SPEED_ABSERR } = \vert \text{SPEED_ERR } \vert __________________________ @@ -230,8 +230,8 @@ DIR_ABSERR is the absolute value of DIR_ERR. In other words, it's an unsigned an .. only:: latex - .. math:: \text{DIR\_ABSERR } = \vert \text{DIR_ERR} \vert + .. math:: \text{DIR\_ABSERR } = \vert \text{DIR\_ERR } \vert .. only:: html - .. math:: \text{DIR_ABSERR } = \vert \text{DIR_ERR} \vert + .. math:: \text{DIR_ABSERR } = \vert \text{DIR_ERR } \vert From d7923a51dbcfbbd6622c106df7325190ff7fef28 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Tue, 20 Jul 2021 10:43:45 -0600 Subject: [PATCH 079/200] Modify math formatting in Appendix G --- met/docs/Users_Guide/appendixG.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index 539a521d1a..6ef21df5f5 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -163,14 +163,10 @@ VDIFF_SPEED is the length (*ie. speed*) of the vector difference between the ave .. math:: \text{VDIFF_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or , equivalently, that - .. only:: latex - - .. math:: \vert \text{SPEED\_ERR } \vert \leq \text{VDIFF\_SPEED. } - + :math:`\vert \text{SPEED\_ERR } \vert \leq \text{VDIFF\_SPEED. }` .. only:: html - - .. math:: \vert \text{SPEED_ERR } \vert \leq \text{VDIFF_SPEED. } + :math:`\vert \text{SPEED_ERR } \vert \leq \text{VDIFF_SPEED. }` _________________________ From ecf75bcc265404577b0f4ce1eb3c88a9e2d2de02 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Tue, 20 Jul 2021 10:51:59 -0600 Subject: [PATCH 080/200] Modify math formatting in Appendix G --- met/docs/Users_Guide/appendixG.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index 6ef21df5f5..8c46641ced 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -162,11 +162,13 @@ VDIFF_SPEED is the length (*ie. speed*) of the vector difference between the ave .. math:: \text{VDIFF_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | -Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or , equivalently, that .. only:: latex - :math:`\vert \text{SPEED\_ERR } \vert \leq \text{VDIFF\_SPEED. }` + + Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or, equivalently, that :math:`\vert \text{SPEED\_ERR } \vert \leq \text{VDIFF\_SPEED. }` + .. only:: html - :math:`\vert \text{SPEED_ERR } \vert \leq \text{VDIFF_SPEED. }` + + Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or, equivalently, that :math:`\vert \text{SPEED_ERR } \vert \leq \text{VDIFF_SPEED. }` _________________________ From 0aaeeccab8f631ceab46502dfcb36ccbcdae04bd Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Tue, 20 Jul 2021 12:40:04 -0600 Subject: [PATCH 081/200] Change release date in conf.py --- met/docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/docs/conf.py b/met/docs/conf.py index 9474c4b5d7..16bb9bcd99 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -24,7 +24,7 @@ verinfo = version release = f'{version}' release_year = '2021' -release_date = f'{release_year}-06-25' +release_date = f'{release_year}-07-20' copyright = f'{release_year}, {author}' # -- General configuration --------------------------------------------------- From 3952496aa1133fa9e61a0538c4ffb37247d4a1be Mon Sep 17 00:00:00 2001 From: hsoh-u Date: Wed, 21 Jul 2021 10:37:49 -0600 Subject: [PATCH 082/200] #1852 get_string_val: check if 2D variable. Also checking if the variable does not have dimension (#1860) Co-authored-by: Howard Soh --- met/src/libcode/vx_nc_util/nc_utils.cc | 89 ++++++++++++++++++-------- 1 file changed, 64 insertions(+), 25 deletions(-) diff --git a/met/src/libcode/vx_nc_util/nc_utils.cc b/met/src/libcode/vx_nc_util/nc_utils.cc index 5ee664a17e..14c473702c 100644 --- a/met/src/libcode/vx_nc_util/nc_utils.cc +++ b/met/src/libcode/vx_nc_util/nc_utils.cc @@ -1040,21 +1040,28 @@ ConcatString* get_string_val(NcFile * nc, const char * var_name, const int index ConcatString* get_string_val(NcVar *var, const int index, const int len, ConcatString &tmp_cs) { - int dim_idx = 0; char tmp_str[len]; std::vector start; std::vector count; const char *method_name = "get_string_val() "; - int dim_size = get_dim_size(var, dim_idx); - if ((index+len) > dim_size) { - NcDim nc_dim = get_nc_dim(var, dim_idx); - mlog << Error << "\n" << method_name << "The requested start offset and count (" - << index << ", " << len << ") exceeds the dimension[" << dim_idx << "]=" << dim_size << " " - << (IS_VALID_NC(nc_dim) ? GET_NC_NAME(nc_dim) : " ") - << " for the variable " << GET_NC_NAME_P(var) << ".\n\n"; + if (2 != get_dim_count(var)) { + mlog << Error << "\n" << method_name << GET_NC_NAME_P(var) + << " is not a two dimensional variablle. start offset and count: (" + << index << ", " << len << ").\n\n"; exit(1); } + else { + int dim_size1 = get_dim_size(var, 0); + int dim_size2 = get_dim_size(var, 1); + if ((index > dim_size1) || (len > dim_size2)) { + mlog << Error << "\n" << method_name << "The start offset and count (" + << index << ", " << len << ") exceeds the dimension size (" + << dim_size1 << ", " << dim_size2 << ") for the variable " + << GET_NC_NAME_P(var) << ".\n\n"; + exit(1); + } + } // // Retrieve the character array value from the NetCDF variable. @@ -1092,10 +1099,18 @@ int get_int_var(NcVar * var, const int index) { if (IS_VALID_NC_P(var)) { int dim_idx = 0; int dim_size = get_dim_size(var, dim_idx); - if (index > dim_size) { + if (0 >= dim_size) { + if ((index > 0) && (0 >= dim_size)) { + mlog << Error << "\n" << method_name << "The start offset (" + << index << ") should be 0 because of no dimension at the variable " + << GET_NC_NAME_P(var) << ".\n\n"; + exit(1); + } + } + else if (index > dim_size) { NcDim nc_dim = get_nc_dim(var, dim_idx); - mlog << Error << "\n" << method_name << "The requested start offset (" - << index << ") exceeds the dimension[" << dim_idx << "]=" << dim_size << " " + mlog << Error << "\n" << method_name << "The start offset (" + << index << ") exceeds the dimension " << dim_size << " " << (IS_VALID_NC(nc_dim) ? GET_NC_NAME(nc_dim) : " ") << " for the variable " << GET_NC_NAME_P(var) << ".\n\n"; exit(1); @@ -1121,10 +1136,18 @@ double get_nc_time(NcVar * var, const int index) { if (IS_VALID_NC_P(var)) { int dim_idx = 0; int dim_size = get_dim_size(var, dim_idx); - if (index > dim_size) { + if (0 >= dim_size) { + if (index > 0) { + mlog << Error << "\n" << method_name << "The start offset (" + << index << ") should be 0 because of no dimension at the variable " + << GET_NC_NAME_P(var) << ".\n\n"; + exit(1); + } + } + else if (index > dim_size) { NcDim nc_dim = get_nc_dim(var, dim_idx); - mlog << Error << "\n" << method_name << "The requested start offset (" - << index << ") exceeds the dimension[" << dim_idx << "]=" << dim_size << " " + mlog << Error << "\n" << method_name << "The start offset (" + << index << ") exceeds the dimension " << dim_size << " " << (IS_VALID_NC(nc_dim) ? GET_NC_NAME(nc_dim) : " ") << " for the variable " << GET_NC_NAME_P(var) << ".\n\n"; exit(1); @@ -1201,10 +1224,18 @@ float get_float_var(NcVar * var, const int index) { if (IS_VALID_NC_P(var)) { int dim_idx = 0; int dim_size = get_dim_size(var, dim_idx); - if (index > dim_size) { + if (0 >= dim_size) { + if (index > 0) { + mlog << Error << "\n" << method_name << "The start offset (" + << index << ") should be 0 because of no dimension at the variable " + << GET_NC_NAME_P(var) << ".\n\n"; + exit(1); + } + } + else if ((index > dim_size) && (0 < dim_size)){ NcDim nc_dim = get_nc_dim(var, dim_idx); - mlog << Error << "\n" << method_name << "The requested start offset (" - << index << ") exceeds the dimension[" << dim_idx << "]=" << dim_size << " " + mlog << Error << "\n" << method_name << "The start offset (" + << index << ") exceeds the dimension " << dim_size << " " << (IS_VALID_NC(nc_dim) ? GET_NC_NAME(nc_dim) : " ") << " for the variable " << GET_NC_NAME_P(var) << ".\n\n"; exit(1); @@ -1284,10 +1315,10 @@ bool _get_nc_data(NcVar *var, T *data, T bad_data, const long *curs) { const int dimC = get_dim_count(var); for (int idx = 0 ; idx < dimC; idx++) { int dim_size = get_dim_size(var, idx); - if (curs[idx] > dim_size) { + if ((curs[idx] > dim_size) && (0 < dim_size)) { NcDim nc_dim = get_nc_dim(var, idx); - mlog << Error << "\n" << method_name << "The requested start offset (" - << curs[idx] << ") exceeds the dimension[" << idx << "]=" << dim_size << " " + mlog << Error << "\n" << method_name << "The start offset (" + << curs[idx] << ") exceeds the dimension[" << idx << "] " << dim_size << " " << (IS_VALID_NC(nc_dim) ? GET_NC_NAME(nc_dim) : " ") << " for the variable " << GET_NC_NAME_P(var) << ".\n\n"; exit(1); @@ -1331,10 +1362,18 @@ bool _get_nc_data(NcVar *var, T *data, T bad_data, const long dim, const long cu start.push_back((size_t)cur); count.push_back((size_t)dim); int dim_size = get_dim_size(var, dim_idx); - if ((cur+dim) > dim_size) { + if (0 >= dim_size) { + if ((cur > 0) || (dim > 1)) { + mlog << Error << "\n" << method_name << "The start offset and count (" + << cur << ", " << dim << ") should be (0, 1) because of no dimension at the variable " + << GET_NC_NAME_P(var) << ".\n\n"; + exit(1); + } + } + else if (((cur+dim) > dim_size) && (0 < dim_size)) { NcDim nc_dim = get_nc_dim(var, dim_idx); - mlog << Error << "\n" << method_name << "The requested start offset and count (" - << cur << ", " << dim << ") exceeds the dimension[" << dim_idx << "]=" << dim_size << " " + mlog << Error << "\n" << method_name << "The start offset and count (" + << cur << " + " << dim << ") exceeds the dimension " << dim_size << " " << (IS_VALID_NC(nc_dim) ? GET_NC_NAME(nc_dim) : " ") << " for the variable " << GET_NC_NAME_P(var) << ".\n\n"; exit(1); @@ -1377,9 +1416,9 @@ bool _get_nc_data(NcVar *var, T *data, T bad_data, const long *dims, const long int dim_size = get_dim_size(var, idx); if ((curs[idx]+dims[idx]) > dim_size) { NcDim nc_dim = get_nc_dim(var, idx); - mlog << Error << "\n" << method_name << "The requested start offset and count (" + mlog << Error << "\n" << method_name << "The start offset and count (" << curs[idx] << ", " << dims[idx] << ") exceeds the dimension[" - << idx << "]=" << dim_size << " " + << idx << "] " << dim_size << " " << (IS_VALID_NC(nc_dim) ? GET_NC_NAME(nc_dim) : " ") << " for the variable " << GET_NC_NAME_P(var) << ".\n\n"; exit(1); From 0c0c4274f513ef3067dd5d3189c1feadefce3580 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Wed, 21 Jul 2021 14:39:49 -0600 Subject: [PATCH 083/200] Feature 1453 create pdf user guide (#1859) * Enable PDF creation * Modify inputenc, fontenc latex_elements * Fix typo in conf.py * Replace unicode with ascii * Replace unicode exponent with math mode * Change eqnarray to align * Replace gif images with png for PDF * Fix png file names * Escape underscore in variable name in math mode * Escape underscore in variable name in math mode * Remove underscores from variables in math mode * Replace bar with overline in some equations * Test derefencing underscores in tables * Test math changes in grid stat * Test math formatting * Test math formatting * Add sphinx.ext.pngmath to conf.py * Fix typo in conf.py * Add sphinx.ext.mathjax to conf.py * Add sphinx.ext.imgmath to conf.py * Fix typo in conf.py * Change math formatting in Appendix C * Temporarily disable equations with errors in Appendix C * Remove sphinx.ext.imgmath in conf.py * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Add sphinx.ext.imgmath to conf.py * Modify math formatting in Appendix C * Temporarily disable equations with errors in Appendix C * Remove sphinx.ext.imgmath in conf.py * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Temporarily disable equations with errors * Modify math formatting in Appendix C * Add usepackage{amssymb} to conf.py * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Modify math formatting in Appendix C * Fix warnings in wavelet-stat.rst * Omit Indices and tables in PDF version of User Guide * Modify math formatting in Appendix G * Modify math formatting in Appendix E * Modify math formatting in Appendix G * Modify math formatting in Appendix G * Modify math formatting in Appendix G * Modify math formatting in Appendix G * Modify math formatting in Appendix G * Modify math formatting in Appendix G * Modify math formatting in Appendix G * Modify math formatting in Appendix G * Modify math formatting in Appendix G * Change release date in conf.py Co-authored-by: John Halley Gotway --- .readthedocs.yaml | 2 +- .../map/admin_by_country/admin_Yemen_data | 4 +- met/data/map/admin_data | 4 +- met/docs/Users_Guide/appendixA.rst | 6 +- met/docs/Users_Guide/appendixB.rst | 4 +- met/docs/Users_Guide/appendixC.rst | 132 +++++++++++------- met/docs/Users_Guide/appendixD.rst | 6 +- met/docs/Users_Guide/appendixE.rst | 18 +-- met/docs/Users_Guide/appendixF.rst | 8 +- met/docs/Users_Guide/appendixG.rst | 104 +++++++++++--- met/docs/Users_Guide/data_io.rst | 10 +- met/docs/Users_Guide/ensemble-stat.rst | 4 +- .../figure/plotting-Gilbert-skill-score.png | Bin 0 -> 15350 bytes .../figure/plotting-verification.png | Bin 0 -> 60682 bytes .../figure/plotting_Gilbert_skill_score.gif | Bin 12846 -> 0 bytes .../figure/plotting_verification.gif | Bin 46212 -> 0 bytes met/docs/Users_Guide/grid-diag.rst | 4 +- met/docs/Users_Guide/grid-stat.rst | 16 +-- met/docs/Users_Guide/index.rst | 9 +- met/docs/Users_Guide/masking.rst | 38 ++--- met/docs/Users_Guide/mode-analysis.rst | 6 +- met/docs/Users_Guide/mode-td.rst | 16 +-- met/docs/Users_Guide/mode.rst | 10 +- met/docs/Users_Guide/plotting.rst | 4 +- met/docs/Users_Guide/point-stat.rst | 36 ++--- met/docs/Users_Guide/reformat_grid.rst | 42 +++--- met/docs/Users_Guide/reformat_point.rst | 58 ++++---- met/docs/Users_Guide/refs.rst | 22 +-- met/docs/Users_Guide/rmw-analysis.rst | 2 +- met/docs/Users_Guide/series-analysis.rst | 2 +- met/docs/Users_Guide/stat-analysis.rst | 28 ++-- met/docs/Users_Guide/tc-dland.rst | 2 +- met/docs/Users_Guide/tc-gen.rst | 6 +- met/docs/Users_Guide/tc-pairs.rst | 10 +- met/docs/Users_Guide/tc-rmw.rst | 2 +- met/docs/Users_Guide/tc-stat.rst | 6 +- met/docs/Users_Guide/wavelet-stat.rst | 44 +++--- met/docs/conf.py | 55 +++++++- 38 files changed, 440 insertions(+), 280 deletions(-) create mode 100644 met/docs/Users_Guide/figure/plotting-Gilbert-skill-score.png create mode 100644 met/docs/Users_Guide/figure/plotting-verification.png delete mode 100644 met/docs/Users_Guide/figure/plotting_Gilbert_skill_score.gif delete mode 100644 met/docs/Users_Guide/figure/plotting_verification.gif diff --git a/.readthedocs.yaml b/.readthedocs.yaml index e148a2aad0..acae87d7f0 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -7,7 +7,7 @@ version: 2 # Build all formats (htmlzip, pdf, epub) #formats: all -formats: [] +formats: [pdf] # Optionally set the version of Python and requirements required to build your # docs diff --git a/met/data/map/admin_by_country/admin_Yemen_data b/met/data/map/admin_by_country/admin_Yemen_data index 3bb2d565c1..38eacd3988 100644 --- a/met/data/map/admin_by_country/admin_Yemen_data +++ b/met/data/map/admin_by_country/admin_Yemen_data @@ -126,7 +126,7 @@ 12.94042 -45.09903 12.86061 -45.05790 12.80125 -44.85958 -4 33 13.829 14.8252 -46.0336 -44.5861 'Al Bayḑā’ (Yemen)' +4 33 13.829 14.8252 -46.0336 -44.5861 'Al Bayḑā' (Yemen)' 14.53238 -45.11610 14.50399 -45.18688 14.55476 -45.31480 @@ -579,7 +579,7 @@ 17.42610 -43.61780 17.36670 -43.68330 17.33890 -43.83190 -17 40 14.7473 16.0428 -45.1087 -43.5061 'Şan‘ā’ (Yemen)' +17 40 14.7473 16.0428 -45.1087 -43.5061 'Şan‘ā' (Yemen)' 15.12214 -45.08009 14.79469 -44.90892 14.74730 -44.83651 diff --git a/met/data/map/admin_data b/met/data/map/admin_data index e1e5e18f84..db40e5e64b 100644 --- a/met/data/map/admin_data +++ b/met/data/map/admin_data @@ -82728,7 +82728,7 @@ 30.32615 -48.28101 30.20689 -48.39930 30.20050 -48.40535 -1193 33 13.829 14.8252 -46.0336 -44.5861 'Al Bayḑā’ (Yemen)' +1193 33 13.829 14.8252 -46.0336 -44.5861 'Al Bayḑā' (Yemen)' 14.53238 -45.11610 14.50399 -45.18688 14.55476 -45.31480 @@ -85990,7 +85990,7 @@ 35.17110 -43.41893 35.14398 -43.44602 35.05437 -43.54642 -1267 40 14.7473 16.0428 -45.1087 -43.5061 'Şan‘ā’ (Yemen)' +1267 40 14.7473 16.0428 -45.1087 -43.5061 'Şan‘ā' (Yemen)' 15.12214 -45.08009 14.79469 -44.90892 14.74730 -44.83651 diff --git a/met/docs/Users_Guide/appendixA.rst b/met/docs/Users_Guide/appendixA.rst index 9a0d619648..f681f48361 100644 --- a/met/docs/Users_Guide/appendixA.rst +++ b/met/docs/Users_Guide/appendixA.rst @@ -44,7 +44,7 @@ A. Currently, very few graphics are included. The plotting tools (plot_point_obs **Q. How do I find the version of the tool I am using?** -A. Type the name of the tool followed by **-version**. For example, type “pb2nc **-version**”. +A. Type the name of the tool followed by **-version**. For example, type "pb2nc **-version**". **Q. What are MET's conventions for latitude, longitude, azimuth and bearing angles?** @@ -81,11 +81,11 @@ The first place to look for help with individual commands is this user's guide o **Error while loading shared libraries** -* Add the lib dir to your LD_LIBRARY_PATH. For example, if you receive the following error: “./mode_analysis: error while loading shared libraries: libgsl.so.19: cannot open shared object file: No such file or directory”, you should add the path to the gsl lib (for example, */home/user/MET/gsl-2.1/lib*) to your LD_LIBRARY_PATH. +* Add the lib dir to your LD_LIBRARY_PATH. For example, if you receive the following error: "./mode_analysis: error while loading shared libraries: libgsl.so.19: cannot open shared object file: No such file or directory", you should add the path to the gsl lib (for example, */home/user/MET/gsl-2.1/lib*) to your LD_LIBRARY_PATH. **General troubleshooting** -* For configuration files used, make certain to use empty square brackets (e.g. [ ]) to indicate no stratification is desired. Do NOT use empty double quotation marks inside square brackets (e.g. [“”]). +* For configuration files used, make certain to use empty square brackets (e.g. [ ]) to indicate no stratification is desired. Do NOT use empty double quotation marks inside square brackets (e.g. [""]). * Have you designated all the required command line arguments? diff --git a/met/docs/Users_Guide/appendixB.rst b/met/docs/Users_Guide/appendixB.rst index 4f93087fad..605712ca43 100644 --- a/met/docs/Users_Guide/appendixB.rst +++ b/met/docs/Users_Guide/appendixB.rst @@ -33,7 +33,7 @@ To specify a Lambert Grid, the syntax is lambert Nx Ny lat_ll lon_ll lon_orient D_km R_km standard_lat_1 [ standard_lat_2 ] N|S -Here, **Nx** and **Ny** are the number of points in, respectively, the **x** and **y** grid directions. These two numbers give the overall size of the grid. **lat_ll** and **lon_ll** are the latitude and longitude, in degrees, of the lower left point of the grid. North latitude and east longitude are considered positive. **lon_orient** is the orientation longitude of the grid. It’s the meridian of longitude that’s parallel to one of the vertical grid directions. **D_km** and **R_km** are the grid resolution and the radius of the Earth, both in kilometers. **standard_lat_1** and **standard_lat_2** are the standard parallels of the Lambert projection. If the two latitudes are the same, then only one needs to be given. **N|S** means to write either **N** or **S** depending on whether the Lambert projection is from the north pole or the south pole. +Here, **Nx** and **Ny** are the number of points in, respectively, the **x** and **y** grid directions. These two numbers give the overall size of the grid. **lat_ll** and **lon_ll** are the latitude and longitude, in degrees, of the lower left point of the grid. North latitude and east longitude are considered positive. **lon_orient** is the orientation longitude of the grid. It's the meridian of longitude that's parallel to one of the vertical grid directions. **D_km** and **R_km** are the grid resolution and the radius of the Earth, both in kilometers. **standard_lat_1** and **standard_lat_2** are the standard parallels of the Lambert projection. If the two latitudes are the same, then only one needs to be given. **N|S** means to write either **N** or **S** depending on whether the Lambert projection is from the north pole or the south pole. As an example of specifying a Lambert grid, suppose you have a northern hemisphere Lambert grid with 614 points in the x direction and 428 points in the y direction. The lower left corner of the grid is at latitude :math:`12.190^\circ` north and longitude :math:`133.459^\circ` west. The orientation longitude is :math:`95^\circ` west. The grid spacing is :math:`12.19058^\circ` km. The radius of the Earth is the default value used in many grib files: 6367.47 km. Both standard parallels are at :math:`25^\circ` north. To specify this grid in the config file, you would write @@ -55,7 +55,7 @@ For Plate Carrée (i.e. Lat/Lon) grids, the syntax is latlon Nx Ny lat_ll lon_ll delta_lat delta_lon -The parameters **Nx, Ny, lat_ll** and **lon_ll** are as before. **delta_lat** and **delta_lon** are the latitude and longitude increments of the grid—i.e., the change in latitude or longitude between one grid point and an adjacent grid point. +The parameters **Nx, Ny, lat_ll** and **lon_ll** are as before. **delta_lat** and **delta_lon** are the latitude and longitude increments of the grid-i.e., the change in latitude or longitude between one grid point and an adjacent grid point. For a Rotated Plate Carrée (i.e. Rotated Lat/Lon) grids, the syntax is diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 547e211d7f..082dcc208c 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -147,8 +147,13 @@ Called "H_RATE" in FHO output :numref:`table_PS_format_info_FHO` H_RATE is defined as -.. math:: \text{H_RATE } = \frac{n_{11}}{T}. +.. only:: latex + .. math:: \text{H\_RATE } = \frac{n_{11}}{T}. + +.. only:: html + + .. math:: \text{H_RATE } = \frac{n_{11}}{T}. H_RATE is equivalent to the H value computed by the NCEP verification system. H_RATE ranges from 0 to 1; a perfect forecast would have H_RATE = 1. @@ -252,7 +257,13 @@ where A more general format that uses percentages is provided by Ou (:ref:`Ou, 2016 `), -.. math:: \text{HSS(\%) } = 100 \ast \frac{(H - E)}{(T - E)} +.. only:: latex + + .. math:: \text{HSS(\%) } = 100 \ast \frac{(H - E)}{(T - E)} + +.. only:: html + + .. math:: \text{HSS(%) } = 100 \ast \frac{(H - E)}{(T - E)} where H is the number of forecasts in the correct category and E is the expected number of forecasts by chance. @@ -581,11 +592,17 @@ The anomaly correlation coefficient is equivalent to the Pearson correlation coe The centered anomaly correlation coefficient (ANOM_CORR) which includes the mean error is defined as: -.. math:: \text{ANOM_CORR } = \frac{ \bar{[(f - c) - \bar{(f - c)}][(a - c) - \bar{(a - c)}]}}{ \sqrt{ \bar{( (f - c) - \bar{(f - c)})^2} \bar{( (a - c) - \bar{(a - c)})^2}}} +.. only:: latex + + .. math:: \text{ANOM\_CORR } = \frac{ \overline{[(f - c) - \overline{(f - c)}][(a - c) - \overline{(a - c)}]}}{ \sqrt{ \overline{( (f - c) - \overline{(f - c)})^2} \overline{( (a - c) - \overline{(a - c)})^2}}} + +.. only:: html + + .. math:: \text{ANOM_CORR } = \frac{ \overline{[(f - c) - \overline{(f - c)}][(a - c) - \overline{(a - c)}]}}{ \sqrt{ \overline{( (f - c) - \overline{(f - c)})^2} \overline{( (a - c) - \overline{(a - c)})^2}}} The uncentered anomaly correlation coefficient (ANOM_CORR_UNCNTR) which does not include the mean errors is defined as: -.. math:: \text{Anomaly Correlation Raw } = \frac{ \bar{(f - c)(a - c)}}{ \sqrt{\bar{(f - c)^2} \bar{(a - c)^2}}} +.. math:: \text{Anomaly Correlation Raw } = \frac{ \overline{(f - c)(a - c)}}{ \sqrt{\overline{(f - c)^2} \overline{(a - c)^2}}} Anomaly correlation can range between -1 and 1; a value of 1 indicates perfect correlation and a value of -1 indicates perfect negative correlation. A value of 0 indicates that the forecast and observed anomalies are not correlated. @@ -594,9 +611,9 @@ Partial Sums lines (SL1L2, SAL1L2, VL1L2, VAL1L2) :numref:`table_PS_format_info_SL1L2`, :numref:`table_PS_format_info_SAL1L2`, :numref:`table_PS_format_info_VL1L2`, and :numref:`table_PS_format_info_VAL1L2` -The SL1L2, SAL1L2, VL1L2, and VAL1L2 line types are used to store data summaries (e.g. partial sums) that can later be accumulated into verification statistics. These are divided according to scalar or vector summaries (S or V). The climate anomaly values (A) can be stored in place of the actuals, which is just a re-centering of the values around the climatological average. L1 and L2 refer to the L1 and L2 norms, the distance metrics commonly referred to as the “city block” and “Euclidean” distances. The city block is the absolute value of a distance while the Euclidean distance is the square root of the squared distance. +The SL1L2, SAL1L2, VL1L2, and VAL1L2 line types are used to store data summaries (e.g. partial sums) that can later be accumulated into verification statistics. These are divided according to scalar or vector summaries (S or V). The climate anomaly values (A) can be stored in place of the actuals, which is just a re-centering of the values around the climatological average. L1 and L2 refer to the L1 and L2 norms, the distance metrics commonly referred to as the "city block" and "Euclidean" distances. The city block is the absolute value of a distance while the Euclidean distance is the square root of the squared distance. -The partial sums can be accumulated over individual cases to produce statistics for a longer period without any loss of information because these sums are *sufficient* for resulting statistics such as RMSE, bias, correlation coefficient, and MAE (:ref:`Mood et al., 1974 `). Thus, the individual errors need not be stored, all of the information relevant to calculation of statistics are contained in the sums. As an example, the sum of all data points and the sum of all squared data points (or equivalently, the sample mean and sample variance) are *jointly sufficient* for estimates of the Gaussian distribution mean and variance. +The partial sums can be accumulated over individual cases to produce statistics for a longer period without any loss of information because these sums are *sufficient* for resulting statistics such as RMSE, bias, correlation coefficient, and MAE (:ref:`Mood et al., 1974 `). Thus, the individual errors need not be stored, all of the information relevant to calculation of statistics are contained in the sums. As an example, the sum of all data points and the sum of all squared data points (or equivalently, the sample mean and sample variance) are *jointly sufficient* for estimates of the Gaussian distribution mean and variance. *Minimally sufficient* statistics are those that condense the data most, with no loss of information. Statistics based on L1 and L2 norms allow for good compression of information. Statistics based on other norms, such as order statistics, do not result in good compression of information. For this reason, statistics such as RMSE are often preferred to statistics such as the median absolute deviation. The partial sums are not sufficient for order statistics, such as the median or quartiles. @@ -607,15 +624,16 @@ Called "FBAR", "OBAR", "FOBAR", "FFBAR", and "OOBAR" in SL1L2 output :numref:`ta These statistics are simply the 1st and 2nd moments of the forecasts, observations and errors: -.. math:: \text{FBAR} = \text{Mean}(f) = \bar{f} = \frac{1}{n} \sum_{i=1}^n f_i +.. math:: + \text{FBAR} = \text{Mean}(f) = \bar{f} = \frac{1}{n} \sum_{i=1}^n f_i - \text{OBAR} = \text{Mean}(o) = \bar{o} = \frac{1}{n} \sum_{i=1}^n o_i + \text{OBAR} = \text{Mean}(o) = \bar{o} = \frac{1}{n} \sum_{i=1}^n o_i - \text{FOBAR} = \text{Mean}(fo) = \bar{fo} = \frac{1}{n} \sum_{i=1}^n f_i o_i + \text{FOBAR} = \text{Mean}(fo) = \bar{fo} = \frac{1}{n} \sum_{i=1}^n f_i o_i - \text{FFBAR} = \text{Mean}(f^2) = \bar{f}^2 = \frac{1}{n} \sum_{i=1}^n f_i^2 + \text{FFBAR} = \text{Mean}(f^2) = \bar{f}^2 = \frac{1}{n} \sum_{i=1}^n f_i^2 - \text{OOBAR} = \text{Mean}(o^2) = \bar{o}^2 = \frac{1}{n} \sum_{i=1}^n o_i^2 + \text{OOBAR} = \text{Mean}(o^2) = \bar{o}^2 = \frac{1}{n} \sum_{i=1}^n o_i^2 Some of the other statistics for continuous forecasts (e.g., RMSE) can be derived from these moments. @@ -626,15 +644,16 @@ Called "FABAR", "OABAR", "FOABAR", "FFABAR", "OOABAR" in SAL1L2 output :numref:` Computation of these statistics requires a climatological value, c. These statistics are the 1st and 2nd moments of the scalar anomalies. The moments are defined as: -.. math:: \text{FABAR} = \text{Mean}(f - c) = \bar{f - c} = \frac{1}{n} \sum_{i=1}^n (f_i - c) +.. math:: + \text{FABAR} = \text{Mean}(f - c) = \bar{f - c} = \frac{1}{n} \sum_{i=1}^n (f_i - c) - \text{OABAR} = \text{Mean}(o - c) = \bar{o - c} = \frac{1}{n} \sum_{i=1}^n (o_i - c) + \text{OABAR} = \text{Mean}(o - c) = \bar{o - c} = \frac{1}{n} \sum_{i=1}^n (o_i - c) - \text{FOABAR} = \text{Mean}[(f - c)(o - c)] = \bar{(f - c)(o - c)} = \frac{1}{n} \sum_{i=1}^n (f_i - c)(o_i - c) + \text{FOABAR} = \text{Mean}[(f - c)(o - c)] = \bar{(f - c)(o - c)} = \frac{1}{n} \sum_{i=1}^n (f_i - c)(o_i - c) - \text{FFABAR} = \text{Mean}[(f - c)^2] = \bar{(f - c)}^2 = \frac{1}{n} \sum_{i=1}^n (f_i - c)^2 + \text{FFABAR} = \text{Mean}[(f - c)^2] = \bar{(f - c)}^2 = \frac{1}{n} \sum_{i=1}^n (f_i - c)^2 - \text{OOABAR} = \text{Mean}[(o - c)^2] = \bar{(o - c)}^2 = \frac{1}{n} \sum_{i=1}^n (o_i - c)^2 + \text{OOABAR} = \text{Mean}[(o - c)^2] = \bar{(o - c)}^2 = \frac{1}{n} \sum_{i=1}^n (o_i - c)^2 Vector L1 and L2 values ~~~~~~~~~~~~~~~~~~~~~~~ @@ -643,19 +662,20 @@ Called "UFBAR", "VFBAR", "UOBAR", "VOBAR", "UVFOBAR", "UVFFBAR", "UVOOBAR" in VL These statistics are the moments for wind vector values, where **u** is the E-W wind component and **v** is the N-S wind component ( :math:`u_f` is the forecast E-W wind component; :math:`u_o` is the observed E-W wind component; :math:`v_f` is the forecast N-S wind component; and :math:`v_o` is the observed N-S wind component). The following measures are computed: -.. math:: \text{UFBAR} = \text{Mean}(u_f) = \bar{u}_f = \frac{1}{n} \sum_{i=1}^n u_{fi} +.. math:: + \text{UFBAR} = \text{Mean}(u_f) = \bar{u}_f = \frac{1}{n} \sum_{i=1}^n u_{fi} - \text{VFBAR} = \text{Mean}(v_f) = \bar{v}_f = \frac{1}{n} \sum_{i=1}^n v_{fi} + \text{VFBAR} = \text{Mean}(v_f) = \bar{v}_f = \frac{1}{n} \sum_{i=1}^n v_{fi} - \text{UOBAR} = \text{Mean}(u_o) = \bar{u}_o = \frac{1}{n} \sum_{i=1}^n u_{oi} + \text{UOBAR} = \text{Mean}(u_o) = \bar{u}_o = \frac{1}{n} \sum_{i=1}^n u_{oi} - \text{VOBAR} = \text{Mean}(v_o) = \bar{v}_o = \frac{1}{n} \sum_{i=1}^n v_{oi} + \text{VOBAR} = \text{Mean}(v_o) = \bar{v}_o = \frac{1}{n} \sum_{i=1}^n v_{oi} - \text{UVFOBAR} = \text{Mean}(u_f u_o + v_f v_o) = \frac{1}{n} \sum_{i=1}^n (u_{fi} u_{oi} + v_{fi} v_{oi}) + \text{UVFOBAR} = \text{Mean}(u_f u_o + v_f v_o) = \frac{1}{n} \sum_{i=1}^n (u_{fi} u_{oi} + v_{fi} v_{oi}) - \text{UVFFBAR} = \text{Mean}(u_f^2 + v_f^2) = \frac{1}{n} \sum_{i=1}^n (u_{fi}^2 + v_{fi}^2) + \text{UVFFBAR} = \text{Mean}(u_f^2 + v_f^2) = \frac{1}{n} \sum_{i=1}^n (u_{fi}^2 + v_{fi}^2) - \text{UVOOBAR} = \text{Mean}(u_o^2 + v_o^2) = \frac{1}{n} \sum_{i=1}^n (u_{oi}^2 + v_{oi}^2) + \text{UVOOBAR} = \text{Mean}(u_o^2 + v_o^2) = \frac{1}{n} \sum_{i=1}^n (u_{oi}^2 + v_{oi}^2) Vector anomaly L1 and L2 values ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -664,20 +684,21 @@ Called "UFABAR", "VFABAR", "UOABAR", "VOABAR", "UVFOABAR", "UVFFABAR", "UVOOABAR These statistics require climatological values for the wind vector components, :math:`u_c \text{ and } v_c`. The measures are defined below: -.. math:: \text{UFABAR} = \text{Mean}(u_f - u_c) = \frac{1}{n} \sum_{i=1}^n (u_{fi} - u_c) +.. math:: + \text{UFABAR} = \text{Mean}(u_f - u_c) = \frac{1}{n} \sum_{i=1}^n (u_{fi} - u_c) - \text{VFBAR} = \text{Mean}(v_f - v_c) = \frac{1}{n} \sum_{i=1}^n (v_{fi} - v_c) + \text{VFBAR} = \text{Mean}(v_f - v_c) = \frac{1}{n} \sum_{i=1}^n (v_{fi} - v_c) - \text{UOABAR} = \text{Mean}(u_o - u_c) = \frac{1}{n} \sum_{i=1}^n (u_{oi} - u_c) + \text{UOABAR} = \text{Mean}(u_o - u_c) = \frac{1}{n} \sum_{i=1}^n (u_{oi} - u_c) - \text{VOABAR} = \text{Mean}(v_o - v_c) = \frac{1}{n} \sum_{i=1}^n (v_{oi} - v_c) + \text{VOABAR} = \text{Mean}(v_o - v_c) = \frac{1}{n} \sum_{i=1}^n (v_{oi} - v_c) - \text{UVFOABAR} &= \text{Mean}[(u_f - u_c)(u_o - u_c) + (v_f - v_c)(v_o - v_c)] \\ - &= \frac{1}{n} \sum_{i=1}^n (u_{fi} - u_c) + (u_{oi} - u_c) + (v_{fi} - v_c)(v_{oi} - v_c) + \text{UVFOABAR} &= \text{Mean}[(u_f - u_c)(u_o - u_c) + (v_f - v_c)(v_o - v_c)] \\ + &= \frac{1}{n} \sum_{i=1}^n (u_{fi} - u_c) + (u_{oi} - u_c) + (v_{fi} - v_c)(v_{oi} - v_c) - \text{UVFFABAR} = \text{Mean}[(u_f - u_c)^2 + (v_f - v_c)^2] = \frac{1}{n} \sum_{i=1}^n ((u_{fi} - u_c)^2 + (v_{fi} - v_c)^2) + \text{UVFFABAR} = \text{Mean}[(u_f - u_c)^2 + (v_f - v_c)^2] = \frac{1}{n} \sum_{i=1}^n ((u_{fi} - u_c)^2 + (v_{fi} - v_c)^2) - \text{UVOOABAR} = \text{Mean}[(u_o - u_c)^2 + (v_o - v_c)^2] = \frac{1}{n} \sum_{i=1}^n ((u_{oi} - u_c)^2 + (v_{oi} - v_c)^2) + \text{UVOOABAR} = \text{Mean}[(u_o - u_c)^2 + (v_o - v_c)^2] = \frac{1}{n} \sum_{i=1}^n ((u_{oi} - u_c)^2 + (v_{oi} - v_c)^2) Gradient values ~~~~~~~~~~~~~~~ @@ -686,25 +707,40 @@ Called "TOTAL", "FGBAR", "OGBAR", "MGBAR", "EGBAR", "S1", "S1_OG", and "FGOG_RAT These statistics are only computed by the Grid-Stat tool and require vectors. Here :math:`\nabla` is the gradient operator, which in this applications signifies the difference between adjacent grid points in both the grid-x and grid-y directions. TOTAL is the count of grid locations used in the calculations. The remaining measures are defined below: -.. math:: \text{FGBAR} = \text{Mean}|\nabla f| = \frac{1}{n} \sum_{i=1}^n | \nabla f_i| +.. math:: + \text{FGBAR} = \text{Mean}|\nabla f| = \frac{1}{n} \sum_{i=1}^n | \nabla f_i| - \text{OGBAR} = \text{Mean}|\nabla o| = \frac{1}{n} \sum_{i=1}^n | \nabla o_i| + \text{OGBAR} = \text{Mean}|\nabla o| = \frac{1}{n} \sum_{i=1}^n | \nabla o_i| - \text{MGBAR} = \text{Max(FGBAR, OGBAR)} + \text{MGBAR} = \text{Max(FGBAR, OGBAR)} - \text{EGBAR} = \text{Mean}|\nabla f - \nabla o| = \frac{1}{n} \sum_{i=1}^n | \nabla f_i - \nabla o_i| + \text{EGBAR} = \text{Mean}|\nabla f - \nabla o| = \frac{1}{n} \sum_{i=1}^n | \nabla f_i - \nabla o_i| - \text{S1} = 100 \frac{\sum_{i=1}^n (w_i (e_g))}{\sum_{i=1}^n (w_i (G_L))}_i , + \text{S1} = 100 \frac{\sum_{i=1}^n (w_i (e_g))}{\sum_{i=1}^n (w_i (G_L))}_i , where the weights are applied at each grid location, with values assigned according to the weight option specified in the configuration file. The components of the :math:`S1` equation are as follows: -.. math:: e_g = (| \frac{\delta}{\delta x}(f - o)| + | \frac{\delta}{\delta y}(f - o)|) +.. math:: + e_g = (\vert \frac{\delta}{\delta x}(f - o)\vert + \vert \frac{\delta}{\delta y}(f - o)\vert) + + G_L = \text{max }(\vert \frac{\delta f}{\delta x}\vert,\vert \frac{\delta o}{\delta x}\vert) + \text{max }(\vert \frac{\delta f}{\delta y}\vert,\vert \frac{\delta o}{\delta y}|) + + +.. only:: latex + + .. math:: + + \text{S1\_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} + + \text{FGOG\_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} - G_L = \text{max}(| \frac{\delta f}{\delta x}|,| \frac{\delta o}{\delta x}|) + \text{max}(| \frac{\delta f}{\delta y}|,| \frac{\delta o}{\delta y}|) +.. only:: html - \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} + .. math:: + \text{S1_OG} = \frac{\text{EGBAR}}{\text{OGBAR}} + + \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} - \text{FGOG_RATIO} = \frac{\text{FGBAR}}{\text{OGBAR}} MET verification measures for probabilistic forecasts _____________________________________________________ @@ -1078,23 +1114,23 @@ The results of the distance map verification approaches that are included in the Baddeley's :math:`\Delta` Metric and Hausdorff Distance ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Called “BADDELEY” and “HAUSDORFF” in the DMAP +Called "BADDELEY" and "HAUSDORFF" in the DMAP output :numref:`table_GS_format_info_DMAP` The Baddeley's :math:`\Delta` Metric is given by .. math:: \Delta_{p,w} (A,B) = [ \frac{1}{N} \sum_{s \in D} | w(d(s,A)) - w(d(s,B))|]^{\frac{1}{P}} -where :math:`d(s,\cdot)` is the distance map for the respective event area, :math:`w(\cdot)` is an optional concave function (i.e., :math:`w( t + u) \leq w(t)+w(u))` that is strictly increasing at zero with :math:`w(t)=0` if and only if :math:`t=0`, *N* is the size of the domain, and *p* is a user chosen parameter for the :math:`L_{p}` norm. The default choice of :math:`p = 2` corresponds to a Euclidean average, :math:`p = 1` is a simple average of the difference in distance maps, and the limiting case of :math:`p= \infty` gives the maximum difference between the two distance maps and is called the Hausdorff distance, denoted as :math:`H(A,B)`, and is the metric that motivated the development of Baddeley’s :math:`\Delta` metric. A typical choice, and the only available with MET, for :math:`w(\cdot) \text{ is } w(t)= \min\{t,c\}`, where *c* is a user-chosen constant with :math:`c = \infty` meaning that :math:`w(\cdot)` is not applied. This choice of :math:`w(\cdot)` provides a cutoff for distances beyond the pre-specified amount given by *c*. +where :math:`d(s,\cdot)` is the distance map for the respective event area, :math:`w(\cdot)` is an optional concave function (i.e., :math:`w( t + u) \leq w(t)+w(u))` that is strictly increasing at zero with :math:`w(t)=0` if and only if :math:`t=0`, *N* is the size of the domain, and *p* is a user chosen parameter for the :math:`L_{p}` norm. The default choice of :math:`p = 2` corresponds to a Euclidean average, :math:`p = 1` is a simple average of the difference in distance maps, and the limiting case of :math:`p= \infty` gives the maximum difference between the two distance maps and is called the Hausdorff distance, denoted as :math:`H(A,B)`, and is the metric that motivated the development of Baddeley's :math:`\Delta` metric. A typical choice, and the only available with MET, for :math:`w(\cdot) \text{ is } w(t)= \min\{t,c\}`, where *c* is a user-chosen constant with :math:`c = \infty` meaning that :math:`w(\cdot)` is not applied. This choice of :math:`w(\cdot)` provides a cutoff for distances beyond the pre-specified amount given by *c*. -In terms of distance maps, Baddeley’s :math:`\Delta` is the :math:`L_{p}` norm of the top left panel in :numref:`grid-stat_fig4` provided :math:`c= \infty`. If :math:`0` for more details. diff --git a/met/docs/Users_Guide/appendixE.rst b/met/docs/Users_Guide/appendixE.rst index 22826ce420..a50afe1703 100644 --- a/met/docs/Users_Guide/appendixE.rst +++ b/met/docs/Users_Guide/appendixE.rst @@ -31,23 +31,23 @@ The usage statement for wwmca_regrid is wwmca_regrid -out filename config filename [ -nh filename ] [ -sh filename ] -Here, the **-out** switch tells wwmca_regrid what to name the output netCDF file. The **-config** switch gives the name of the config file that wwmca_regrid should use—like many of the MET tools, wwmca-regrid uses a configuration file to specify user-changeable parameters. The format of this file will be explained below. +Here, the **-out** switch tells wwmca_regrid what to name the output netCDF file. The **-config** switch gives the name of the config file that wwmca_regrid should use-like many of the MET tools, wwmca-regrid uses a configuration file to specify user-changeable parameters. The format of this file will be explained below. The **-nh** and **-sh** options give names of WWMCA cloud percent files that wwmca_regrid should use as input. Northern hemisphere files are specified with **-nh**, and southern hemisphere files with **-sh**. At least one of these must be given, but in many cases both need not be given. -In any regridding problem, there are two grids involved: the “From” grid, which is the grid the input data are on, and the “To” grid, which is the grid the data are to be moved onto. For wwmca_regrid, the “To” grid is specified in the config file. If this grid is entirely confined to one hemisphere, then only the WWMCA data file for that hemisphere needs to be given. It’s only when the “To” grid straddles the equator that data files for both hemispheres need to be given (though the interpolation width parameter in the config file can change this—see below). Once the “To” grid is specified in the config file, the WWMCA-Regrid tool will know which input data files it needs, and will complain if it’s not given the right ones. +In any regridding problem, there are two grids involved: the "From" grid, which is the grid the input data are on, and the "To" grid, which is the grid the data are to be moved onto. For wwmca_regrid, the "To" grid is specified in the config file. If this grid is entirely confined to one hemisphere, then only the WWMCA data file for that hemisphere needs to be given. It's only when the "To" grid straddles the equator that data files for both hemispheres need to be given (though the interpolation width parameter in the config file can change this-see below). Once the "To" grid is specified in the config file, the WWMCA-Regrid tool will know which input data files it needs, and will complain if it's not given the right ones. -Now let’s talk about the details of the config file. The config file has the same C-like syntax that all the other MET config files use. The first (and most complicated) thing to specify is the “To” grid. This is given by the **to_grid** parameter. If you are using one of the standard NCEP grids, for example grid #218, you can simply write +Now let's talk about the details of the config file. The config file has the same C-like syntax that all the other MET config files use. The first (and most complicated) thing to specify is the "To" grid. This is given by the **to_grid** parameter. If you are using one of the standard NCEP grids, for example grid #218, you can simply write .. code-block:: none To grid = "G218"; -and that will work. Failing that, you must give the parameters that specify the grid and it’s projection. Please refer the description of the grid specification strings in :ref:`appendixB`. +and that will work. Failing that, you must give the parameters that specify the grid and it's projection. Please refer the description of the grid specification strings in :ref:`appendixB`. Thankfully, the rest of the parameters in the config file are easier to specify. -The next two config file parameters have to do with specifying the interpolation scheme used. The **interp_method** parameter specifies which interpolation method is to be used. Four methods are supported: average, maximum, minimum and nearest neighbor. As an example, to specify the “average” method, one would write +The next two config file parameters have to do with specifying the interpolation scheme used. The **interp_method** parameter specifies which interpolation method is to be used. Four methods are supported: average, maximum, minimum and nearest neighbor. As an example, to specify the "average" method, one would write .. code-block:: none @@ -59,17 +59,17 @@ The other interpolation parameter is **interp_width**. This specifies the width interp_width = 5; -The value must be odd and ≥ 1. If a value of 1 is specified, then nearest neighbor interpolation will be used regardless of the value assigned to **interp_method**. +The value must be odd and :math:`\geqq` 1. If a value of 1 is specified, then nearest neighbor interpolation will be used regardless of the value assigned to **interp_method**. -The fact that an interpolation box is used has one subtle implication—the “To” grid is effectively fattened by half the width of the interpolation box. This means that even for a “To” grid that is entirely contained in one hemisphere, if it comes close to the equator, this virtual fattening may be enough to push it over the equator, and the user will then have to provide input WWMCA files for both hemispheres, even though the “To” grid doesn’t cross the equator. The WWMCA-Regrid tool should detect this situation and complain to the user if not given the correct input files. +The fact that an interpolation box is used has one subtle implication-the "To" grid is effectively fattened by half the width of the interpolation box. This means that even for a "To" grid that is entirely contained in one hemisphere, if it comes close to the equator, this virtual fattening may be enough to push it over the equator, and the user will then have to provide input WWMCA files for both hemispheres, even though the "To" grid doesn't cross the equator. The WWMCA-Regrid tool should detect this situation and complain to the user if not given the correct input files. -The next variable, **good_percent**, tells what fraction of the values in the interpolation square needs to be “good” in order for the interpolation scheme to return a “good” result. Example: +The next variable, **good_percent**, tells what fraction of the values in the interpolation square needs to be "good" in order for the interpolation scheme to return a "good" result. Example: .. code-block:: none good percent = 0; -The rest of the config file parameters have to do with how the output netCDF file represents the data. These should be self-explanatory, so I’ll just give an example: +The rest of the config file parameters have to do with how the output netCDF file represents the data. These should be self-explanatory, so I'll just give an example: .. code-block:: none diff --git a/met/docs/Users_Guide/appendixF.rst b/met/docs/Users_Guide/appendixF.rst index aaaa228318..3a4046e9ea 100644 --- a/met/docs/Users_Guide/appendixF.rst +++ b/met/docs/Users_Guide/appendixF.rst @@ -17,9 +17,9 @@ The local Python installation must also support a minimum set of required packag In addition to the **configure** option mentioned above, two variables, **MET_PYTHON_CC** and **MET_PYTHON_LD**, must also be set for the configuration process. These may either be set as environment variables or as command line options to **configure**. These constants are passed as compiler command line options when building MET to enable the compiler to find the requisite Python header files and libraries in the user's local filesystem. Fortunately, Python provides a way to set these variables properly. This frees the user from the necessity of having any expert knowledge of the compiling and linking process. Along with the **Python** executable, there should be another executable called **python3-config**, whose output can be used to set these environment variables as follows: -• On the command line, run “**python3-config --cflags**”. Set the value of **MET_PYTHON_CC** to the output of that command. +• On the command line, run "**python3-config --cflags**". Set the value of **MET_PYTHON_CC** to the output of that command. -• Again on the command line, run “**python3-config --ldflags**”. Set the value of **MET_PYTHON_LD** to the output of that command. +• Again on the command line, run "**python3-config --ldflags**". Set the value of **MET_PYTHON_LD** to the output of that command. Make sure that these are set as environment variables or that you have included them on the command line prior to running **configure**. @@ -239,7 +239,7 @@ Python Embedding for Point Observations _______________________________________ -The ASCII2NC tool supports the “-format python” option. With this option, point observations may be passed as input. An example of this is provided in :numref:`ascii2nc-pyembed`. That example uses the **read_ascii_point.py** sample script which is included with the MET code. It reads ASCII data in MET's 11-column point observation format and stores it in a Pandas dataframe to be read by the ASCII2NC tool with Python. +The ASCII2NC tool supports the "-format python" option. With this option, point observations may be passed as input. An example of this is provided in :numref:`ascii2nc-pyembed`. That example uses the **read_ascii_point.py** sample script which is included with the MET code. It reads ASCII data in MET's 11-column point observation format and stores it in a Pandas dataframe to be read by the ASCII2NC tool with Python. The **read_ascii_point.py** sample script can be found in: @@ -250,7 +250,7 @@ The **read_ascii_point.py** sample script can be found in: Python Embedding for MPR data _____________________________ -The Stat-Analysis tool supports the “-lookin python” option. With this option, matched pair (MPR) data may be passed as input. An example of this is provided in :numref:`StA-pyembed`. That example uses the **read_ascii_mpr.py** sample script which is included with the MET code. It reads MPR data and stores it in a Pandas dataframe to be read by the Stat-Analysis tool with Python. +The Stat-Analysis tool supports the "-lookin python" option. With this option, matched pair (MPR) data may be passed as input. An example of this is provided in :numref:`StA-pyembed`. That example uses the **read_ascii_mpr.py** sample script which is included with the MET code. It reads MPR data and stores it in a Pandas dataframe to be read by the Stat-Analysis tool with Python. The **read_ascii_mpr.py** sample script can be found in: diff --git a/met/docs/Users_Guide/appendixG.rst b/met/docs/Users_Guide/appendixG.rst index 12316fe477..8c46641ced 100644 --- a/met/docs/Users_Guide/appendixG.rst +++ b/met/docs/Users_Guide/appendixG.rst @@ -73,26 +73,42 @@ _________________________ FBAR and OBAR are the average values of the forecast and observed wind speed. -.. math:: \text{FBAR} = \frac{1}{N} \sum_i s_{fi} +.. math:: + + \text{FBAR} = \frac{1}{N} \sum_i s_{fi} - \text{OBAR} = {1 \over N} \sum_i s_{oi} + \text{OBAR} = {1 \over N} \sum_i s_{oi} _________________________ FS_RMS and OS_RMS are the root-mean-square values of the forecast and observed wind speeds. -.. math:: \text{FS_RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} +.. only:: latex + + .. math:: + + \text{FS\_RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} + + \text{OS\_RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} + +.. only:: html + + .. math:: + + \text{FS_RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} - \text{OS_RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} + \text{OS_RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} ___________________________ MSVE and RMSVE are, respectively, the mean squared, and root mean squared, lengths of the vector difference between the forecast and observed wind vectors. -.. math:: \text{MSVE} = \frac{1}{N} \sum_i | \mathbf{F}_i - \mathbf{O}_i|^2 +.. math:: - \text{RMSVE} = \sqrt{MSVE} + \text{MSVE} = \frac{1}{N} \sum_i | \mathbf{F}_i - \mathbf{O}_i|^2 + + \text{RMSVE} = \sqrt{MSVE} ____________________________ @@ -116,48 +132,104 @@ ________________________ FBAR_SPEED and OBAR_SPEED are the lengths of the average forecast and observed wind vectors. Note that this is *not* the same as the average forecast and observed wind speeds (*ie.,* the length of an average vector :math:`\neq` the average length of the vector). -.. math:: \text{FBAR_SPEED } = | \mathbf{F}_a | - - \text{OBAR_SPEED } = | \mathbf{O}_a | +.. only:: latex + + .. math:: + + \text{FBAR\_SPEED } = | \mathbf{F}_a | + + \text{OBAR\_SPEED } = | \mathbf{O}_a | + +.. only:: html + + .. math:: + + \text{FBAR_SPEED } = | \mathbf{F}_a | + + \text{OBAR_SPEED } = | \mathbf{O}_a | + ________________________ VDIFF_SPEED is the length (*ie. speed*) of the vector difference between the average forecast and average observed wind vectors. -.. math:: \text{VDIFF_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | +.. only:: latex + + .. math:: \text{VDIFF\_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | + +.. only:: html + + .. math:: \text{VDIFF_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | + +.. only:: latex + + Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or, equivalently, that :math:`\vert \text{SPEED\_ERR } \vert \leq \text{VDIFF\_SPEED. }` + +.. only:: html -Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or , equivalently, that :math:`| \text{SPEED_ERR} | \leq \text{VDIFF_SPEED}`. + Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or, equivalently, that :math:`\vert \text{SPEED_ERR } \vert \leq \text{VDIFF_SPEED. }` _________________________ VDIFF_DIR is the direction of the vector difference of the average forecast and average observed wind vectors. Note that this is {\it not} the same as the difference in direction of the average forecast and average observed wind vectors. This latter quantity would be FDIR :math:`-` ODIR. -.. math:: \text{VDIFF_DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) +.. only:: latex + + .. math:: \text{VDIFF\_DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) + +.. only:: html + + .. math:: \text{VDIFF_DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) _________________________ SPEED_ERR is the difference in the lengths (speeds) of the average forecast and average observed wind vectors. (See the discussion of VDIFF_SPEED above.) -.. math:: \text{SPEED_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR_SPEED } - \text{ OBAR_SPEED} +.. only:: latex + + .. math:: \text{SPEED\_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR\_SPEED } - \text{ OBAR\_SPEED } + +.. only:: html + + .. math:: \text{SPEED_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR_SPEED } - \text{ OBAR_SPEED } + ___________________________ SPEED_ABSERR is the absolute value of SPEED_ERR. Note that we have SPEED_ABSERR :math:`\leq` VDIFF_SPEED (see the discussion of VDIFF_SPEED above). -.. math:: \text{SPEED_ABSERR } = | \text{SPEED_ERR} | +.. only:: latex + + .. math:: \text{SPEED\_ABSERR } = \vert \text{SPEED\_ERR } \vert + +.. only:: html + + .. math:: \text{SPEED_ABSERR } = \vert \text{SPEED_ERR } \vert __________________________ DIR_ERR is the signed angle between the directions of the average forecast and average observed wind vectors. Positive if the forecast vector is counterclockwise from the observed vector. -.. math:: \text{DIR_ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) +.. only:: latex + + .. math:: \text{DIR\_ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) + +.. only:: html + + .. math:: \text{DIR_ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) __________________________ DIR_ABSERR is the absolute value of DIR_ERR. In other words, it's an unsigned angle rather than a signed angle. -.. math:: \text{DIR_ABSERR } = | \text{DIR_ERR}| +.. only:: latex + + .. math:: \text{DIR\_ABSERR } = \vert \text{DIR\_ERR } \vert + +.. only:: html + + .. math:: \text{DIR_ABSERR } = \vert \text{DIR_ERR } \vert diff --git a/met/docs/Users_Guide/data_io.rst b/met/docs/Users_Guide/data_io.rst index 3dd4552ab9..8b6d41ea95 100644 --- a/met/docs/Users_Guide/data_io.rst +++ b/met/docs/Users_Guide/data_io.rst @@ -92,7 +92,7 @@ The following is a summary of the input and output formats for each of the tools #. **Pcp-Combine Tool** - * **Input**: Two or more gridded model or observation files (in GRIB format for “sum” command, or any gridded file for “add”, “subtract”, and “derive” commands) containing data (often accumulated precipitation) to be combined. + * **Input**: Two or more gridded model or observation files (in GRIB format for "sum" command, or any gridded file for "add", "subtract", and "derive" commands) containing data (often accumulated precipitation) to be combined. * **Output**: One NetCDF file containing output for the requested operation(s). @@ -142,7 +142,7 @@ The following is a summary of the input and output formats for each of the tools * **Input**: One gridded model file, one gridded observation file, and one configuration file. - * **Output**: One STAT file containing the “ISC” line type, one ASCII file containing intensity-scale information and statistics, one NetCDF file containing information about the wavelet decomposition of forecast and observed fields and their differences, and one PostScript file containing plots and summaries of the intensity-scale verification. + * **Output**: One STAT file containing the "ISC" line type, one ASCII file containing intensity-scale information and statistics, one NetCDF file containing information about the wavelet decomposition of forecast and observed fields and their differences, and one PostScript file containing plots and summaries of the intensity-scale verification. #. **GSID2MPR Tool** @@ -160,7 +160,7 @@ The following is a summary of the input and output formats for each of the tools * **Input**: One or more STAT files output from the Point-Stat, Grid-Stat, Ensemble Stat, Wavelet-Stat, or TC-Gen tools and, optionally, one configuration file containing specifications for the analysis job(s) to be run on the STAT data. - * **Output**: ASCII output of the analysis jobs is printed to the screen unless redirected to a file using the “-out” option or redirected to a STAT output file using the “-out_stat” option. + * **Output**: ASCII output of the analysis jobs is printed to the screen unless redirected to a file using the "-out" option or redirected to a STAT output file using the "-out_stat" option. #. **Series-Analysis Tool** @@ -184,7 +184,7 @@ The following is a summary of the input and output formats for each of the tools * **Input**: One or more MODE object statistics files from the MODE tool and, optionally, one configuration file containing specification for the analysis job(s) to be run on the object data. - * **Output**: ASCII output of the analysis jobs will be printed to the screen unless redirected to a file using the “-out” option. + * **Output**: ASCII output of the analysis jobs will be printed to the screen unless redirected to a file using the "-out" option. #. **MODE-TD Tool** @@ -208,7 +208,7 @@ The following is a summary of the input and output formats for each of the tools * **Input**: One or more TCSTAT output files output from the TC-Pairs tool and, optionally, one configuration file containing specifications for the analysis job(s) to be run on the TCSTAT data. - * **Output**: ASCII output of the analysis jobs will be printed to the screen unless redirected to a file using the “-out” option. + * **Output**: ASCII output of the analysis jobs will be printed to the screen unless redirected to a file using the "-out" option. #. **TC-Gen Tool** diff --git a/met/docs/Users_Guide/ensemble-stat.rst b/met/docs/Users_Guide/ensemble-stat.rst index cfe920c0e6..d4763fe32f 100644 --- a/met/docs/Users_Guide/ensemble-stat.rst +++ b/met/docs/Users_Guide/ensemble-stat.rst @@ -106,9 +106,9 @@ Optional arguments for ensemble_stat 10. The **-log** file outputs log messages to the specified file. -11. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. +11. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. -12. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +12. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the ensemble_stat calling sequence is shown below: diff --git a/met/docs/Users_Guide/figure/plotting-Gilbert-skill-score.png b/met/docs/Users_Guide/figure/plotting-Gilbert-skill-score.png new file mode 100644 index 0000000000000000000000000000000000000000..0b8b71056a20c8becf513232088b4f340379a011 GIT binary patch literal 15350 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 r{cbAv%bI$n> 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 literal 0 HcmV?d00001 diff --git a/met/docs/Users_Guide/figure/plotting_Gilbert_skill_score.gif b/met/docs/Users_Guide/figure/plotting_Gilbert_skill_score.gif deleted file mode 100644 index 7840e1e6eac958e9d1c9034601ac7f10b25f7683..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12846 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

&FgfunH3lnijAiY-RmJnv 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 diff --git a/met/docs/Users_Guide/grid-diag.rst b/met/docs/Users_Guide/grid-diag.rst index fb6c14f58c..22200ad0e2 100644 --- a/met/docs/Users_Guide/grid-diag.rst +++ b/met/docs/Users_Guide/grid-diag.rst @@ -48,9 +48,9 @@ Optional arguments for grid_diag 4. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -5. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +5. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -6. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +6. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. grid_diag configuration file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/met/docs/Users_Guide/grid-stat.rst b/met/docs/Users_Guide/grid-stat.rst index 123954bc47..f626f77ef8 100644 --- a/met/docs/Users_Guide/grid-stat.rst +++ b/met/docs/Users_Guide/grid-stat.rst @@ -31,7 +31,7 @@ Measures for continuous variables For continuous variables, many verification measures are based on the forecast error (i.e., f - o). However, it also is of interest to investigate characteristics of the forecasts, and the observations, as well as their relationship. These concepts are consistent with the general framework for verification outlined by :ref:`Murphy and Winkler (1987) `. The statistics produced by MET for continuous forecasts represent this philosophy of verification, which focuses on a variety of aspects of performance rather than a single measure. See :numref:`Appendix C, Section %s ` for specific information. -A user may wish to eliminate certain values of the forecasts from the calculation of statistics, a process referred to here as “conditional verification”. For example, a user may eliminate all temperatures above freezing and then calculate the error statistics only for those forecasts of below freezing temperatures. Another common example involves verification of wind forecasts. Since wind direction is indeterminate at very low wind speeds, the user may wish to set a minimum wind speed threshold prior to calculating error statistics for wind direction. The user may specify these thresholds in the configuration file to specify the conditional verification. Thresholds can be specified using the usual Fortran conventions (<, <=, ==, !-, >=, or >) followed by a numeric value. The threshold type may also be specified using two letter abbreviations (lt, le, eq, ne, ge, gt). Further, more complex thresholds can be achieved by defining multiple thresholds and using && or || to string together event definition logic. The forecast and observation threshold can be used together according to user preference by specifying one of: UNION, INTERSECTION, or SYMDIFF (symmetric difference). +A user may wish to eliminate certain values of the forecasts from the calculation of statistics, a process referred to here as "conditional verification". For example, a user may eliminate all temperatures above freezing and then calculate the error statistics only for those forecasts of below freezing temperatures. Another common example involves verification of wind forecasts. Since wind direction is indeterminate at very low wind speeds, the user may wish to set a minimum wind speed threshold prior to calculating error statistics for wind direction. The user may specify these thresholds in the configuration file to specify the conditional verification. Thresholds can be specified using the usual Fortran conventions (<, <=, ==, !-, >=, or >) followed by a numeric value. The threshold type may also be specified using two letter abbreviations (lt, le, eq, ne, ge, gt). Further, more complex thresholds can be achieved by defining multiple thresholds and using && or || to string together event definition logic. The forecast and observation threshold can be used together according to user preference by specifying one of: UNION, INTERSECTION, or SYMDIFF (symmetric difference). Measures for probabilistic forecasts and dichotomous outcomes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ When computing continuous statistics on a regular large scale or global latitude Neighborhood methods ~~~~~~~~~~~~~~~~~~~~ -MET also incorporates several neighborhood methods to give credit to forecasts that are close to the observations, but not necessarily exactly matched up in space. Also referred to as “fuzzy” verification methods, these methods do not just compare a single forecast at each grid point to a single observation at each grid point; they compare the forecasts and observations in a neighborhood surrounding the point of interest. With the neighborhood method, the user chooses a distance within which the forecast event can fall from the observed event and still be considered a hit. In MET this is implemented by defining a square search window around each grid point. Within the search window, the number of observed events is compared to the number of forecast events. In this way, credit is given to forecasts that are close to the observations without requiring a strict match between forecasted events and observed events at any particular grid point. The neighborhood methods allow the user to see how forecast skill varies with neighborhood size and can help determine the smallest neighborhood size that can be used to give sufficiently accurate forecasts. +MET also incorporates several neighborhood methods to give credit to forecasts that are close to the observations, but not necessarily exactly matched up in space. Also referred to as "fuzzy" verification methods, these methods do not just compare a single forecast at each grid point to a single observation at each grid point; they compare the forecasts and observations in a neighborhood surrounding the point of interest. With the neighborhood method, the user chooses a distance within which the forecast event can fall from the observed event and still be considered a hit. In MET this is implemented by defining a square search window around each grid point. Within the search window, the number of observed events is compared to the number of forecast events. In this way, credit is given to forecasts that are close to the observations without requiring a strict match between forecasted events and observed events at any particular grid point. The neighborhood methods allow the user to see how forecast skill varies with neighborhood size and can help determine the smallest neighborhood size that can be used to give sufficiently accurate forecasts. There are several ways to present the results of the neighborhood approaches, such as the Fractions Skill Score (FSS) or the Fractions Brier Score (FBS). These scores are presented in :numref:`Appendix C, Section %s `. One can also simply up-scale the information on the forecast verification grid by smoothing or resampling within a specified neighborhood around each grid point and recalculate the traditional verification metrics on the coarser grid. The MET output includes traditional contingency table statistics for each threshold and neighborhood window size. @@ -90,7 +90,7 @@ Differences are computed in both of the horizontal grid directions and is not a Distance Maps ~~~~~~~~~~~~~ -The following methods can all be computed efficiently by utilizing fast algorithms developed for calculating distance maps. A distance map results from calculating the shortest distance from every grid point, :math:`s=(x,y)`, in the domain, :math:`D`, to the nearest one-valued grid point. In each of the following, it is understood that they are calculated between event areas :math:`A`, from one field and observation event areas :math:`B` from another. If the measure is applied to a feature within a field, then the distance map is still calculated over the entire original domain. Some of the distance map statistics are computed over the entire distance map, while others use only parts of it. +The following methods can all be computed efficiently by utilizing fast algorithms developed for calculating distance maps. A distance map results from calculating the shortest distance from every grid point, **s=(x,y)**, in the domain, **D**, to the nearest one-valued grid point. In each of the following, it is understood that they are calculated between event areas **A**, from one field and observation event areas **B** from another. If the measure is applied to a feature within a field, then the distance map is still calculated over the entire original domain. Some of the distance map statistics are computed over the entire distance map, while others use only parts of it. Because these methods rely on the distance map, it is helpful to understand precisely what such maps do. :numref:`grid-stat_fig1` demonstrates the path of the shortest distance to the nearest event point in the event area A marked by the gray rectangle in the diagram. Note that the arrows all point to a grid point on the boundary of the event area A as it would be a longer distance to any point in its interior. :numref:`grid-stat_fig2` demonstrates the shortest distances from every grid point inside a second event area marked by the gray circle labeled B to the same event area A as in :numref:`grid-stat_fig1`. Note that all of the distances are to points on a small subsection (indicated by the yellow stretch) of the subset A. @@ -163,9 +163,9 @@ Optional arguments for grid_stat 5. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -6. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +6. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -7. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +7. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the grid_stat calling sequence is listed below: @@ -251,7 +251,7 @@ The **field** entry is set to **BOTH, FCST, OBS**, or **NONE** to indicate the f The **vld_thresh** entry contains a number between 0 and 1. When performing neighborhood verification over some neighborhood of points the ratio of the number of valid data points to the total number of points in the neighborhood is computed. If that ratio is greater than this threshold, that value is included in the neighborhood verification. Setting this threshold to 1, which is the default, requires that the entire neighborhood must contain valid data. This variable will typically come into play only along the boundaries of the verification region chosen. -The **cov_thresh** entry contains a comma separated list of thresholds to be applied to the neighborhood coverage field. The coverage is the proportion of forecast points in the neighborhood that exceed the forecast threshold. For example, if 10 of the 25 forecast grid points contain values larger than a threshold of 2, then the coverage is 10/25 = 0.4. If the coverage threshold is set to 0.5, then this neighborhood is considered to be a “No” forecast. +The **cov_thresh** entry contains a comma separated list of thresholds to be applied to the neighborhood coverage field. The coverage is the proportion of forecast points in the neighborhood that exceed the forecast threshold. For example, if 10 of the 25 forecast grid points contain values larger than a threshold of 2, then the coverage is 10/25 = 0.4. If the coverage threshold is set to 0.5, then this neighborhood is considered to be a "No" forecast. ___________________ @@ -291,7 +291,7 @@ ____________________ zhu_weight = 0.5; } -The **distance_map** entry is a dictionary containing options related to the distance map statistics in the **DMAP** output line type. The **baddeley_p** entry is an integer specifying the exponent used in the Lp-norm when computing the Baddeley :math:`\Delta` metric. The **baddeley_max_dist** entry is a floating point number specifying the maximum allowable distance for each distance map. Any distances larger than this number will be reset to this constant. A value of **NA** indicates that no maximum distance value should be used. The **fom_alpha** entry is a floating point number specifying the scaling constant to be used when computing Pratt's Figure of Merit. The **zhu_weight** specifies a value between 0 and 1 to define the importance of the RMSE of the binary fields (i.e. amount of overlap) versus the mean-error distance (MED). The default value of 0.5 gives equal weighting. This configuration option may be set separately in each **obs.field** entry. +The **distance_map** entry is a dictionary containing options related to the distance map statistics in the **DMAP** output line type. The **baddeley_p** entry is an integer specifying the exponent used in the Lp-norm when computing the Baddeley Delta metric. The **baddeley_max_dist** entry is a floating point number specifying the maximum allowable distance for each distance map. Any distances larger than this number will be reset to this constant. A value of **NA** indicates that no maximum distance value should be used. The **fom_alpha** entry is a floating point number specifying the scaling constant to be used when computing Pratt's Figure of Merit. The **zhu_weight** specifies a value between 0 and 1 to define the importance of the RMSE of the binary fields (i.e. amount of overlap) versus the mean-error distance (MED). The default value of 0.5 gives equal weighting. This configuration option may be set separately in each **obs.field** entry. _____________________ @@ -755,7 +755,7 @@ The format of the STAT and ASCII output of the Grid-Stat tool are the same as th - Frequency Bias * - 29 - BADDELEY - - Baddeley's :math:`\Delta` Metric + - Baddeley's Delta Metric * - 30 - HAUSDORFF - Hausdorff Distance diff --git a/met/docs/Users_Guide/index.rst b/met/docs/Users_Guide/index.rst index 6f62391dc6..213fcae61d 100644 --- a/met/docs/Users_Guide/index.rst +++ b/met/docs/Users_Guide/index.rst @@ -79,11 +79,12 @@ The National Center for Atmospheric Research (NCAR) is sponsored by NSF. The DTC appendixF appendixG +.. only:: html -Indices and tables -================== + Indices and tables + ================== -* :ref:`genindex` -* :ref:`search` + * :ref:`genindex` + * :ref:`search` diff --git a/met/docs/Users_Guide/masking.rst b/met/docs/Users_Guide/masking.rst index 08ef85727c..db695f97f1 100644 --- a/met/docs/Users_Guide/masking.rst +++ b/met/docs/Users_Guide/masking.rst @@ -3,7 +3,7 @@ Regional Verification using Spatial Masking =========================================== -Verification over a particular region or area of interest may be performed using “masking”. Defining a masking region is simply selecting the desired set of grid points to be used. The Gen-Vx-Mask tool automates this process and replaces the Gen-Poly-Mask and Gen-Circle-Mask tools from previous releases. It may be run to create a bitmap verification masking region to be used by many of the statistical tools. This tool enables the user to generate a masking region once for a domain and apply it to many cases. It has been enhanced to support additional types of masking region definition (e.g. tropical-cyclone track over water only). An iterative approach may be used to define complex areas by combining multiple masking regions together. +Verification over a particular region or area of interest may be performed using "masking". Defining a masking region is simply selecting the desired set of grid points to be used. The Gen-Vx-Mask tool automates this process and replaces the Gen-Poly-Mask and Gen-Circle-Mask tools from previous releases. It may be run to create a bitmap verification masking region to be used by many of the statistical tools. This tool enables the user to generate a masking region once for a domain and apply it to many cases. It has been enhanced to support additional types of masking region definition (e.g. tropical-cyclone track over water only). An iterative approach may be used to define complex areas by combining multiple masking regions together. Gen-Vx-Mask tool ________________ @@ -45,15 +45,15 @@ Required arguments for gen_vx_mask 2. The **mask_file** argument defines the masking information, see below. -• For “poly”, “box”, “circle”, and “track” masking, specify an ASCII Lat/Lon file. +• For "poly", "box", "circle", and "track" masking, specify an ASCII Lat/Lon file. -• For “grid” and “data” masking, specify a gridded data file. +• For "grid" and "data" masking, specify a gridded data file. -• For “solar_alt” and “solar_azi” masking, specify a gridded data file or a time string in YYYYMMDD[_HH[MMSS]] format. +• For "solar_alt" and "solar_azi" masking, specify a gridded data file or a time string in YYYYMMDD[_HH[MMSS]] format. -• For “lat” and “lon” masking, no “mask_file” needed, simply repeat the path for “input_file”. +• For "lat" and "lon" masking, no "mask_file" needed, simply repeat the path for "input_file". -• For “shape” masking, specify an ESRI shapefile (.shp). +• For "shape" masking, specify an ESRI shapefile (.shp). 3. The **out_file** argument is the output NetCDF mask file to be written. @@ -62,25 +62,25 @@ Required arguments for gen_vx_mask Optional arguments for gen_vx_mask ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -5. The **-input_field string** option can be used to read existing mask data from “input_file”. +5. The **-input_field string** option can be used to read existing mask data from "input_file". -6. The **-mask_field string** option can be used to define the field from “mask_file” to be used for “data” masking. +6. The **-mask_field string** option can be used to define the field from "mask_file" to be used for "data" masking. -7. The **-complement** option can be used to compute the complement of the area defined by “mask_file”. +7. The **-complement** option can be used to compute the complement of the area defined by "mask_file". -8. The **-union | -intersection | -symdiff** option can be used to specify how to combine the masks from “input_file” and “mask_file”. +8. The **-union | -intersection | -symdiff** option can be used to specify how to combine the masks from "input_file" and "mask_file". 9. The **-thresh string** option can be used to define the threshold to be applied. -• For “circle” and “track” masking, threshold the distance (km). +• For "circle" and "track" masking, threshold the distance (km). -• For “data” masking, threshold the values of “mask_field”. +• For "data" masking, threshold the values of "mask_field". -• For “solar_alt” and “solar_azi” masking, threshold the computed solar values. +• For "solar_alt" and "solar_azi" masking, threshold the computed solar values. -• For “lat” and “lon” masking, threshold the latitude and longitude values. +• For "lat" and "lon" masking, threshold the latitude and longitude values. -10. The **-height n** and **-width n** options set the size in grid units for “box”masking. +10. The **-height n** and **-width n** options set the size in grid units for "box"masking. 11. The **-shapeno n** option is only used for shapefile masking. (See description of shapefile masking below). @@ -92,7 +92,7 @@ Optional arguments for gen_vx_mask 15. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. -16. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +16. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. The Gen-Vx-Mask tool supports the following types of masking region definition selected using the **-type** command line option: @@ -112,7 +112,7 @@ The Gen-Vx-Mask tool supports the following types of masking region definition s 8. Latitude (**lat**) and longitude (**lon**) masking computes the latitude and longitude value at each grid point. This logic only requires the definition of the grid, specified by the **input_file**. Technically, the **mask_file** is not needed, but a value must be specified for the command line to parse correctly. Users are advised to simply repeat the **input_file** setting twice. If the **-thresh** command line option is not used, the raw latitude or longitude values for each grid point will be written to the output. This option is useful when defining latitude or longitude bands over which to compute statistics. -9. Shapefile (**shape**) masking uses a closed polygon taken from an ESRI shapefile to define the masking region. Gen-Vx-Mask reads the shapefile with the ".shp" suffix and extracts the latitude and longitudes of the vertices. The other types of shapefiles (index file, suffix “.shx”, and dBASE file, suffix “.dbf”) are not currently used. The shapefile must consist of closed polygons rather than polylines, points, or any of the other data types that shapefiles support. Shapefiles usually contain more than one polygon, and the **-shape n** command line option enables the user to select one polygon from the shapefile. The integer **n** tells which shape number to use from the shapefile. Note that this value is zero-based, so that the first polygon in the shapefile is polygon number 0, the second polygon in the shapefile is polygon number 1, etc. For the user's convenience, some utilities that perform human-readable screen dumps of shapefile contents are provided. The gis_dump_shp, gis_dump_shx and gis_dump_dbf tools enable the user to examine the contents of her shapefiles. As an example, if the user knows the name of the particular polygon but not the number of the polygon in the shapefile, the user can use the gis_dump_dbf utility to examine the names of the polygons in the shapefile. The information written to the screen will display the corresponding polygon number. +9. Shapefile (**shape**) masking uses a closed polygon taken from an ESRI shapefile to define the masking region. Gen-Vx-Mask reads the shapefile with the ".shp" suffix and extracts the latitude and longitudes of the vertices. The other types of shapefiles (index file, suffix ".shx", and dBASE file, suffix ".dbf") are not currently used. The shapefile must consist of closed polygons rather than polylines, points, or any of the other data types that shapefiles support. Shapefiles usually contain more than one polygon, and the **-shape n** command line option enables the user to select one polygon from the shapefile. The integer **n** tells which shape number to use from the shapefile. Note that this value is zero-based, so that the first polygon in the shapefile is polygon number 0, the second polygon in the shapefile is polygon number 1, etc. For the user's convenience, some utilities that perform human-readable screen dumps of shapefile contents are provided. The gis_dump_shp, gis_dump_shx and gis_dump_dbf tools enable the user to examine the contents of her shapefiles. As an example, if the user knows the name of the particular polygon but not the number of the polygon in the shapefile, the user can use the gis_dump_dbf utility to examine the names of the polygons in the shapefile. The information written to the screen will display the corresponding polygon number. The polyline, box, circle, and track masking methods all read an ASCII file containing Lat/Lon locations. Those files must contain a string, which defines the name of the masking region, followed by a series of whitespace-separated latitude (degrees north) and longitude (degree east) values. @@ -150,7 +150,7 @@ This three step process enables the Gen-Vx-Mask tool to be run iteratively on it • Rerun the Gen-Vx-Mask tool passing in the output of the first call and applying polyline masking to define the geographic area of interest. - – Use the **-intersection** option to only select grid points whose value is non-zero in both the input field and the current mask. + - Use the **-intersection** option to only select grid points whose value is non-zero in both the input field and the current mask. An example of the gen_vx_mask calling sequence is shown below: @@ -164,4 +164,4 @@ In this example, the Gen-Vx-Mask tool will read the ASCII Lat/Lon file named **C Feature-Relative Methods ________________________ -This section contains a description of several methods that may be used to perform feature-relative (or event -based) evaluation. The methodology pertains to examining the environment surrounding a particular feature or event such as a tropical, extra-tropical cyclone, convective cell, snow-band, etc. Several approaches are available for these types of investigations including applying masking described above (e.g. circle or box) or using the “FORCE” interpolation method in the regrid configuration option (see :numref:`config_options`). These methods generally require additional scripting, including potentially storm-track identification, outside of MET to be paired with the features of the MET tools. METplus may be used to execute this type of analysis. Please refer to the `METplus User's Guide `__. +This section contains a description of several methods that may be used to perform feature-relative (or event -based) evaluation. The methodology pertains to examining the environment surrounding a particular feature or event such as a tropical, extra-tropical cyclone, convective cell, snow-band, etc. Several approaches are available for these types of investigations including applying masking described above (e.g. circle or box) or using the "FORCE" interpolation method in the regrid configuration option (see :numref:`config_options`). These methods generally require additional scripting, including potentially storm-track identification, outside of MET to be paired with the features of the MET tools. METplus may be used to execute this type of analysis. Please refer to the `METplus User's Guide `__. diff --git a/met/docs/Users_Guide/mode-analysis.rst b/met/docs/Users_Guide/mode-analysis.rst index 53852534e3..c641f8b8e6 100644 --- a/met/docs/Users_Guide/mode-analysis.rst +++ b/met/docs/Users_Guide/mode-analysis.rst @@ -13,9 +13,9 @@ Users may wish to summarize multiple ASCII files produced by MODE across many ca Scientific and statistical aspects __________________________________ -The MODE-Analysis tool operates in two modes, called “summary” and “bycase”. In summary mode, the user specifies on the command line the MODE output columns of interest as well as filtering criteria that determine which input lines should be used. For example, a user may be interested in forecast object areas, but only if the object was matched, and only if the object centroid is inside a particular region. The summary statistics generated for each specified column of data are the minimum, maximum, mean, standard deviation, and the 10th, 25th, 50th, 75th and 90th percentiles. In addition, the user may specify a “dump'” file: the individual MODE lines used to produce the statistics will be written to this file. This option provides the user with a filtering capability. The dump file will consist only of lines that match the specified criteria. +The MODE-Analysis tool operates in two modes, called "summary" and "bycase". In summary mode, the user specifies on the command line the MODE output columns of interest as well as filtering criteria that determine which input lines should be used. For example, a user may be interested in forecast object areas, but only if the object was matched, and only if the object centroid is inside a particular region. The summary statistics generated for each specified column of data are the minimum, maximum, mean, standard deviation, and the 10th, 25th, 50th, 75th and 90th percentiles. In addition, the user may specify a "dump'" file: the individual MODE lines used to produce the statistics will be written to this file. This option provides the user with a filtering capability. The dump file will consist only of lines that match the specified criteria. -The other option for operating the analysis tool is “bycase”. Given initial and final values for forecast lead time, the tool will output, for each valid time in the interval, the matched area, unmatched area, and the number of forecast and observed objects that were matched or unmatched. For the areas, the user can specify forecast or observed objects, and also simple or cluster objects. A dump file may also be specified in this mode. +The other option for operating the analysis tool is "bycase". Given initial and final values for forecast lead time, the tool will output, for each valid time in the interval, the matched area, unmatched area, and the number of forecast and observed objects that were matched or unmatched. For the areas, the user can specify forecast or observed objects, and also simple or cluster objects. A dump file may also be specified in this mode. Practical information _____________________ @@ -591,7 +591,7 @@ mode_analysis configuration file To use the MODE-Analysis tool, the user must un-comment the options in the configuration file to apply them and comment out unwanted options. The options in the configuration file for the MODE-Analysis tools are the same as the MODE command line options described in :numref:`mode_analysis-usage`. -The parameters that are set in the configuration file either add to or override parameters that are set on the command line. For the “set string” and “set integer type” options enclosed in brackets, the values specified in the configuration file are added to any values set on the command line. For the “toggle” and “min/max type” options, the values specified in the configuration file override those set on the command line. +The parameters that are set in the configuration file either add to or override parameters that are set on the command line. For the "set string" and "set integer type" options enclosed in brackets, the values specified in the configuration file are added to any values set on the command line. For the "toggle" and "min/max type" options, the values specified in the configuration file override those set on the command line. mode_analysis output ~~~~~~~~~~~~~~~~~~~~ diff --git a/met/docs/Users_Guide/mode-td.rst b/met/docs/Users_Guide/mode-td.rst index 75f45b2054..b646410835 100644 --- a/met/docs/Users_Guide/mode-td.rst +++ b/met/docs/Users_Guide/mode-td.rst @@ -42,11 +42,11 @@ Convolution As in MODE, MTD applies a convolution filter to the raw data as a preliminary step in resolving the field into objects. The convolution step in MTD differs in several respects from that performed in MODE, however. -First, MTD typically reads in several planes of data for each data field—one plane for each time step, and there is really no limit to the number of time steps. So MTD is convolving much more data than it would be if it were simply analyzing a 2D data field. Secondly, MTD convolves in time as well as space, which again increases the amount of data needing to be processed. The net effect of all this is to greatly increase the time needed to perform the convolution step. +First, MTD typically reads in several planes of data for each data field-one plane for each time step, and there is really no limit to the number of time steps. So MTD is convolving much more data than it would be if it were simply analyzing a 2D data field. Secondly, MTD convolves in time as well as space, which again increases the amount of data needing to be processed. The net effect of all this is to greatly increase the time needed to perform the convolution step. Because of this, the developers decided to make several changes in the way convolution was performed in MTD. Most of the differences come from the need to make the convolution step as fast as possible. -The most basic change is to use a square convolution filter rather than the circular one that MODE uses. The overall “size” of the filter is still determined by one parameter (denoted :math:`R`, as in MODE), but this should not be thought of as a radius. Instead, the size of the square is :math:`(2 R + 1) \times (2 R + 1)`, as shown in :numref:`mtd-two_r_plus_one`. +The most basic change is to use a square convolution filter rather than the circular one that MODE uses. The overall "size" of the filter is still determined by one parameter (denoted :math:`R`, as in MODE), but this should not be thought of as a radius. Instead, the size of the square is :math:`(2 R + 1) \times (2 R + 1)`, as shown in :numref:`mtd-two_r_plus_one`. .. _mtd-two_r_plus_one: @@ -73,7 +73,7 @@ The vector **velocity** :math:`(v_x, v_y)` is obtained by fitting a line to a 3D The spatial orientation of an object (what traditional MODE calls the **axis angle** of an object) is gotten by fitting a plane to an object. As with the case of velocity, our optimization criterion is that the sum of the squares of the spatial distances from each point of the object to the plane be minimized. -:numref:`mtd-axis_3d` gives some idea of the reason for fitting a plane, rather than a line, as MODE does. On the left in the figure, we see an object (in blue shaped like an “A”) at several time steps moving through the grid. For simplicity, the object is not rotating as it moves (though of course real objects can certainly do this). At each time step, the 2D MODE spatial axis of the object is indicated by the red line. In the center of the figure, we see the same thing, just with more time steps. And on the right, even more time steps. We see that the axis lines at each time step sweep out a plane in three dimensions, shown in red on the right. This plane is the same one that MTD would calculate for this 3D object to determine its spatial orientation, *i.e.,* axis angle. Indeed, for the special case of an object that is not moving at all, the MTD calculation of axis angle reduces to the same one that traditional MODE uses, as it should. +:numref:`mtd-axis_3d` gives some idea of the reason for fitting a plane, rather than a line, as MODE does. On the left in the figure, we see an object (in blue shaped like an "A") at several time steps moving through the grid. For simplicity, the object is not rotating as it moves (though of course real objects can certainly do this). At each time step, the 2D MODE spatial axis of the object is indicated by the red line. In the center of the figure, we see the same thing, just with more time steps. And on the right, even more time steps. We see that the axis lines at each time step sweep out a plane in three dimensions, shown in red on the right. This plane is the same one that MTD would calculate for this 3D object to determine its spatial orientation, *i.e.,* axis angle. Indeed, for the special case of an object that is not moving at all, the MTD calculation of axis angle reduces to the same one that traditional MODE uses, as it should. .. _mtd-axis_3d: @@ -92,9 +92,9 @@ Finally, MTD calculates several **intensity percentiles** of the raw data values 3D Pair Attributes ~~~~~~~~~~~~~~~~~~ -The next category of spatial attributes is for pairs of objects — one of the pair coming from the collection of forecast objects, the other coming from the observation objects. +The next category of spatial attributes is for pairs of objects - one of the pair coming from the collection of forecast objects, the other coming from the observation objects. -Note: whenever a pair attribute is described below as a *delta*, that means it's a simple difference of two single-object attributes. The difference is always taken as “forecast minus observed”. +Note: whenever a pair attribute is described below as a *delta*, that means it's a simple difference of two single-object attributes. The difference is always taken as "forecast minus observed". The **spatial centroid distance** is the purely spatial part of the centroid separation of two objects. If one centroid is at :math:`(\bar{x}_1, \bar{y}_1, \bar{t}_1)` and the other is at :math:`(\bar{x}_2, \bar{y}_2, \bar{t}_2)` then the distance is calculated as @@ -184,7 +184,7 @@ MTD input The formats for two-dimensional data files used as input to MTD are the same ones supported by most of the MET tools. Generally speaking, if MODE can use a forecast or observation data file as input, then that file can also be used by MTD. The only difference is that while MODE takes only one forecast and one observed data file as input, MTD takes a series of files. -As shown in the next section, filenames for each time used must be given. Thus, for example, if MTD is being used for verification over a period of 24 hours, and the data file valid times are separated by one hour, then a total of 48 filenames must be specified on the MTD command line — 24 filenames for the forecast files, and 24 for the observation files. Further, the filenames must be given in order of increasing valid time. Many users will prefer to write scripts to automate this, rather than type in a lengthy command line by hand. +As shown in the next section, filenames for each time used must be given. Thus, for example, if MTD is being used for verification over a period of 24 hours, and the data file valid times are separated by one hour, then a total of 48 filenames must be specified on the MTD command line - 24 filenames for the forecast files, and 24 for the observation files. Further, the filenames must be given in order of increasing valid time. Many users will prefer to write scripts to automate this, rather than type in a lengthy command line by hand. MTD usage ~~~~~~~~~ @@ -558,7 +558,7 @@ The contents of the OBJECT_ID and OBJECT_CAT columns identify the objects using - Angle that the axis plane of an object makes with the grid x direction * - 33 - VOLUME - - Integer count of the number of 3D “cells” in an object + - Integer count of the number of 3D "cells" in an object * - 34 - START_TIME - Object start time @@ -631,7 +631,7 @@ The contents of the OBJECT_ID and OBJECT_CAT columns identify the objects using - Difference in object ending time steps * - 33 - INTERSECTION_VOLUME - - “Volume” of object intersection + - "Volume" of object intersection * - 34 - DURATION_DIFF - Difference in the lifetimes of the two objects diff --git a/met/docs/Users_Guide/mode.rst b/met/docs/Users_Guide/mode.rst index 68556c2c9c..defbb38603 100644 --- a/met/docs/Users_Guide/mode.rst +++ b/met/docs/Users_Guide/mode.rst @@ -30,7 +30,7 @@ The process used for resolving objects in a raw data field is called *convolutio In this formula, :math:`f` is the raw data field, :math:`\phi` is the filter function, and :math:`C` is the resulting convolved field. The variables :math:`(x, y)` and :math:`(u, v)` are grid coordinates. The filter function :math:`\phi` is a simple circular filter determined by a radius of influence :math:`R` , and a height :math:`H` : -.. math:: \phi (x,y) = \begin{eqnarray}\begin{cases} H &\text{if } x^2 + y^2\leq R^2\\ 0 &\text{otherwise.} \end{cases}\end{eqnarray} +.. math:: \phi (x,y) = \begin{align}\begin{cases} H &\text{if } x^2 + y^2\leq R^2\\ 0 &\text{otherwise.} \end{cases}\end{align} The parameters :math:`R` and :math:`H` are not independent. They are related by the requirement that the integral of :math:`\phi` over the grid be unity: @@ -40,13 +40,13 @@ Thus, the radius of influence :math:`R` is the only tunable parameter in the con Once the convolved field :math:`C` is in hand, it is thresholded to create a mask field :math:`M` : -.. math:: M(x,y) = \begin{eqnarray}\begin{cases} 1 &\text{if } C(x,y)\ge T\\ 0 &\text{otherwise.} \end{cases}\end{eqnarray} +.. math:: M(x,y) = \begin{align}\begin{cases} 1 &\text{if } C(x,y)\ge T\\ 0 &\text{otherwise.} \end{cases}\end{align} where :math:`T` is the threshold. The objects are the connected regions where :math:`M = 1` . Finally, the raw data are restored to object interiors to obtain the object field :math:`F` : .. math:: F(x,y)=M(x,y)f(x,y). -Thus, two parameters — the radius of influence :math:`R`, and the threshold :math:`T` — control the entire process of resolving objects in the raw data field. +Thus, two parameters - the radius of influence :math:`R`, and the threshold :math:`T` - control the entire process of resolving objects in the raw data field. An example of the steps involved in resolving objects is shown in :numref:`mode-object_id`. It shows a "raw" precipitation field, where the vertical coordinate represents the precipitation amount. Part (b) shows the convolved field, and part (c) shows the masked field obtained after the threshold is applied. Finally, :numref:`mode-object_id` shows the objects once the original precipitation values have been restored to the interiors of the objects. @@ -148,7 +148,7 @@ Optional arguments for mode 7. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -8. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +8. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the MODE calling sequence is listed below: @@ -641,7 +641,7 @@ This first file uses the following naming convention: where *PREFIX* indicates the user-defined output prefix, *FCST\_VAR\_LVL* is the forecast variable and vertical level being used, *OBS\_VAR\_LVL* is the observation variable and vertical level being used, *HHMMSSL* indicates the forecast lead time, *YYYYMMDD\_HHMMSSV* indicates the forecast valid time, and *HHMMSSA* indicates the accumulation period. The {\tt cts} string stands for contingency table statistics. The generation of this file can be disabled using the *ct\_stats\_flag* option in the configuration file. This CTS output file differs somewhat from the CTS output of the Point-Stat and Grid-Stat tools. The columns of this output file are summarized in :numref:`CTS_output`. -The second ASCII file the MODE tool generates contains all of the attributes for simple objects, the merged cluster objects, and pairs of objects. Each line in this file contains the same number of columns, though those columns not applicable to a given line contain fill data. The first row of every MODE object attribute file is a header containing the column names. The number of lines in this file depends on the number of objects defined. This file contains lines of 6 types that are indicated by the contents of the **OBJECT_ID** column. The **OBJECT_ID** can take the following 6 forms: **FNN, ONN, FNNN_ONNN, CFNNN, CONNN, CFNNN_CONNN**. In each case, **NNN** is a three-digit number indicating the object index. While all lines have the first 18 header columns in common, these 6 forms for **OBJECT_ID** can be divided into two types - one for single objects and one for pairs of objects. The single object lines **(FNN, ONN, CFNNN**, and **CONNN)** contain valid data in columns 19–39 and fill data in columns 40–51. The object pair lines **(FNNN_ONNN** and **CFNNN_CONNN)** contain valid data in columns 40–51 and fill data in columns 19–39. +The second ASCII file the MODE tool generates contains all of the attributes for simple objects, the merged cluster objects, and pairs of objects. Each line in this file contains the same number of columns, though those columns not applicable to a given line contain fill data. The first row of every MODE object attribute file is a header containing the column names. The number of lines in this file depends on the number of objects defined. This file contains lines of 6 types that are indicated by the contents of the **OBJECT_ID** column. The **OBJECT_ID** can take the following 6 forms: **FNN, ONN, FNNN_ONNN, CFNNN, CONNN, CFNNN_CONNN**. In each case, **NNN** is a three-digit number indicating the object index. While all lines have the first 18 header columns in common, these 6 forms for **OBJECT_ID** can be divided into two types - one for single objects and one for pairs of objects. The single object lines **(FNN, ONN, CFNNN**, and **CONNN)** contain valid data in columns 19-39 and fill data in columns 40-51. The object pair lines **(FNNN_ONNN** and **CFNNN_CONNN)** contain valid data in columns 40-51 and fill data in columns 19-39. These object identifiers are described in :numref:`MODE_object_attribute`. diff --git a/met/docs/Users_Guide/plotting.rst b/met/docs/Users_Guide/plotting.rst index 04e9ee629a..7f748e7885 100644 --- a/met/docs/Users_Guide/plotting.rst +++ b/met/docs/Users_Guide/plotting.rst @@ -320,7 +320,7 @@ The plots in :numref:`plotting_Gilbert_skill_score` show time series of frequenc .. _plotting_Gilbert_skill_score: -.. figure:: figure/plotting_Gilbert_skill_score.gif +.. figure:: figure/plotting-Gilbert-skill-score.png Time series of forecast area bias and Gilbert Skill Score for four model configurations (different lines) stratified by time-of-day. @@ -333,7 +333,7 @@ When using the MODE tool, it is possible to think of matched objects as hits and .. _plotting_verification: -.. figure:: figure/plotting_verification.gif +.. figure:: figure/plotting-verification.png Traditional verification scores applied to output of the MODE tool, computed by defining matched observed objects to be hits, unmatched observed objects to be misses, and unmatched forecast objects to be false alarms; weighted by object area. Bar plots show numbers (penultimate row) and areas (bottom row) of observed and forecast objects, respectively. diff --git a/met/docs/Users_Guide/point-stat.rst b/met/docs/Users_Guide/point-stat.rst index a1a7cdd9cf..ed99da2a59 100644 --- a/met/docs/Users_Guide/point-stat.rst +++ b/met/docs/Users_Guide/point-stat.rst @@ -1307,58 +1307,58 @@ The first set of header columns are common to all of the output files generated * - 25 - TOTAL - Total number of data points - * - 26–28 + * - 26-28 - FBAR - Mean value of forecast wind speed - * - 29–31 + * - 29-31 - OBAR - Mean value of observed wind speed - * - 32–34 + * - 32-34 - FS_RMS - Root mean square forecast wind speed - * - 35–37 + * - 35-37 - OS_RMS - Root mean square observed wind speed - * - 38–40 + * - 38-40 - MSVE - Mean squared length of the vector difference between the forecast and observed winds - * - 41–43 + * - 41-43 - RMSVE - Square root of MSVE - * - 45–46 + * - 45-46 - FSTDEV - Standard deviation of the forecast wind speed - * - 47–49 + * - 47-49 - OSTDEV - Standard deviation of the observed wind field - * - 50–52 + * - 50-52 - FDIR - Direction of the average forecast wind vector - * - 53–55 + * - 53-55 - ODIR - Direction of the average observed wind vector - * - 56–58 + * - 56-58 - FBAR_SPEED - Length (speed) of the average forecast wind vector - * - 59–61 + * - 59-61 - OBAR_SPEED - Length (speed) of the average observed wind vector - * - 62–64 + * - 62-64 - VDIFF_SPEED - Length (speed) of the vector difference between the average forecast and average observed wind vectors - * - 65–67 + * - 65-67 - VDIFF_DIR - Direction of the vector difference between the average forecast and average wind vectors - * - 68–70 + * - 68-70 - SPEED_ERR - Difference between the length of the average forecast wind vector and the average observed wind vector (in the sense F - O) - * - 71–73 + * - 71-73 - SPEED_ABSERR - Absolute value of SPEED_ERR - * - 74–76 + * - 74-76 - DIR_ERR - Signed angle between the directions of the average forecast and observed wing vectors. Positive if the forecast wind vector is counterclockwise from the observed wind vector - * - 77–79 + * - 77-79 - DIR_ABSERR - Absolute value of DIR_ABSERR diff --git a/met/docs/Users_Guide/reformat_grid.rst b/met/docs/Users_Guide/reformat_grid.rst index c2c5fe36ba..5975de88d1 100644 --- a/met/docs/Users_Guide/reformat_grid.rst +++ b/met/docs/Users_Guide/reformat_grid.rst @@ -10,17 +10,17 @@ ________________ This section describes the Pcp-Combine tool which summarizes data across multiple input gridded data files and writes the results to a single NetCDF output file. It is often used to modify precipitation accumulation intervals in the forecast and/or observation datasets to make them comparable. However it can also be used to derive summary fields, such as daily min/max temperature or average precipitation rate. -The Pcp-Combine tool supports four types of commands (“sum”, “add”, “subtract”, and “derive”) which may be run on any gridded data files supported by MET. +The Pcp-Combine tool supports four types of commands ("sum", "add", "subtract", and "derive") which may be run on any gridded data files supported by MET. -1. The “sum” command is the default command and therefore specifying “-sum” on the command line is optional. Using the sum arguments described below, Pcp-Combine searches the input directories (“-pcpdir” option) for data that matches the requested time stamps and accumulation intervals. Pcp-Combine only considers files from the input data directory which match the specified regular expression (“-pcprx” option). While “sum” searches for matching data, all the other commands are run on the explicit set of input files specified. +1. The "sum" command is the default command and therefore specifying "-sum" on the command line is optional. Using the sum arguments described below, Pcp-Combine searches the input directories ("-pcpdir" option) for data that matches the requested time stamps and accumulation intervals. Pcp-Combine only considers files from the input data directory which match the specified regular expression ("-pcprx" option). While "sum" searches for matching data, all the other commands are run on the explicit set of input files specified. -2. The “add” command reads the requested data from the input data files and adds them together. +2. The "add" command reads the requested data from the input data files and adds them together. -3. The “subtract” command reads the requested data from exactly two input files and computes their difference. +3. The "subtract" command reads the requested data from exactly two input files and computes their difference. -4. The “derive” command reads the requested data from the input data files and computes the requested summary fields. +4. The "derive" command reads the requested data from the input data files and computes the requested summary fields. -By default, the Pcp-Combine tool processes data for **APCP**, the GRIB string for accumulated precipitation. When requesting data using time strings (i.e. [HH]MMSS), Pcp-Combine searches for accumulated precipitation for that accumulation interval. Alternatively, use the “-field” option to process fields other than **APCP** or for non-GRIB files. The “-field” option may be used multiple times to process multiple fields in a single run. Since the Pcp-Combine tool does not support automated regridding, all input data must be on the same grid. In general the input files should have the same initialization time unless the user has indicated that it should ignore the initialization time for the “sum” command. The “subtract” command produces a warning when the input initialization times differ or the subtraction results in a negative accumulation interval. +By default, the Pcp-Combine tool processes data for **APCP**, the GRIB string for accumulated precipitation. When requesting data using time strings (i.e. [HH]MMSS), Pcp-Combine searches for accumulated precipitation for that accumulation interval. Alternatively, use the "-field" option to process fields other than **APCP** or for non-GRIB files. The "-field" option may be used multiple times to process multiple fields in a single run. Since the Pcp-Combine tool does not support automated regridding, all input data must be on the same grid. In general the input files should have the same initialization time unless the user has indicated that it should ignore the initialization time for the "sum" command. The "subtract" command produces a warning when the input initialization times differ or the subtraction results in a negative accumulation interval. pcp_combine usage ~~~~~~~~~~~~~~~~~ @@ -82,9 +82,9 @@ Optional arguments for pcp_combine 6. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -7. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +7. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -8. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +8. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. Required arguments for the pcp_combine sum command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -100,14 +100,14 @@ Required arguments for the pcp_combine sum command Optional arguments for pcp_combine sum command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -5. The **-pcpdir path** option indicates the directories in which the input files reside. The contents of “**path**” will override the default setting. This option may be used multiple times and can accept multiple arguments, supporting the use of wildcards. +5. The **-pcpdir path** option indicates the directories in which the input files reside. The contents of "**path**" will override the default setting. This option may be used multiple times and can accept multiple arguments, supporting the use of wildcards. -6. The **-pcprx reg_exp** option indicates the regular expression to be used in matching files in the search directories specified. The contents of “reg_exp” will override the default setting that matches all file names. If the search directories contain a large number of files, the user may specify that only a subset of those files be processed using a regular expression which will speed up the run time. +6. The **-pcprx reg_exp** option indicates the regular expression to be used in matching files in the search directories specified. The contents of "reg_exp" will override the default setting that matches all file names. If the search directories contain a large number of files, the user may specify that only a subset of those files be processed using a regular expression which will speed up the run time. Required arguments for the pcp_combine derive command ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -1. The “derive” run command must be followed by **stat_list** which is a comma-separated list of summary fields to be computed. The **stat_list** may be set to sum, min, max, range, mean, stdev, and vld_count for the sum, minimum, maximum, range (max-min), average, standard deviation, and valid data count fields, respectively. +1. The "derive" run command must be followed by **stat_list** which is a comma-separated list of summary fields to be computed. The **stat_list** may be set to sum, min, max, range, mean, stdev, and vld_count for the sum, minimum, maximum, range (max-min), average, standard deviation, and valid data count fields, respectively. Input files for pcp_combine add, subtract, and derive commands ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -116,9 +116,9 @@ The input files for the add, subtract, and derive command can be specified in on 1. Use **file_1 config_str_1 ... file_n config_str_n** to specify the full path to each input file followed by a description of the data to be read from it. The **config_str_i** argument describing the data can be a set to a time string in HH[MMSS] format for accumulated precipitation or a full configuration string. For example, use **'name="TMP"; level="P500";'** to process temperature at 500mb. -2. Use **file_1 ... file_n** to specify the list of input files to be processed on the command line. Rather than specifying a separate configuration string for each input file, the “-field” command line option is required to specify the data to be processed. +2. Use **file_1 ... file_n** to specify the list of input files to be processed on the command line. Rather than specifying a separate configuration string for each input file, the "-field" command line option is required to specify the data to be processed. -3. Use **input_file_list** to specify the name of an ASCII file which contains the paths for the gridded data files to be processed. As in the previous option, the “-field” command line option is required to specify the data to be processed. +3. Use **input_file_list** to specify the name of an ASCII file which contains the paths for the gridded data files to be processed. As in the previous option, the "-field" command line option is required to specify the data to be processed. An example of the pcp_combine calling sequence is presented below: @@ -260,7 +260,7 @@ Optional arguments for regrid_data_plane 12. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -13. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +13. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. 14. The **-compress level** option specifies the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. @@ -337,9 +337,9 @@ Optional arguments for shift_data_plane 9. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -10. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +10. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -11. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +11. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. For more details on setting the **-method** and **-width** options, see the **regrid** entry in :numref:`config_options`. An example of the shift_data_plane calling sequence is shown below: @@ -402,7 +402,7 @@ Optional arguments for modis_regrid 8. The **-units text** option specifies the units string in the global attributes section of the output file. -9. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +9. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the modis_regrid calling sequence is shown below: @@ -462,7 +462,7 @@ Optional arguments for wwmca_plot 4. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -5. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. +5. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. .. figure:: figure/reformat_grid_fig2.png @@ -502,11 +502,11 @@ Optional arguments for wwmca_regrid 5. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -6. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. +6. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. -7. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +7. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. -In any regridding problem, there are two grids involved: the “From” grid, which is the grid the input data are on, and the “To” grid, which is the grid the data are to be moved onto. In **WWMCA-Regrid** the “From” grid is pre-defined by the hemisphere of the WWMCA binary files being processed. The “To” grid and corresponding regridding logic are specified using the **regrid** section of the configuration file. If the “To” grid is entirely confined to one hemisphere, then only the WWMCA data file for that hemisphere needs to be given. If the “To” grid or the interpolation box used straddles the equator, the data files for both hemispheres need to be given. Once the “To” grid is specified in the config file, the WWMCA-Regrid tool will know which input data files it needs and will complain if it is not given the right ones. +In any regridding problem, there are two grids involved: the "From" grid, which is the grid the input data are on, and the "To" grid, which is the grid the data are to be moved onto. In **WWMCA-Regrid** the "From" grid is pre-defined by the hemisphere of the WWMCA binary files being processed. The "To" grid and corresponding regridding logic are specified using the **regrid** section of the configuration file. If the "To" grid is entirely confined to one hemisphere, then only the WWMCA data file for that hemisphere needs to be given. If the "To" grid or the interpolation box used straddles the equator, the data files for both hemispheres need to be given. Once the "To" grid is specified in the config file, the WWMCA-Regrid tool will know which input data files it needs and will complain if it is not given the right ones. wwmca_regrid configuration file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/met/docs/Users_Guide/reformat_point.rst b/met/docs/Users_Guide/reformat_point.rst index f872a12b40..999393b72d 100644 --- a/met/docs/Users_Guide/reformat_point.rst +++ b/met/docs/Users_Guide/reformat_point.rst @@ -61,10 +61,10 @@ The **-valid_beg** time option in YYYYMMDD[_HH[MMSS]] format sets the beginning The **-valid_end** time option in YYYYMMDD[_HH[MMSS]] format sets the end of the retention time window. 4. -The **-nmsg num_messages** option may be used for testing purposes. This argument indicates that only the first “num_messages” PrepBUFR messages should be processed rather than the whole file. This option is provided to speed up testing because running the PB2NC tool can take a few minutes for each file. Most users will not need this option. +The **-nmsg num_messages** option may be used for testing purposes. This argument indicates that only the first "num_messages" PrepBUFR messages should be processed rather than the whole file. This option is provided to speed up testing because running the PB2NC tool can take a few minutes for each file. Most users will not need this option. 5. -The **-dump path** option may be used to dump the entire contents of the PrepBUFR file to several ASCII files written to the directory specified by “path”. The user may use this option to view a human-readable version of the input PrepBUFR file, although writing the contents to ASCII files can be slow. +The **-dump path** option may be used to dump the entire contents of the PrepBUFR file to several ASCII files written to the directory specified by "path". The user may use this option to view a human-readable version of the input PrepBUFR file, although writing the contents to ASCII files can be slow. 6. The **-index** option shows the available variables with valid data from the BUFR input. It collects the available variable list from BUFR input and checks the existence of valid data and directs the variable names with valid data to the screen. The NetCDF output won't be generated. @@ -73,10 +73,10 @@ The **-index** option shows the available variables with valid data from the BUF The **-log** file option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. 8. -The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. 9. -The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the pb2nc calling sequence is shown below: @@ -99,7 +99,7 @@ When editing configuration files, environment variables may be used for setting For example, using an environment variable to set the **message_type** (see below) parameter to use ADPUPA and ADPSFC message types might consist of the following: -\* In a C-Shell: **setenv MSG_TYP ' “ADPUPA”, “ADPSFC” '** +\* In a C-Shell: **setenv MSG_TYP ' "ADPUPA", "ADPSFC" '** \* In the configuration file: **message_type = [ ${MSG_TYP} ];** @@ -128,7 +128,7 @@ ___________________ .. code-block:: none - message_type_map = [ { key = “AIRCAR”; val = “AIRCAR_PROFILES”; } ]; + message_type_map = [ { key = "AIRCAR"; val = "AIRCAR_PROFILES"; } ]; The **message_type_map** entry is an array of dictionaries, each containing a **key** string and **val** string. This defines a mapping of input PrepBUFR message types to output message types. This provides a method for renaming input PrepBUFR message types. @@ -293,7 +293,7 @@ ___________________ The **time_summary** dictionary enables additional processing for observations with high temporal resolution. The **flag** entry toggles the **time_summary** on (**TRUE**) and off (**FALSE**). If the **raw_data** flag is set to TRUE, then both the individual observation values and the derived time summary value will be written to the output. If FALSE, only the summary values are written. Observations may be summarized across the user specified time period defined by the **beg** and **end** entries in HHMMSS format. The **step** entry defines the time between intervals in seconds. The **width** entry specifies the summary interval in seconds. It may either be set as an integer number of seconds for a centered time interval or a dictionary with beginning and ending time offsets in seconds. -This example listed above does a 10-minute time summary (width = 600;) every 5 minutes (step = 300;) throughout the day (beg = “000000”; end = 235959”;). The first interval will be from 23:55:00 the previous day through 00:04:59 of the current day. The second interval will be from 0:00:00 through 00:09:59. And so on. +This example listed above does a 10-minute time summary (width = 600;) every 5 minutes (step = 300;) throughout the day (beg = "000000"; end = 235959";). The first interval will be from 23:55:00 the previous day through 00:04:59 of the current day. The second interval will be from 0:00:00 through 00:09:59. And so on. The two **width** settings listed above are equivalent. Both define a centered 10-minute time interval. Use the **beg** and **end** entries to define uncentered time intervals. The following example requests observations for one hour prior: @@ -422,7 +422,7 @@ This section describes how to run the ASCII2NC tool. The ASCII2NC tool is used t Initial versions of the ASCII2NC tool supported only a simple 11 column ASCII point observation format. It currently supports point observation data in the following formats: the default 11 column format, little_r format, `SURFace RADiation (SURFRAD) `_ and Integrated Surface Irradiance Study (ISIS) formats, the Western Wind and Solar Integration Study (WWSIS) format, and the `AErosol RObotic NEtwork (AERONET) versions 2 and 3 format. `_ WWSIS data are available by request from National Renewable Energy Laboratory (NREL) in Boulder, CO. -MET version 9.0 adds support for the passing observations to ascii2nc using a Python script with the “-format python” option. An example of running ASCII2NC with Python embedding is included below. +MET version 9.0 adds support for the passing observations to ascii2nc using a Python script with the "-format python" option. An example of running ASCII2NC with Python embedding is included below. The default ASCII point observation format consists of one row of data per observation value. Each row of data consists of 11 columns as shown in :numref:`table_reform-point_ascii2nc_format`. @@ -496,14 +496,14 @@ ascii2nc has two required arguments and can take several optional ones. Required arguments for ascii2nc ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -1. The **ascii_file** argument is the ASCII point observation file(s) to be processed. If using Python embedding with “-format python” provides a quoted string containing the Python script to be run followed by any command line arguments that script takes. +1. The **ascii_file** argument is the ASCII point observation file(s) to be processed. If using Python embedding with "-format python" provides a quoted string containing the Python script to be run followed by any command line arguments that script takes. 2. The **netcdf_file** argument is the NetCDF output file to be written. Optional arguments for ascii2nc ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -3. The **-format ASCII_format** option may be set to “met_point”, “little_r”, “surfrad”, “wwsis”, “aeronet”, “aeronetv2”, “aeronetv3”, or “python”. If passing in ISIS data, use the “surfrad” format flag. +3. The **-format ASCII_format** option may be set to "met_point", "little_r", "surfrad", "wwsis", "aeronet", "aeronetv2", "aeronetv3", or "python". If passing in ISIS data, use the "surfrad" format flag. 4. The **-config file** option is the configuration file for generating time summaries. @@ -511,13 +511,13 @@ Optional arguments for ascii2nc 6. The **-mask_poly** file option is a polyline masking file to filter the point observations spatially. -7. The **-mask_sid** file|list option is a station ID masking file or a comma-separated list of station ID's to filter the point observations spatially. See the description of the “sid” entry in :numref:`config_options`. +7. The **-mask_sid** file|list option is a station ID masking file or a comma-separated list of station ID's to filter the point observations spatially. See the description of the "sid" entry in :numref:`config_options`. 8. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -9. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +9. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -10. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +10. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the ascii2nc calling sequence is shown below: @@ -538,7 +538,7 @@ Here is an example of processing the same set of observations but using Python e .. code-block:: none ascii2nc -format python \ - “MET_BASE/python/read_ascii_point.py sample_ascii_obs.txt" \ + "MET_BASE/python/read_ascii_point.py sample_ascii_obs.txt" \ sample_ascii_obs_python.nc Please refer to :numref:`Appendix F, Section %s ` for more details about Python embedding in MET. @@ -592,7 +592,7 @@ ascii2nc output The NetCDF output of the ASCII2NC tool is structured in the same way as the output of the PB2NC tool described in :numref:`pb2nc output`. -“obs_vid” variable is replaced with “obs_gc” when the GRIB code is given instead of the variable names. In this case, the global variable “use_var_id” does not exist or set to false (use_var_id = "false" ;). Three variables (obs_var, obs_units, and obs_desc) related with variable names are not added. +"obs_vid" variable is replaced with "obs_gc" when the GRIB code is given instead of the variable names. In this case, the global variable "use_var_id" does not exist or set to false (use_var_id = "false" ;). Three variables (obs_var, obs_units, and obs_desc) related with variable names are not added. MADIS2NC tool @@ -662,13 +662,13 @@ Optional arguments for madis2nc 9. The **-mask_poly file** option defines a polyline masking file for filtering the point observations spatially. -10. The **-mask_sid file|list** option is a station ID masking file or a comma-separated list of station ID's for filtering the point observations spatially. See the description of the “sid” entry in :numref:`config_options`. +10. The **-mask_sid file|list** option is a station ID masking file or a comma-separated list of station ID's for filtering the point observations spatially. See the description of the "sid" entry in :numref:`config_options`. 11. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -12. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. +12. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. 13. The **-compress level** option specifies the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. @@ -720,7 +720,7 @@ madis2nc output The NetCDF output of the MADIS2NC tool is structured in the same way as the output of the PB2NC tool described in :numref:`pb2nc output`. -“obs_vid” variable is replaced with “obs_gc” when the GRIB code is given instead of the variable names. In this case, the global variable “use_var_id” does not exist or set to false (use_var_id = "false" ;). Three variables (obs_var, obs_units, and obs_desc) related with variable names are not added. +"obs_vid" variable is replaced with "obs_gc" when the GRIB code is given instead of the variable names. In this case, the global variable "use_var_id" does not exist or set to false (use_var_id = "false" ;). Three variables (obs_var, obs_units, and obs_desc) related with variable names are not added. LIDAR2NC tool @@ -762,9 +762,9 @@ Optional arguments for lidar2nc 3. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -4. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +4. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -5. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +5. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. lidar2nc output ~~~~~~~~~~~~~~~ @@ -889,9 +889,9 @@ Optional arguments for ioda2nc 8. The **-log** file option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -9. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +9. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -10. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +10. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the ioda2nc calling sequence is shown below: @@ -1017,7 +1017,7 @@ Required arguments for point2grid 3. The **output_filename** argument is the name of the output NetCDF file to be written. -4. The **-field** string argument is a string that defines the data to be regridded. It may be used multiple times. If **-adp** option is given (for AOD data from GOES16/17), the name consists with the variable name from the input data file and the variable name from ADP data file (for example, “AOD_Smoke” or “AOD_Dust”: getting AOD variable from the input data and applying smoke or dust variable from ADP data file). +4. The **-field** string argument is a string that defines the data to be regridded. It may be used multiple times. If **-adp** option is given (for AOD data from GOES16/17), the name consists with the variable name from the input data file and the variable name from ADP data file (for example, "AOD_Smoke" or "AOD_Dust": getting AOD variable from the input data and applying smoke or dust variable from ADP data file). Optional arguments for point2grid @@ -1025,9 +1025,9 @@ Optional arguments for point2grid 5. The **-config** file option is the configuration file to be used. -6. The **-qc** flags option specifies a comma-separated list of quality control (QC) flags, for example “0,1”. This should only be applied if grid_mapping is set to “goes_imager_projection” and the QC variable exists. +6. The **-qc** flags option specifies a comma-separated list of quality control (QC) flags, for example "0,1". This should only be applied if grid_mapping is set to "goes_imager_projection" and the QC variable exists. -7. The **-adp adp_file_name** option provides an additional Aerosol Detection Product (ADP) information on aerosols, dust, and smoke. This option is ignored if the requested variable is not AOD (“AOD_Dust” or “AOD_Smoke”) from GOES16/17. The gridded data is filtered by the presence of dust/smoke. If -qc options are given, it's applied to QC of dust/smoke, too (First filtering with AOD QC values and the second filtering with dust/smoke QC values). +7. The **-adp adp_file_name** option provides an additional Aerosol Detection Product (ADP) information on aerosols, dust, and smoke. This option is ignored if the requested variable is not AOD ("AOD_Dust" or "AOD_Smoke") from GOES16/17. The gridded data is filtered by the presence of dust/smoke. If -qc options are given, it's applied to QC of dust/smoke, too (First filtering with AOD QC values and the second filtering with dust/smoke QC values). 8. The **-method type** option specifies the regridding method. The default method is UW_MEAN. @@ -1043,9 +1043,9 @@ Optional arguments for point2grid 14. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -15. The **-v level** option indicates the desired level of verbosity. The value of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +15. The **-v level** option indicates the desired level of verbosity. The value of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. -16. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +16. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. Only 4 interpolation methods are applied to the field variables; MIN/MAX/MEDIAN/UW_MEAN. The GAUSSIAN method is applied to the probability variable only. Unlike regrad_data_plane, MAX method is applied to the file variable and Gaussian method to the probability variable with the MAXGAUSS method. If the probability variable is not requested, MAXGAUSS method is the same as MAX method. @@ -1083,13 +1083,13 @@ The point2grid tool will output a gridded NetCDF file containing the following: 4. The count field which represents the number of point observations that were included calculating the value of the variable at that grid cell. -5. The mask field which is a binary field representing the presence or lack thereof of point observations at that grid cell. A value of “1” indicates that there was at least one point observation within the bounds of that grid cell and a value of “0” indicates the lack of point observations at that grid cell. +5. The mask field which is a binary field representing the presence or lack thereof of point observations at that grid cell. A value of "1" indicates that there was at least one point observation within the bounds of that grid cell and a value of "0" indicates the lack of point observations at that grid cell. 6. The probability field which is the probability of the event defined by the **-prob_cat_thresh** command line option. The output variable name includes the threshold used to define the probability. Ranges from 0 to 1. -7. The probability mask field which is a binary field that represents whether or not there is probability data at that grid point. Can be either “0” or “1” with “0” meaning the probability value does not exist and a value of “1” meaning that the probability value does exist. +7. The probability mask field which is a binary field that represents whether or not there is probability data at that grid point. Can be either "0" or "1" with "0" meaning the probability value does not exist and a value of "1" meaning that the probability value does exist. For MET observation input and CF complaint NetCDF input with 2D time variable: The latest observation time within the target grid is saved as the observation time. If the "valid_time" is configured at the configuration file, the valid_time from the configuration file is saved into the output file. diff --git a/met/docs/Users_Guide/refs.rst b/met/docs/Users_Guide/refs.rst index a039a91ab8..a58ddf8dda 100644 --- a/met/docs/Users_Guide/refs.rst +++ b/met/docs/Users_Guide/refs.rst @@ -13,7 +13,7 @@ References | Barker, T. W., 1991: The relationship between spread and forecast error in -| extended-range forecasts. *Journal of Climate*, 4, 733–742. +| extended-range forecasts. *Journal of Climate*, 4, 733-742. | .. _Bradley-2008: @@ -27,7 +27,7 @@ References | Brill, K. F., and F. Mesinger, 2009: Applying a general analytic method | for assessing bias sensitivity to bias-adjusted threat and equitable -| threat scores. *Weather and Forecasting*, 24, 1748–1754. +| threat scores. *Weather and Forecasting*, 24, 1748-1754. | .. _Brown-2007: @@ -45,7 +45,7 @@ References | Buizza, R., 1997: Potential forecast skill of ensemble prediction and spread | and skill distributions of the ECMWF ensemble prediction system. *Monthly* -| *Weather Review*,125, 99–119. +| *Weather Review*,125, 99-119. | .. _Bullock-2016: @@ -58,7 +58,7 @@ References | Candille, G., and O. Talagrand, 2008: Impact of observational error on the | validation of ensemble prediction systems. *Quarterly Journal of the Royal* -| *Meteorological Society* 134: 959–971. +| *Meteorological Society* 134: 959-971. | .. _Casati-2004: @@ -153,9 +153,9 @@ References .. _Mason-2004: -| Mason, S. J., 2004: On Using “Climatology” as a Reference Strategy +| Mason, S. J., 2004: On Using "Climatology" as a Reference Strategy | in the Brier and Ranked Probability Skill Scores. *Monthly Weather Review*, -| 132, 1891–1895. +| 132, 1891-1895. | .. _Mittermaier-2014: @@ -166,7 +166,7 @@ References .. _Mood-1974: -| Mood, A. M., F. A. Graybill and D. C. Boes, 1974: *Introduction to the* +| Mood, A. M., F. A. Graybill and D. C. Boes, 1974: *Introduction to the* | *Theory of Statistics*, McGraw-Hill, 299-338. | @@ -194,14 +194,14 @@ References | Saetra O., H. Hersbach, J-R Bidlot, D. Richardson, 2004: Effects of | observation errors on the statistics for ensemble spread and -| reliability. *Monthly Weather Review* 132: 1487–1501. +| reliability. *Monthly Weather Review* 132: 1487-1501. | .. _Santos-2012: | Santos C. and A. Ghelli, 2012: Observational probability method to assess | ensemble precipitation forecasts. *Quarterly Journal of the Royal* -| *Meteorological Society* 138: 209–221. +| *Meteorological Society* 138: 209-221. | .. _Schwartz-2017: @@ -213,7 +213,7 @@ References .. _Stephenson-2000: -| Stephenson, D.B., 2000: Use of the “Odds Ratio” for diagnosing +| Stephenson, D.B., 2000: Use of the "Odds Ratio" for diagnosing | forecast skill. *Weather and Forecasting*, 15, 221-232. | @@ -235,7 +235,7 @@ References | Wilks, D.S. 2010: Sampling distributions of the Brier score and Brier skill | score under serial dependence. *Quarterly Journal of the Royal* -| *Meteorological Society,*, 136, 2109–2118. doi:10.1002/qj.709 +| *Meteorological Society,*, 136, 2109-2118. doi:10.1002/qj.709 | .. _Wilks-2011: diff --git a/met/docs/Users_Guide/rmw-analysis.rst b/met/docs/Users_Guide/rmw-analysis.rst index c7247446f5..9ae27fe82f 100644 --- a/met/docs/Users_Guide/rmw-analysis.rst +++ b/met/docs/Users_Guide/rmw-analysis.rst @@ -43,7 +43,7 @@ Optional arguments for rmw_analysis 4. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no logfile. -5. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +5. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. rmw_analysis configuration file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/met/docs/Users_Guide/series-analysis.rst b/met/docs/Users_Guide/series-analysis.rst index 26e7e200ea..bc9095dbf1 100644 --- a/met/docs/Users_Guide/series-analysis.rst +++ b/met/docs/Users_Guide/series-analysis.rst @@ -63,7 +63,7 @@ Optional arguments for series_analysis 8. The -v level overrides the default level of logging (2). -9. The -compress level option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +9. The -compress level option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the series_analysis calling sequence is shown below: diff --git a/met/docs/Users_Guide/stat-analysis.rst b/met/docs/Users_Guide/stat-analysis.rst index d12ae5746a..2267f7ba03 100644 --- a/met/docs/Users_Guide/stat-analysis.rst +++ b/met/docs/Users_Guide/stat-analysis.rst @@ -8,23 +8,23 @@ ____________ The Stat-Analysis tool ties together results from the Point-Stat, Grid-Stat, Ensemble-Stat, Wavelet-Stat, and TC-Gen tools by providing summary statistical information and a way to filter their STAT output files. It processes the STAT output created by the other MET tools in a variety of ways which are described in this section. -MET version 9.0 adds support for the passing matched pair data (MPR) into Stat-Analysis using a Python script with the “-lookin python ...” option. An example of running Stat-Analysis with Python embedding is shown in :numref:`stat_analysis-usage`. +MET version 9.0 adds support for the passing matched pair data (MPR) into Stat-Analysis using a Python script with the "-lookin python ..." option. An example of running Stat-Analysis with Python embedding is shown in :numref:`stat_analysis-usage`. Scientific and statistical aspects __________________________________ -The Stat-Analysis tool can perform a variety of analyses, and each type of analysis is called a “job”. The job types include the ability to (i) aggregate results over a user-specified time; (ii) stratify statistics based on time of day, model initialization time, lead-time, model run identifier, output filename, or wavelet decomposition scale; and (iii) compute specific verification indices such as the GO Index [1]_ +The Stat-Analysis tool can perform a variety of analyses, and each type of analysis is called a "job". The job types include the ability to (i) aggregate results over a user-specified time; (ii) stratify statistics based on time of day, model initialization time, lead-time, model run identifier, output filename, or wavelet decomposition scale; and (iii) compute specific verification indices such as the GO Index [1]_ and wind direction statistics. Future functionality may include information about time-trends and/or calculations based on climatology (e.g., anomaly correlation). This section summarizes the capabilities of the supported Stat-Analysis jobs. Filter STAT lines ~~~~~~~~~~~~~~~~~ -The Stat-Analysis “filter” job simply filters out specific STAT lines based on user-specified search criteria. All of the STAT lines that are retained from one or many files are written to a single output file. The output file for filtered STAT lines must be specified using the **-dump_row** job command option. +The Stat-Analysis "filter" job simply filters out specific STAT lines based on user-specified search criteria. All of the STAT lines that are retained from one or many files are written to a single output file. The output file for filtered STAT lines must be specified using the **-dump_row** job command option. Summary statistics for columns ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The Stat-Analysis “summary” job produces summary information for columns of data. After the user specifies the column(s) of interest and any other relevant search criteria, summary information is produced from values in those column(s) of data. The summary statistics produced are: mean, standard deviation, minimum, maximum, the 10th, 25th, 50th, 75th, and 90th percentiles, the interquartile range, the range, and both weighted and unweighted means using the logic prescribed by the World Meteorological Organization (WMO). +The Stat-Analysis "summary" job produces summary information for columns of data. After the user specifies the column(s) of interest and any other relevant search criteria, summary information is produced from values in those column(s) of data. The summary statistics produced are: mean, standard deviation, minimum, maximum, the 10th, 25th, 50th, 75th, and 90th percentiles, the interquartile range, the range, and both weighted and unweighted means using the logic prescribed by the World Meteorological Organization (WMO). Confidence intervals are computed for the mean and standard deviation of the column of data. For the mean, the confidence interval is computed two ways - based on an assumption of normality and also using the bootstrap method. For the standard deviation, the confidence interval is computed using the bootstrap method. In this application of the bootstrap method, the values in the column of data being summarized are resampled, and for each replicated sample, the mean and standard deviation are computed. @@ -39,14 +39,14 @@ The **-derive** job command option can be used to perform the derivation of stat Aggregated values from multiple STAT lines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The Stat-Analysis “aggregate” job aggregates values from multiple STAT lines of the same type. The user may specify the specific line type of interest and any other relevant search criteria. The Stat-Analysis tool then creates sums of each of the values in all lines matching the search criteria. The aggregated data are output as the same line type as the user specified. The STAT line types which may be aggregated in this way are the contingency table (FHO, CTC, PCT, MCTC, NBRCTC), partial sums (SL1L2, SAL1L2, VL1L2, and VAL1L2), and other (ISC, ECNT, RPS, RHIST, PHIST, RELP, NBRCNT, SSVAR, and GRAD) line types. +The Stat-Analysis "aggregate" job aggregates values from multiple STAT lines of the same type. The user may specify the specific line type of interest and any other relevant search criteria. The Stat-Analysis tool then creates sums of each of the values in all lines matching the search criteria. The aggregated data are output as the same line type as the user specified. The STAT line types which may be aggregated in this way are the contingency table (FHO, CTC, PCT, MCTC, NBRCTC), partial sums (SL1L2, SAL1L2, VL1L2, and VAL1L2), and other (ISC, ECNT, RPS, RHIST, PHIST, RELP, NBRCNT, SSVAR, and GRAD) line types. Aggregate STAT lines and produce aggregated statistics ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The Stat-Analysis “aggregate-stat” job aggregates multiple STAT lines of the same type together and produces relevant statistics from the aggregated line. This may be done in the same manner listed above in :numref:`StA_Aggregated-values-from`. However, rather than writing out the aggregated STAT line itself, the relevant statistics generated from that aggregated line are provided in the output. Specifically, if a contingency table line type (FHO, CTC, PCT, MCTC, or NBRCTC) has been aggregated, contingency table statistics (CTS, ECLV, PSTD, MCTS, or NBRCTS) line types can be computed. If a partial sums line type (SL1L2 or SAL1L2) has been aggregated, the continuous statistics (CNT) line type can be computed. If a vector partial sums line type (VL1L2) has been aggregated, the vector continuous statistics (VCNT) line type can be computed. For ensembles, the ORANK line type can be accumulated into ECNT, RPS, RHIST, PHIST, RELP, or SSVAR output. If the matched pair line type (MPR) has been aggregated, may output line types (FHO, CTC, CTS, CNT, MCTC, MCTS, SL1L2, SAL1L2, VL1L2, VCNT, WDIR, PCT, PSTD, PJC, PRC, or ECLV) can be computed. Multiple output line types may be specified for each “aggregate-stat” job, as long as each output is derivable from the input. +The Stat-Analysis "aggregate-stat" job aggregates multiple STAT lines of the same type together and produces relevant statistics from the aggregated line. This may be done in the same manner listed above in :numref:`StA_Aggregated-values-from`. However, rather than writing out the aggregated STAT line itself, the relevant statistics generated from that aggregated line are provided in the output. Specifically, if a contingency table line type (FHO, CTC, PCT, MCTC, or NBRCTC) has been aggregated, contingency table statistics (CTS, ECLV, PSTD, MCTS, or NBRCTS) line types can be computed. If a partial sums line type (SL1L2 or SAL1L2) has been aggregated, the continuous statistics (CNT) line type can be computed. If a vector partial sums line type (VL1L2) has been aggregated, the vector continuous statistics (VCNT) line type can be computed. For ensembles, the ORANK line type can be accumulated into ECNT, RPS, RHIST, PHIST, RELP, or SSVAR output. If the matched pair line type (MPR) has been aggregated, may output line types (FHO, CTC, CTS, CNT, MCTC, MCTS, SL1L2, SAL1L2, VL1L2, VCNT, WDIR, PCT, PSTD, PJC, PRC, or ECLV) can be computed. Multiple output line types may be specified for each "aggregate-stat" job, as long as each output is derivable from the input. -When aggregating the matched pair line type (MPR), additional required job command options are determined by the requested output line type(s). For example, the “-out_thresh” (or “-out_fcst_thresh” and “-out_obs_thresh” options) are required to compute contingnecy table counts (FHO, CTC) or statistics (CTS). Those same job command options can also specify filtering thresholds when computing continuous partial sums (SL1L2, SAL1L2) or statistics (CNT). Output is written for each threshold specified. +When aggregating the matched pair line type (MPR), additional required job command options are determined by the requested output line type(s). For example, the "-out_thresh" (or "-out_fcst_thresh" and "-out_obs_thresh" options) are required to compute contingnecy table counts (FHO, CTC) or statistics (CTS). Those same job command options can also specify filtering thresholds when computing continuous partial sums (SL1L2, SAL1L2) or statistics (CNT). Output is written for each threshold specified. When aggregating the matched pair line type (MPR) and computing an output contingency table statistics (CTS) or continuous statistics (CNT) line type, the bootstrapping method can be applied to compute confidence intervals. The bootstrapping method is applied here in the same way that it is applied in the statistics tools. For a set of n matched forecast-observation pairs, the matched pairs are resampled with replacement many times. For each replicated sample, the corresponding statistics are computed. The confidence intervals are derived from the statistics computed for each replicated sample. @@ -55,7 +55,7 @@ When aggregating the matched pair line type (MPR) and computing an output contin Skill Score Index, including GO Index ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The Stat-Analysis “ss_index” and “go_index” jobs calculate the skill score indices by weighting scores for different meteorological fields at different pressure levels and for different lead times. The GO Index is a special case of the Skill Score index for which a specific configuration file is provided. The GO index is a weighted average of the RMSE values for wind speed, dew point temperature, temperature, height, and pressure at several levels in the atmosphere. The variables, levels, and lead times included in the index are shown in :numref:`compute_GO_Index` and are defined by a default Stat-Analysis configuration file. The partial sums (SL1L2 lines in the STAT output) for each of these variables at each level and lead time must have been computed in a previous step. The Stat-Analysis tool then uses the weights in :numref:`compute_GO_Index` to compute values for the GO Index. For a general skill score index, the user can specify the weights and variables to use in the calculations in a Stat-Analysis configuration file and run the ss_index job type. +The Stat-Analysis "ss_index" and "go_index" jobs calculate the skill score indices by weighting scores for different meteorological fields at different pressure levels and for different lead times. The GO Index is a special case of the Skill Score index for which a specific configuration file is provided. The GO index is a weighted average of the RMSE values for wind speed, dew point temperature, temperature, height, and pressure at several levels in the atmosphere. The variables, levels, and lead times included in the index are shown in :numref:`compute_GO_Index` and are defined by a default Stat-Analysis configuration file. The partial sums (SL1L2 lines in the STAT output) for each of these variables at each level and lead time must have been computed in a previous step. The Stat-Analysis tool then uses the weights in :numref:`compute_GO_Index` to compute values for the GO Index. For a general skill score index, the user can specify the weights and variables to use in the calculations in a Stat-Analysis configuration file and run the ss_index job type. .. _compute_GO_Index: @@ -151,12 +151,12 @@ The Stat-Analysis “ss_index” and “go_index” jobs calculate the skill sco Ramp Events ~~~~~~~~~~~ -The Stat-Analysis “ramp” job identifies ramp events (large increases or decreases in values over a time window) in both the forecast and observation data. It categorizes these events as hits, misses, false alarms, or correct negatives by applying a configurable matching time window and computes the corresponding categorical statistics. +The Stat-Analysis "ramp" job identifies ramp events (large increases or decreases in values over a time window) in both the forecast and observation data. It categorizes these events as hits, misses, false alarms, or correct negatives by applying a configurable matching time window and computes the corresponding categorical statistics. Wind Direction Statistics ~~~~~~~~~~~~~~~~~~~~~~~~~ -The Stat-Analysis “aggregate_stat” job can read vector partial sums and derive wind direction error statistics (WDIR). The vector partial sums (VL1L2 or VAL1L2) or matched pairs (MPR) for the UGRD and VGRD must have been computed in a previous step, i.e. by Point-Stat or Grid-Stat tools. This job computes an average forecast wind direction and an average observed wind direction along with their difference. The output is in degrees. In Point-Stat and Grid-Stat, the UGRD and VGRD can be verified using thresholds on their values or on the calculated wind speed. If thresholds have been applied, the wind direction statistics are calculated for each threshold. +The Stat-Analysis "aggregate_stat" job can read vector partial sums and derive wind direction error statistics (WDIR). The vector partial sums (VL1L2 or VAL1L2) or matched pairs (MPR) for the UGRD and VGRD must have been computed in a previous step, i.e. by Point-Stat or Grid-Stat tools. This job computes an average forecast wind direction and an average observed wind direction along with their difference. The output is in degrees. In Point-Stat and Grid-Stat, the UGRD and VGRD can be verified using thresholds on their values or on the calculated wind speed. If thresholds have been applied, the wind direction statistics are calculated for each threshold. The first step in verifying wind direction is running the Grid-Stat and/or Point-Stat tools to verify each forecast of interest and generate the VL1L2 or MPR line(s). When running these tools, please note: @@ -203,7 +203,7 @@ In the usage statement for the Stat-Analysis tool, some additional terminology i Required arguments for stat_analysis ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -1. The **-lookin path** specifies the name of a directory to be searched recursively for STAT files (ending in “.stat”) or any explicit file name with any suffix (such as “_ctc.txt”) to be read. This option may be used multiple times to specify multiple directories and/or files to be read. If “-lookin python” is used, it must be followed by a Python embedding script and any command line arguments it takes. Python embedding can be used to pass matched pair (MPR) lines as input to Stat-Analysis. +1. The **-lookin path** specifies the name of a directory to be searched recursively for STAT files (ending in ".stat") or any explicit file name with any suffix (such as "_ctc.txt") to be read. This option may be used multiple times to specify multiple directories and/or files to be read. If "-lookin python" is used, it must be followed by a Python embedding script and any command line arguments it takes. Python embedding can be used to pass matched pair (MPR) lines as input to Stat-Analysis. 2. Either a configuration file must be specified with the **-config** option, or a **JOB COMMAND LINE** must be denoted. The **JOB COMMAND LINE** is described in :numref:`stat_analysis-configuration-file` @@ -553,9 +553,9 @@ This option specifies the desired output line type(s) for the **aggregate_stat** The Stat-Analysis tool writes its output to either the log file or the file specified using the **-out** command line option. However the **aggregate** and **aggregate_stat** jobs create STAT output lines and the standard output written lacks the full set of STAT header columns. The **-out_stat** job command option may be used for these jobs to specify the name of an output file to which full STAT output lines should be written. When the **-out_stat** job command option is used for **aggregate** and **aggregate_stat** jobs the output is sent to the **-out_stat** file instead of the log or **-out** file. -Jobs will often combine output with multiple entries in the header columns. For example, a job may aggregate output with three different values in the **VX_MASK** column, such as “mask1”, “mask2”, and “mask3”. The output **VX_MASK** column will contain the unique values encountered concatenated together with commas: “mask1,mask2,mask3”. Alternatively, the **-set_hdr** option may be used to specify what should be written to the output header columns, such as “-set_hdr VX_MASK all_three_masks”. +Jobs will often combine output with multiple entries in the header columns. For example, a job may aggregate output with three different values in the **VX_MASK** column, such as "mask1", "mask2", and "mask3". The output **VX_MASK** column will contain the unique values encountered concatenated together with commas: "mask1,mask2,mask3". Alternatively, the **-set_hdr** option may be used to specify what should be written to the output header columns, such as "-set_hdr VX_MASK all_three_masks". -When using the “-out_stat” option to create a .stat output file and stratifying results using one or more “-by” job command options, those columns may be referenced in the “-set_hdr” option. When using multiple “-by” options, use “CASE” to reference the full case information string: +When using the "-out_stat" option to create a .stat output file and stratifying results using one or more "-by" job command options, those columns may be referenced in the "-set_hdr" option. When using multiple "-by" options, use "CASE" to reference the full case information string: .. code-block:: none @@ -570,7 +570,7 @@ The example above reads MPR lines, stratifies the data by forecast variable name -mask_poly file -mask_sid file|list -When processing input MPR lines, these options may be used to define a masking grid, polyline, or list of station ID's to filter the matched pair data geographically prior to computing statistics. The **-mask_sid** option is a station ID masking file or a comma-separated list of station ID's for filtering the matched pairs spatially. See the description of the “sid” entry in :numref:`config_options`. +When processing input MPR lines, these options may be used to define a masking grid, polyline, or list of station ID's to filter the matched pair data geographically prior to computing statistics. The **-mask_sid** option is a station ID masking file or a comma-separated list of station ID's for filtering the matched pairs spatially. See the description of the "sid" entry in :numref:`config_options`. .. code-block:: none diff --git a/met/docs/Users_Guide/tc-dland.rst b/met/docs/Users_Guide/tc-dland.rst index d902be5569..163c732968 100644 --- a/met/docs/Users_Guide/tc-dland.rst +++ b/met/docs/Users_Guide/tc-dland.rst @@ -58,6 +58,6 @@ Optional arguments for tc_dland 5. The **-log file** argument outputs log messages to the specified file. -6. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +6. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. 7. The **-compress level** option specifies the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. Setting the compression level to 0 will make no compression for the NetCDF output. Lower numbers result in minimal compression and faster I/O processing speed; higher numbers result in better compression, but at the expense of I/O processing speed. diff --git a/met/docs/Users_Guide/tc-gen.rst b/met/docs/Users_Guide/tc-gen.rst index 763c5663b4..61209566dc 100644 --- a/met/docs/Users_Guide/tc-gen.rst +++ b/met/docs/Users_Guide/tc-gen.rst @@ -6,7 +6,7 @@ TC-Gen Tool Introduction ____________ -The TC-Gen tool provides verification of tropical cyclone genesis forecasts in ATCF file format. Producing reliable tropical cyclone genesis forecasts is an important metric for global numerical weather prediction models. This tool ingests deterministic model output post-processed by a genesis tracking software (e.g. GFDL vortex tracker) and ATCF format reference dataset(s) (e.g. Best Track analysis and CARQ operational tracks) and outputs categorical counts and statistics. The capability to modify the spatial and temporal tolerances that define a “hit” forecast is included to give users the ability to condition the criteria based on model performance and/or conduct sensitivity analyses. Statistical aspects are outlined in :numref:`tc-gen_stat_aspects` and practical aspects of the TC-Gen tool are described in :numref:`tc-gen_practical_info`. +The TC-Gen tool provides verification of tropical cyclone genesis forecasts in ATCF file format. Producing reliable tropical cyclone genesis forecasts is an important metric for global numerical weather prediction models. This tool ingests deterministic model output post-processed by a genesis tracking software (e.g. GFDL vortex tracker) and ATCF format reference dataset(s) (e.g. Best Track analysis and CARQ operational tracks) and outputs categorical counts and statistics. The capability to modify the spatial and temporal tolerances that define a "hit" forecast is included to give users the ability to condition the criteria based on model performance and/or conduct sensitivity analyses. Statistical aspects are outlined in :numref:`tc-gen_stat_aspects` and practical aspects of the TC-Gen tool are described in :numref:`tc-gen_practical_info`. .. _tc-gen_stat_aspects: @@ -48,7 +48,7 @@ Required arguments for tc_gen 1. The **-genesis path** argument is the path to one or more ATCF or fort.66 (see documentation listed below) files generated by the Geophysical Fluid Dynamics Laboratory (GFDL) Vortex Tracker when run in tcgen mode or an ASCII file list or a top-level directory containing them. The **-genesis** option must be used at least once. The required file format is described in the "Output formats" section of the `GFDL Vortex Tracker users guide. `_ -2. The **-track path** argument is one or more ATCF reference track files or an ASCII file list or top-level directory containing them, with files ending in “.dat”. This tool processes either Best track data from bdeck files, or operational track data (e.g. CARQ) from adeck files, or both. Providing both bdeck and adeck files will result in a richer dataset to match with the **-genesis** files. Both adeck and bdeck data should be provided using the **-track** option. The **-track** option must be used at least once. +2. The **-track path** argument is one or more ATCF reference track files or an ASCII file list or top-level directory containing them, with files ending in ".dat". This tool processes either Best track data from bdeck files, or operational track data (e.g. CARQ) from adeck files, or both. Providing both bdeck and adeck files will result in a richer dataset to match with the **-genesis** files. Both adeck and bdeck data should be provided using the **-track** option. The **-track** option must be used at least once. 3. The **-config** file argument indicates the name of the configuration file to be used. The contents of the configuration file are discussed below. @@ -59,7 +59,7 @@ Optional arguments for tc_gen 5. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -6. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +6. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. The TC-Gen tool implements the following logic: diff --git a/met/docs/Users_Guide/tc-pairs.rst b/met/docs/Users_Guide/tc-pairs.rst index de8ff0f957..f2ce129846 100644 --- a/met/docs/Users_Guide/tc-pairs.rst +++ b/met/docs/Users_Guide/tc-pairs.rst @@ -35,11 +35,11 @@ tc_pairs has required arguments and can accept several optional arguments. Required arguments for tc_pairs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -1. The **-adeck source** argument indicates the adeck TC-Pairs acceptable format data source containing tropical cyclone model forecast (output from tracker) data to be verified. Acceptable data formats are limited to the standard ATCF format and the one column modified ATCF file, generated by running the tracker in genesis mode. It specifies the name of a TC-Pairs acceptable format file or top-level directory containing TC-Pairs acceptable format files ending in “.dat” to be processed. The **-adeck** or **-edeck** option must be used at least once. +1. The **-adeck source** argument indicates the adeck TC-Pairs acceptable format data source containing tropical cyclone model forecast (output from tracker) data to be verified. Acceptable data formats are limited to the standard ATCF format and the one column modified ATCF file, generated by running the tracker in genesis mode. It specifies the name of a TC-Pairs acceptable format file or top-level directory containing TC-Pairs acceptable format files ending in ".dat" to be processed. The **-adeck** or **-edeck** option must be used at least once. -2. The **-edeck source** argument indicates the edeck ATCF format data source containing probabilistic track data to be verified. It specifies the name of an ATCF format file or top-level directory containing ATCF format files ending in “.dat” to be processed. The **-adeck** or **-edeck** option must be used at least once. +2. The **-edeck source** argument indicates the edeck ATCF format data source containing probabilistic track data to be verified. It specifies the name of an ATCF format file or top-level directory containing ATCF format files ending in ".dat" to be processed. The **-adeck** or **-edeck** option must be used at least once. -3. The **-bdeck source** argument indicates the TC-Pairs acceptable format data source containing the tropical cyclone reference dataset to be used for verifying the adeck source. This source is typically the NHC Best Track Analysis, but could be any TC-Pairs acceptable formatted reference. The acceptable data formats for bdecks are the same as those for adecks. This argument specifies the name of a TC-Pairs acceptable format file or top-level directory containing TC-Pairs acceptable format files ending in “.dat” to be processed. +3. The **-bdeck source** argument indicates the TC-Pairs acceptable format data source containing the tropical cyclone reference dataset to be used for verifying the adeck source. This source is typically the NHC Best Track Analysis, but could be any TC-Pairs acceptable formatted reference. The acceptable data formats for bdecks are the same as those for adecks. This argument specifies the name of a TC-Pairs acceptable format file or top-level directory containing TC-Pairs acceptable format files ending in ".dat" to be processed. 4. The **-config file** argument indicates the name of the configuration file to be used. The contents of the configuration file are discussed below. @@ -50,7 +50,7 @@ Optional arguments for tc_pairs 6. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -7. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +7. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. This tool currently only supports the rapid intensification (**RI**) edeck probability type but support for additional edeck probability types will be added in future releases. At least one **-adeck** or **-edeck** option must be specified. The **-adeck, -edeck**, and **-bdeck** options may optionally be followed with **suffix=string** to append that string to all model names found within that data source. This option may be useful when processing track data from two different sources which reuse the same model names. @@ -151,7 +151,7 @@ ____________________ .. code-block:: none - lag_time = [ “06”, “12” ]; + lag_time = [ "06", "12" ]; The **lag_time** field is a comma-separated list of forecast lag times to be used in HH[MMSS] format. For each adeck track identified, a lagged track will be derived for each entry. In the tc_pairs output, the original adeck record will be retained, with the lagged entry listed as the adeck name with "_LAG_HH" appended. diff --git a/met/docs/Users_Guide/tc-rmw.rst b/met/docs/Users_Guide/tc-rmw.rst index efe5273c84..852973b0f1 100644 --- a/met/docs/Users_Guide/tc-rmw.rst +++ b/met/docs/Users_Guide/tc-rmw.rst @@ -44,7 +44,7 @@ Optional arguments for tc_rmw 5. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no logfile. -6. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +6. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. tc_rmw configuration file ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/met/docs/Users_Guide/tc-stat.rst b/met/docs/Users_Guide/tc-stat.rst index c66a6f6894..ee774eee0d 100644 --- a/met/docs/Users_Guide/tc-stat.rst +++ b/met/docs/Users_Guide/tc-stat.rst @@ -104,7 +104,7 @@ Optional arguments for tc_stat 4. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -5. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. +5. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity above 1 will increase the amount of logging. 6. The **-config file** argument indicates the name of the configuration file to be used. The contents of the configuration file are discussed below. @@ -396,13 +396,13 @@ This job produces summary statistics for the column name specified by the **-col "COL_NAME", followed by the summary statistics that are applied; 3. -“SUMMARY”, which is followed by the total, mean (with confidence intervals), standard deviation, minimum value, percentiles (10th, 25th, 50th, 75th, 90th), maximum value, interquartile range, range, sum, time to independence, and frequency of superior performance. +"SUMMARY", which is followed by the total, mean (with confidence intervals), standard deviation, minimum value, percentiles (10th, 25th, 50th, 75th, 90th), maximum value, interquartile range, range, sum, time to independence, and frequency of superior performance. The output columns are shown below in :numref:`table_columnar_output_summary_tc_stat` The **-by** option can also be used one or more times to make this job more powerful. Rather than running the specified job once, it will be run once for each unique combination of the entries found in the column(s) specified with the **-by** option. .. _table_columnar_output_summary_tc_stat: -.. list-table:: Columnar output of “summary” job output from the TC-Stat tool. +.. list-table:: Columnar output of "summary" job output from the TC-Stat tool. :widths: auto :header-rows: 2 diff --git a/met/docs/Users_Guide/wavelet-stat.rst b/met/docs/Users_Guide/wavelet-stat.rst index 19db97d1ed..e449a513e3 100644 --- a/met/docs/Users_Guide/wavelet-stat.rst +++ b/met/docs/Users_Guide/wavelet-stat.rst @@ -32,7 +32,7 @@ The Intensity Scale approach can be summarized in the following 5 steps: 1. For each threshold, the forecast and observation fields are transformed into binary fields: where the grid-point precipitation value meets the threshold criteria it is assigned 1, where the threshold criteria are not met it is assigned 0. This can also be done with no thresholds indicated at all and in that case the grid-point values are not transformed to binary fields and instead the raw data is used as is for statistics. :numref:`wavelet-stat_NIMROD_3h_fcst` illustrates an example of a forecast and observation fields, and their corresponding binary fields for a threshold of 1mm/h. This case shows an intense storm of the scale of 160 km displaced almost its entire length. The displacement error is clearly visible from the binary field difference and the contingency table image obtained for the same threshold :numref:`contingency_table_counts`. -2. The binary forecast and observation fields obtained from the thresholding are then decomposed into the sum of components on different scales, by using a 2D Haar wavelet filter (:numref:`wavelet-stat_NIMROD_diff`). Note that the scale components are fields, and their sum adds up to the original binary field. For a forecast defined over square domain of **2ⁿ x 2ⁿ** grid-points, the scale components are **n+1: n** mother wavelet components + the largest father wavelet (or scale-function) component. The **n** mother wavelet components have resolution equal to **1, 2, 4, ...** :math:`\mathbf{2^{n-1}}` grid-points. The largest father wavelet component is a constant field over the **2ⁿ x 2ⁿ** grid-point domain with value equal to the field mean. +2. The binary forecast and observation fields obtained from the thresholding are then decomposed into the sum of components on different scales, by using a 2D Haar wavelet filter (:numref:`wavelet-stat_NIMROD_diff`). Note that the scale components are fields, and their sum adds up to the original binary field. For a forecast defined over square domain of :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} grid-points, the scale components are **n+1: n** mother wavelet components + the largest father wavelet (or scale-function) component. The **n** mother wavelet components have resolution equal to **1, 2, 4, ...** :math:`\mathbf{2^{n-1}}` grid-points. The largest father wavelet component is a constant field over the :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} grid-point domain with value equal to the field mean. **Note** that the wavelet transform is a linear operator: this implies that the difference of the spatial scale components of the binary forecast and observation fields (:numref:`wavelet-stat_NIMROD_diff`) are equal to the spatial scale components of the difference of the binary forecast and observation fields (:numref:`wavelet-stat_NIMROD_binary_fcst_and_obs`), and these scale components also add up to the original binary field difference (:numref:`wavelet-stat_NIMROD_3h_fcst`). The intensity-scale technique considers thus the spatial scale of the error. For the case illustrated (:numref:`wavelet-stat_NIMROD_3h_fcst` and :numref:`wavelet-stat_NIMROD_binary_fcst_and_obs`) note the large error associated at the scale of 160 km, due the storm, 160km displaced almost its entire length. @@ -59,14 +59,14 @@ The Intensity-Scale (IS) skill score evaluates the forecast skill as a function - - Total * - - - o = 1 (e.g., “Yes”) - - o = 0 (e.g., “No”) + - o = 1 (e.g., "Yes") + - o = 0 (e.g., "No") - - * - f = 1 (e.g., “Yes”) + * - f = 1 (e.g., "Yes") - Hits **= a** - False Alarms **= b** - **a+b** - * - f = 0 (e.g., “No”) + * - f = 0 (e.g., "No") - Misses **= c** - Correct rejections **= d** - **c+d** @@ -128,18 +128,18 @@ Note that the energy squared of the observation binary field is identical to the The spatial domain constraints ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The Intensity-Scale technique is constrained by the fact that orthogonal wavelets (discrete wavelet transforms) are usually performed dyadic domains, square domains of **2ⁿ x 2ⁿ** grid-points. The Wavelet-Stat tool handles this issue based on settings in the configuration file by defining tiles of dimensions **2ⁿ x 2ⁿ** over the input domain in the following ways: +The Intensity-Scale technique is constrained by the fact that orthogonal wavelets (discrete wavelet transforms) are usually performed dyadic domains, square domains of :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} grid-points. The Wavelet-Stat tool handles this issue based on settings in the configuration file by defining tiles of dimensions :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} over the input domain in the following ways: -1. User-Defined Tiling: The user may define one or more tiles of size **2ⁿ x 2ⁿ** over their domain to be applied. This is done by selecting the grid coordinates for the lower-left corner of the tile(s) and the tile dimension to be used. If the user specifies more than one tile, the Intensity-Scale method will be applied to each tile separately. At the end, the results will automatically be aggregated across all the tiles and written out with the results for each of the individual tiles. Users are encouraged to select tiles which consist entirely of valid data. +1. User-Defined Tiling: The user may define one or more tiles of size :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} over their domain to be applied. This is done by selecting the grid coordinates for the lower-left corner of the tile(s) and the tile dimension to be used. If the user specifies more than one tile, the Intensity-Scale method will be applied to each tile separately. At the end, the results will automatically be aggregated across all the tiles and written out with the results for each of the individual tiles. Users are encouraged to select tiles which consist entirely of valid data. -2. Automated Tiling: This tiling method is essentially the same as the user-defined tiling method listed above except that the tool automatically selects the location and size of the tile(s) to be applied. It figures out the maximum tile of dimension **2ⁿ x 2ⁿ** that fits within the domain and places the tile at the center of the domain. For domains that are very elongated in one direction, it defines as many of these tiles as possible that fit within the domain. +2. Automated Tiling: This tiling method is essentially the same as the user-defined tiling method listed above except that the tool automatically selects the location and size of the tile(s) to be applied. It figures out the maximum tile of dimension :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} that fits within the domain and places the tile at the center of the domain. For domains that are very elongated in one direction, it defines as many of these tiles as possible that fit within the domain. -3. Padding: If the domain size is only slightly smaller than **2ⁿ x 2ⁿ**, for certain variables (e.g. precipitation), it is advisable to expand the domain out to **2ⁿ x 2ⁿ** grid-points by adding extra rows and/or columns of fill data. For precipitation variables, a fill value of zero is used. For continuous variables, such as temperature, the fill value is defined as the mean of the valid data in the rest of the field. A drawback to the padding method is the introduction of artificial data into the original field. Padding should only be used when a very small number of rows and/or columns need to be added. +3. Padding: If the domain size is only slightly smaller than :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n}, for certain variables (e.g. precipitation), it is advisable to expand the domain out to :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} grid-points by adding extra rows and/or columns of fill data. For precipitation variables, a fill value of zero is used. For continuous variables, such as temperature, the fill value is defined as the mean of the valid data in the rest of the field. A drawback to the padding method is the introduction of artificial data into the original field. Padding should only be used when a very small number of rows and/or columns need to be added. Aggregation of statistics on multiple cases ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The Stat-Analysis tool aggregates the intensity scale technique results. Since the results are scale-dependent, it is sensible to aggregate results from multiple model runs (e.g. daily runs for a season) on the same spatial domain, so that the scale components for each singular case will be the same number, and the domain, if not a square domain of **2ⁿ x 2ⁿ** grid-points, will be treated in the same fashion. Similarly, the intensity thresholds for each run should all be the same. +The Stat-Analysis tool aggregates the intensity scale technique results. Since the results are scale-dependent, it is sensible to aggregate results from multiple model runs (e.g. daily runs for a season) on the same spatial domain, so that the scale components for each singular case will be the same number, and the domain, if not a square domain of :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} grid-points, will be treated in the same fashion. Similarly, the intensity thresholds for each run should all be the same. The MSE and forecast and observation squared energy for each scale and thresholds are aggregated simply with a weighted average, where weights are proportional to the number of grid-points used in each single run to evaluate the statistics. If the same domain is always used (and it should) the weights result all the same, and the weighted averaging is a simple mean. For each threshold, the aggregated Br is equal to the aggregated squared energy of the binary observation field, and the aggregated FBI is obtained as the ratio of the aggregated squared energies of the forecast and observation binary fields. From aggregated Br and FBI, the MSErandom for the aggregated runs can be evaluated using the same formula as for the single run. Finally, the Intensity-Scale Skill Score is evaluated by using the aggregated statistics within the same formula used for the single case. @@ -182,9 +182,9 @@ Optional arguments for wavelet_stat 5. The **-log file** option directs output and errors to the specified log file. All messages will be written to that file as well as standard out and error. Thus, users can save the messages without having to redirect the output on the command line. The default behavior is no log file. -6. The **-v level** option indicates the desired level of verbosity. The contents of “level” will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. +6. The **-v level** option indicates the desired level of verbosity. The contents of "level" will override the default setting of 2. Setting the verbosity to 0 will make the tool run with no log messages, while increasing the verbosity will increase the amount of logging. -7. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of “level” will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. +7. The **-compress level** option indicates the desired level of compression (deflate level) for NetCDF variables. The valid level is between 0 and 9. The value of "level" will override the default setting of 0 from the configuration file or the environment variable MET_NC_COMPRESS. Setting the compression level to 0 will make no compression for the NetCDF output. Lower number is for fast compression and higher number is for better compression. An example of the wavelet_stat calling sequence is listed below: @@ -217,7 +217,7 @@ _______________________ mask_missing_flag = NONE; met_data_dir = "MET_BASE"; ps_plot_flag = TRUE; - fcst_raw_plot = { color_table = "MET_BASE/colortables/met_default.ctable”; + fcst_raw_plot = { color_table = "MET_BASE/colortables/met_default.ctable"; plot_min = 0.0; plot_max = 0.0; } obs_raw_plot = { ... } wvlt_plot = { ... } @@ -260,7 +260,7 @@ The **grid_decomp_flag** variable specifies how tiling should be performed: • **TILE** indicates that the user-defined tiles should be applied. -• **PAD** indicated that the data should be padded out to the nearest dimension of **2ⁿ x 2ⁿ** +• **PAD** indicated that the data should be padded out to the nearest dimension of :math:`\mathbf{2^n} **x** :math:`\mathbf{2^n} The **width** and **location** variables allow users to manually define the tiles of dimension they would like to apply. The x_ll and y_ll variables specify the location of one or more lower-left tile grid (x, y) points. @@ -477,11 +477,11 @@ The dimensions and variables included in the wavelet_stat NetCDF files are descr * - NetCDF Dimension - Description * - x - - Dimension of the tile which equals **2ⁿ** + - Dimension of the tile which equals :math:`\mathbf{2^n}` * - y - - Dimension of the tile which equals **2ⁿ** + - Dimension of the tile which equals :math:`\mathbf{2^n}` * - scale - - Dimension for the number of scales. This is set to **n+2**, where **2ⁿ** is the tile dimension. The 2 extra scales are for the binary image and the wavelet averaged over the whole tile. + - Dimension for the number of scales. This is set to **n+2**, where :math:`\mathbf{2^n}` is the tile dimension. The 2 extra scales are for the binary image and the wavelet averaged over the whole tile. * - tile - Dimension for the number of tiles used @@ -499,19 +499,19 @@ The dimensions and variables included in the wavelet_stat NetCDF files are descr - Description * - FCST_FIELD_LEVEL_RAW - tile, x, y - - Raw values for the forecast field specified by “FIELD_LEVEL” + - Raw values for the forecast field specified by "FIELD_LEVEL" * - OBS_FIELD_LEVEL_RAW - tile, x, y - - Raw values for the observation field specified by “FIELD_LEVEL” + - Raw values for the observation field specified by "FIELD_LEVEL" * - DIFF_FIELD_LEVEL_RAW - tile, x, y - - Raw values for the difference field (**f-o**) specified by “FIELD_LEVEL” + - Raw values for the difference field (**f-o**) specified by "FIELD_LEVEL" * - FCST_FIELD_LEVEL_THRESH - tile, scale, x, y - - Wavelet scale-decomposition of the forecast field specified by “FIELD_LEVEL_THRESH” + - Wavelet scale-decomposition of the forecast field specified by "FIELD_LEVEL_THRESH" * - OBS_FIELD_LEVEL_THRESH - tile, scale, x, y - - Wavelet scale-decomposition of the observation field specified by “FIELD_LEVEL_THRESH” + - Wavelet scale-decomposition of the observation field specified by "FIELD_LEVEL_THRESH" Lastly, the **Wavelet-Stat** tool creates a PostScript plot summarizing the scale-decomposition approach used in the verification. The PostScript plot is generated using internal libraries and does not depend on an external plotting package. The generation of this PostScript output can be disabled using the **ps_plot_flag** configuration file option. diff --git a/met/docs/conf.py b/met/docs/conf.py index 61d78fba23..16bb9bcd99 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-beta1' +version = '10.1.0-beta2' verinfo = version release = f'{version}' release_year = '2021' -release_date = f'{release_year}-06-13' +release_date = f'{release_year}-07-20' copyright = f'{release_year}, {author}' # -- General configuration --------------------------------------------------- @@ -34,6 +34,57 @@ # ones. extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx'] +# settings for ReadTheDocs PDF creation +latex_engine = 'pdflatex' +latex_theme = 'manual' +latex_logo = os.path.join('_static','met_logo_2019_09.png') +latex_show_pagerefs = True +latex_master_doc = 'Users_Guide/index' + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + 'papersize': 'letterpaper', + 'releasename':"{version}", + 'fncychap': '\\usepackage{fncychap}', + 'fontpkg': '\\usepackage{amsmath,amsfonts,amssymb,amsthm}', + 'inputenc': '\\usepackage[utf8]{inputenc}', + 'fontenc': '\\usepackage[LGR,T1]{fontenc}', + + 'figure_align':'htbp', + 'pointsize': '11pt', + + 'preamble': r''' + \usepackage{charter} + \usepackage[defaultsans]{lato} + \usepackage{inconsolata} + \setcounter{secnumdepth}{4} + \setcounter{tocdepth}{4} + ''', + + 'sphinxsetup': \ + 'hmargin={0.7in,0.7in}, vmargin={1in,1in}, \ + verbatimwithframe=true, \ + TitleColor={rgb}{0,0,0}, \ + HeaderFamily=\\rmfamily\\bfseries, \ + InnerLinkColor={rgb}{0,0,1}, \ + OuterLinkColor={rgb}{0,0,1}', + 'maketitle': '\\sphinxmaketitle', +# 'tableofcontents': ' ', + 'printindex': ' ' +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (latex_master_doc, + 'users_guide.tex', + 'MET User\'s Guide', + ' ', + 'manual') +] + # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] From 3e33a4ec46e0a867cd4abb49d1e506b8cfe89de6 Mon Sep 17 00:00:00 2001 From: johnhg Date: Fri, 23 Jul 2021 10:45:04 -0600 Subject: [PATCH 084/200] Feature 1853 rps doc (#1861) * Per #1853, adding RPS docs from Eric. * Per #1853, work in progress getting the formatting correct. * Per #1853, work in progress getting the formatting correct. * Per #1853, work in progress getting the formatting correct. * Per #1853, work in progress getting the formatting correct. * Per #1853, adding a manual page break after the ROC image to get it to stay in the right spot. * Per #1853, backing out last change which didn't make the ROC image stay in the right spot. --- met/docs/Users_Guide/appendixC.rst | 18 ++++++++++++++++++ met/docs/Users_Guide/refs.rst | 29 ++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 082dcc208c..8f508f770a 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -939,6 +939,24 @@ The area under the curve can be estimated in a variety of ways. In MET, the simp MET verification measures for ensemble forecasts ________________________________________________ +RPS +~~~ + +Called "RPS" in RPS output :numref:`table_ES_header_info_es_out_ECNT` + +While the above probabilistic verification measures utilize dichotomous observations, the Ranked Probability Score (RPS, :ref:`Epstein, 1969 `, :ref:`Murphy, 1969 `) is the only probabilistic verification measure for discrete multiple-category events available in MET. It is assumed that the categories are ordinal as nominal categorical variables can be collapsed into sequences of binary predictands, which can in turn be evaluated with the above measures for dichotomous variables (:ref:`Wilks, 2011 `). The RPS is the multi-category extension of the Brier score (:ref:`Tödter and Ahrens, 2012`), and is a proper score (:ref:`Mason, 2008`). + +Let :math:`\text{J}` be the number of categories, then both the forecast, :math:`\text{f} = (f_1,…,f_J)`, and observation, :math:`\text{o} = (o_1,…,o_J)`, are length-:math:`\text{J}` vectors, where the components of :math:`\text{f}` include the probabilities forecast for each category :math:`\text{1,…,J}` and :math:`\text{o}` contains 1 in the category that is realized and zero everywhere else. The cumulative forecasts, :math:`F_m`, and observations, :math:`O_m`, are defined to be: + +:math:`F_m = \sum_{j=1}^m (f_j)` and :math:`O_m = \sum_{j=1}^m (o_j), m = 1,…,J`. + + +To clarify, :math:`F_1 = f_1` is the first component of :math:`F_m`, :math:`F_2 = f_1+f_2`, etc., and :math:`F_J = 1`. Similarly, if :math:`o_j = 1` and :math:`i < j`, then :math:`O_i = 0` and when :math:`i≥j`, :math:`O_i = 1`, and of course, :math:`O_J = 1`. Finally, the RPS is defined to be: + +.. math:: \text{RPS} = \sum_{m=1}^J (F_m - O_m)^2 = \sum_{m=1}^J BS_m, + +where :math:`BS_m` is the Brier score for the m-th category (:ref:`Tödter and Ahrens, 2012`). Subsequently, the RPS lends itself to a decomposition into reliability, resolution and uncertainty components, noting that each component is aggregated over the different categories; these are written to the columns named "RPS_REL", "RPS_RES" and "RPS_UNC" in RPS output :numref:`table_ES_header_info_es_out_ECNT`. + CRPS ~~~~ diff --git a/met/docs/Users_Guide/refs.rst b/met/docs/Users_Guide/refs.rst index a58ddf8dda..118258f15c 100644 --- a/met/docs/Users_Guide/refs.rst +++ b/met/docs/Users_Guide/refs.rst @@ -103,7 +103,13 @@ References | Efron, B. 2007: Correlation and large-scale significance testing. *Journal* | of the American Statistical Association,* 102(477), 93-103. -| +| + +.. _Epstein-1969: + +| Epstein, E. S., 1969: A scoring system for probability forecasts of ranked categories. +| *J. Appl. Meteor.*, 8, 985–987, 10.1175/1520-0450(1969)008<0985:ASSFPF>2.0.CO;2. +| .. _Gilleland-2010: @@ -158,6 +164,13 @@ References | 132, 1891-1895. | +.. _Mason-2008: + +| Mason, S. J., 2008: Understanding forecast verification statistics. +| *Meteor. Appl.*, 15, 31–40, doi: 10.1002/met.51. +| + + .. _Mittermaier-2014: | Mittermaier, M., 2014: A strategy for verifying near-convection-resolving @@ -170,6 +183,13 @@ References | *Theory of Statistics*, McGraw-Hill, 299-338. | +.. _Murphy-1969: + +| Murphy, A.H., 1969: On the ranked probability score. *Journal of Applied* +| *Meteorology and Climatology*, 8 (6), 988 – 989, +| doi: 10.1175/1520-0450(1969)008<0988:OTPS>2.0.CO;2. +| + .. _Murphy-1987: | Murphy, A.H., and R.L. Winkler, 1987: A general framework for forecast @@ -224,6 +244,13 @@ References | *Meteorological Applications* 15, 41-50. | +.. _Todter-2012: + +| Tödter, J. and B. Ahrens, 2012: Generalization of the Ignorance Score: +| Continuous ranked version and its decomposition. *Mon. Wea. Rev.*, +| 140 (6), 2005 – 2017, doi: 10.1175/MWR-D-11-00266.1. +| + .. _Weniger-2016: | Weniger, M., F. Kapp, and P. Friederichs, 2016: Spatial Verification Using From 0a66ca115f8e219d8862e36c25b0cc0e250920bf Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 23 Jul 2021 17:44:33 -0600 Subject: [PATCH 085/200] #1855 Removed break after return (SobarQube) --- met/src/basic/vx_config/my_config_scanner.cc | 26 ++++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/met/src/basic/vx_config/my_config_scanner.cc b/met/src/basic/vx_config/my_config_scanner.cc index 1acae0582b..a9d8ac7fda 100644 --- a/met/src/basic/vx_config/my_config_scanner.cc +++ b/met/src/basic/vx_config/my_config_scanner.cc @@ -253,27 +253,27 @@ switch ( c ) { // single character tokens // - case '[': { do_single_char_token(lexeme[0]); is_lhs = false; dict_stack->push_array(); return ( token(lexeme[0]) ); } break; - case '{': { do_single_char_token(lexeme[0]); is_lhs = true; dict_stack->push(); return ( token(lexeme[0]) ); } break; + case '[': { do_single_char_token(lexeme[0]); is_lhs = false; dict_stack->push_array(); return ( token(lexeme[0]) ); } + case '{': { do_single_char_token(lexeme[0]); is_lhs = true; dict_stack->push(); return ( token(lexeme[0]) ); } - case ']': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } break; - case '}': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } break; + case ']': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } + case '}': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } - case '(': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } break; - case ')': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } break; + case '(': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } + case ')': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } - case '+': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } break; + case '+': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } - case '-': { if ( ! need_number ) { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } } break; + case '-': { if ( ! need_number ) { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } } - case '*': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } break; - case '^': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } break; + case '*': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } + case '^': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } - // case '=': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } break; + // case '=': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } - case ';': { do_single_char_token(lexeme[0]); is_lhs = true; return ( token( ';' ) ); } break; - case ',': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } break; + case ';': { do_single_char_token(lexeme[0]); is_lhs = true; return ( token( ';' ) ); } + case ',': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } case '\"': { do_quoted_string(); return ( token ( QUOTED_STRING ) ); } From f1a2d3fc7ca5d9704298c63e242b0a7f9a55d8ef Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 23 Jul 2021 17:45:32 -0600 Subject: [PATCH 086/200] #1855 Removed break after exit --- met/src/basic/vx_config/calculator.cc | 1 - met/src/basic/vx_config/config_util.cc | 12 ------------ met/src/basic/vx_config/icode.cc | 3 --- met/src/basic/vx_config/threshold.cc | 2 -- met/src/basic/vx_math/affine.cc | 2 -- met/src/basic/vx_math/so3.cc | 1 - .../core/wavelet_stat/wavelet_stat_conf_info.cc | 3 --- 7 files changed, 24 deletions(-) diff --git a/met/src/basic/vx_config/calculator.cc b/met/src/basic/vx_config/calculator.cc index bd7813f48f..0ce9d6cb6b 100644 --- a/met/src/basic/vx_config/calculator.cc +++ b/met/src/basic/vx_config/calculator.cc @@ -671,7 +671,6 @@ while ( pos < (v.length()) ) { << celltype_to_string(cell.type) << "\"\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/basic/vx_config/config_util.cc b/met/src/basic/vx_config/config_util.cc index c55fd819ae..64720d41de 100644 --- a/met/src/basic/vx_config/config_util.cc +++ b/met/src/basic/vx_config/config_util.cc @@ -2450,7 +2450,6 @@ ConcatString fieldtype_to_string(FieldType type) { mlog << Error << "\nfieldtype_to_string() -> " << "Unexpected FieldType value of " << type << ".\n\n"; exit(1); - break; } return(s); @@ -2520,7 +2519,6 @@ ConcatString setlogic_to_string(SetLogic type) { mlog << Error << "\nsetlogic_to_string() -> " << "Unexpected SetLogic value of " << type << ".\n\n"; exit(1); - break; } return(s); @@ -2541,7 +2539,6 @@ ConcatString setlogic_to_abbr(SetLogic type) { mlog << Error << "\nsetlogic_to_abbr() -> " << "Unexpected SetLogic value of " << type << ".\n\n"; exit(1); - break; } return(s); @@ -2562,7 +2559,6 @@ ConcatString setlogic_to_symbol(SetLogic type) { mlog << Error << "\nsetlogic_to_symbol() -> " << "Unexpected SetLogic value of " << type << ".\n\n"; exit(1); - break; } return(s); @@ -2642,7 +2638,6 @@ ConcatString tracktype_to_string(TrackType type) { mlog << Error << "\ntracktype_to_string() -> " << "Unexpected TrackType value of " << type << ".\n\n"; exit(1); - break; } return(s); @@ -2698,7 +2693,6 @@ ConcatString interp12type_to_string(Interp12Type type) { mlog << Error << "\ninterp12type_to_string() -> " << "Unexpected Interp12Type value of " << type << ".\n\n"; exit(1); - break; } return(s); @@ -2738,7 +2732,6 @@ ConcatString mergetype_to_string(MergeType type) { mlog << Error << "\nmergetype_to_string() -> " << "Unexpected MergeType value of " << type << ".\n\n"; exit(1); - break; } return(s); @@ -2765,7 +2758,6 @@ ConcatString obssummary_to_string(ObsSummary type, int perc_val) { mlog << Error << "\nobssummary_to_string() -> " << "Unexpected ObsSummary value of " << type << ".\n\n"; exit(1); - break; } return(s); @@ -2805,7 +2797,6 @@ ConcatString matchtype_to_string(MatchType type) { mlog << Error << "\nmatchtype_to_string() -> " << "Unexpected MatchType value of " << type << ".\n\n"; exit(1); - break; } return(s); @@ -2873,7 +2864,6 @@ ConcatString disttype_to_string(DistType type) { mlog << Error << "\ndisttype_to_string() -> " << "Unexpected DistType value of " << type << ".\n\n"; exit(1); - break; } return(s); @@ -2915,7 +2905,6 @@ ConcatString griddecomptype_to_string(GridDecompType type) { mlog << Error << "\ngriddecomptype_to_string() -> " << "Unexpected GridDecompType value of " << type << ".\n\n"; exit(1); - break; } return(s); @@ -2939,7 +2928,6 @@ ConcatString wavelettype_to_string(WaveletType type) { mlog << Error << "\nwavlettype_to_string() -> " << "Unexpected WaveletType value of " << type << ".\n\n"; exit(1); - break; } return(s); diff --git a/met/src/basic/vx_config/icode.cc b/met/src/basic/vx_config/icode.cc index a45736daf1..fda6db8f01 100644 --- a/met/src/basic/vx_config/icode.cc +++ b/met/src/basic/vx_config/icode.cc @@ -262,7 +262,6 @@ switch ( type ) { default: cerr << "\n\n IcodeCell::as_double() const -> bad type ... \"" << celltype_to_string(type) << "\"\n\n"; exit ( 1 ); - break; } // switch @@ -289,7 +288,6 @@ switch ( type ) { default: cerr << "\n\n IcodeCell::as_int() const -> bad type ... \"" << celltype_to_string(type) << "\"\n\n"; exit ( 1 ); - break; } // switch @@ -392,7 +390,6 @@ switch ( type ) { default: cerr << "\n\n IcodeCell::dump() -> unrecognized type ... \"" << celltype_to_string(type) << "\"\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/basic/vx_config/threshold.cc b/met/src/basic/vx_config/threshold.cc index bb1dfaa49a..cf3e9dd26a 100644 --- a/met/src/basic/vx_config/threshold.cc +++ b/met/src/basic/vx_config/threshold.cc @@ -857,7 +857,6 @@ switch ( op ) { mlog << Error << "\nSimple_Node::check(double, double, double) const -> " << "bad op ... " << op << "\n\n"; exit ( 1 ); - break; } // switch @@ -1202,7 +1201,6 @@ if ( Ptype == perc_thresh_climo_dist ) { << "threshold to a probability!\n\n"; exit ( 1 ); - break; } // switch } diff --git a/met/src/basic/vx_math/affine.cc b/met/src/basic/vx_math/affine.cc index b7094024e1..974eb32aa4 100644 --- a/met/src/basic/vx_math/affine.cc +++ b/met/src/basic/vx_math/affine.cc @@ -1144,7 +1144,6 @@ switch ( g ) { mlog << Error << "\nConformalAffine::set() -> " << "bad gravity ... " << viewgravity_to_string(g) << "\n\n"; exit ( 1 ); - break; } // switch @@ -1421,7 +1420,6 @@ switch ( g ) { << "\n\n viewgravity_to_uv() -> bad gravity ... " << viewgravity_to_string(g) << "\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/basic/vx_math/so3.cc b/met/src/basic/vx_math/so3.cc index 41e3dbc82b..3f3c93ab73 100644 --- a/met/src/basic/vx_math/so3.cc +++ b/met/src/basic/vx_math/so3.cc @@ -780,7 +780,6 @@ switch ( k ) { default: cerr << "\n\n SO3::operator()(int, int) const -> range check error (2)\n\n"; exit ( 1 ); - break; } diff --git a/met/src/tools/core/wavelet_stat/wavelet_stat_conf_info.cc b/met/src/tools/core/wavelet_stat/wavelet_stat_conf_info.cc index 103f203280..b8a8a8c774 100644 --- a/met/src/tools/core/wavelet_stat/wavelet_stat_conf_info.cc +++ b/met/src/tools/core/wavelet_stat/wavelet_stat_conf_info.cc @@ -342,7 +342,6 @@ void WaveletStatConfInfo::process_config(GrdFileType ftype, mlog << Error << "\nWaveletStatConfInfo::process_config() -> " << "Unsupported wavelet type value of " << wvlt_type << ".\n\n"; exit(1); - break; } // Conf: wavelet.member @@ -389,7 +388,6 @@ void WaveletStatConfInfo::process_config(GrdFileType ftype, mlog << Error << "\nWaveletStatConfInfo::process_config() -> " << "Unsupported wavelet type value of " << wvlt_type << ".\n\n"; exit(1); - break; } // Initialize the requested wavelet @@ -569,7 +567,6 @@ void WaveletStatConfInfo::process_tiles(const Grid &grid) { << "Unsupported grid decomposition type of " << grid_decomp_flag << ".\n\n"; exit(1); - break; } // end switch // Compute n_scale based on tile_dim From f60c0527ac2ebef71206585c700a7f6799657204 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 23 Jul 2021 17:47:04 -0600 Subject: [PATCH 087/200] 1855 Added return at MetNcPointObsOut::write_to_netcdf --- met/src/libcode/vx_nc_obs/nc_point_obs_out.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/met/src/libcode/vx_nc_obs/nc_point_obs_out.cc b/met/src/libcode/vx_nc_obs/nc_point_obs_out.cc index b758df0093..29e204672f 100644 --- a/met/src/libcode/vx_nc_obs/nc_point_obs_out.cc +++ b/met/src/libcode/vx_nc_obs/nc_point_obs_out.cc @@ -602,6 +602,7 @@ bool MetNcPointObsOut::write_to_netcdf(StringArray obs_names, StringArray obs_un << "variable names are not added because of empty names\n\n"; } else mlog << Debug(7) << method_name << "use_var_id is false\n"; + return true; } //////////////////////////////////////////////////////////////////////// From c5b1610c09d585174b2da32d417a8fe07aaa5cb9 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 23 Jul 2021 17:48:09 -0600 Subject: [PATCH 088/200] #1855 Avoid releasing memory twice --- met/src/tools/dev_utils/insitu_nc_file.cc | 48 +++++++++++------------ 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/met/src/tools/dev_utils/insitu_nc_file.cc b/met/src/tools/dev_utils/insitu_nc_file.cc index 753f44204c..bdb88f5813 100644 --- a/met/src/tools/dev_utils/insitu_nc_file.cc +++ b/met/src/tools/dev_utils/insitu_nc_file.cc @@ -1,5 +1,3 @@ - - // *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* // ** Copyright UCAR (c) 1992 - 2021 // ** University Corporation for Atmospheric Research (UCAR) @@ -100,7 +98,7 @@ void InsituNcFile::close() // Reclaim the space used for the variables - delete [] _aircraftId; + if (_aircraftId) delete [] _aircraftId; delete [] _timeObs; delete [] _latitude; delete [] _longitude; @@ -150,7 +148,7 @@ bool InsituNcFile::open(const char * filename) if (IS_INVALID_NC(num_recs_dim)) { mlog << Error << "\n" << method_name << " -> " - << "recNum dimension not found in file\n"; + << "recNum dimension not found in file\n"; return false; } @@ -166,7 +164,7 @@ bool InsituNcFile::open(const char * filename) if (IS_INVALID_NC(aircraft_id_len_dim)) { mlog << Error << "\n" << method_name << " -> " - << "aircraftIdLen dimension not found in file\n"; + << "aircraftIdLen dimension not found in file\n"; return false; } @@ -177,7 +175,7 @@ bool InsituNcFile::open(const char * filename) if (IS_INVALID_NC(aircraft_id_var)) { mlog << Error << "\n" << method_name << " -> " - << "aircraftId variable not found in file\n"; + << "aircraftId variable not found in file\n"; return false; } @@ -187,7 +185,7 @@ bool InsituNcFile::open(const char * filename) if (!get_nc_data(&aircraft_id_var, aircraft_id)) { mlog << Error << "\n" << method_name << " -> " - << "error retrieving aircraftId values from file\n"; + << "error retrieving aircraftId values from file\n"; if(aircraft_id) delete[] aircraft_id; return false; } @@ -197,7 +195,7 @@ bool InsituNcFile::open(const char * filename) for (int i = 0; i < _numRecords; ++i) _aircraftId[i] = &aircraft_id[i * aircraft_id_len]; - if(aircraft_id) delete[] aircraft_id; + if(aircraft_id) { delete[] aircraft_id; aircraft_id = 0; } // timeObs @@ -205,7 +203,7 @@ bool InsituNcFile::open(const char * filename) if (IS_INVALID_NC(time_obs_var)) { mlog << Error << "\n" << method_name << " -> " - << "timeObs variable not found in file\n"; + << "timeObs variable not found in file\n"; return false; } @@ -216,7 +214,7 @@ bool InsituNcFile::open(const char * filename) if (!get_nc_data(&time_obs_var, _timeObs)) { mlog << Error << "\n" << method_name << " -> " - << "error retrieving timeObs variable from file\n"; + << "error retrieving timeObs variable from file\n"; return false; } @@ -227,7 +225,7 @@ bool InsituNcFile::open(const char * filename) if (IS_INVALID_NC(latitude_var)) { mlog << Error << "\n" << method_name << " -> " - << "latitude variable not found in file\n"; + << "latitude variable not found in file\n"; return false; } @@ -237,7 +235,7 @@ bool InsituNcFile::open(const char * filename) if (!get_nc_data(&latitude_var, _latitude, _numRecords)) { mlog << Error << "\n" << method_name << " -> " - << "error retrieving latitude values from file\n"; + << "error retrieving latitude values from file\n"; return false; } @@ -248,7 +246,7 @@ bool InsituNcFile::open(const char * filename) if (IS_INVALID_NC(longitude_var)) { mlog << Error << "\n" << method_name << " -> " - << "longitude variable not found in file\n"; + << "longitude variable not found in file\n"; return false; } @@ -258,7 +256,7 @@ bool InsituNcFile::open(const char * filename) if (!get_nc_data(&longitude_var, _longitude, _numRecords)) { mlog << Error << "\n" << method_name << " -> " - << "error retrieving longitude values from file\n"; + << "error retrieving longitude values from file\n"; return false; } @@ -269,7 +267,7 @@ bool InsituNcFile::open(const char * filename) if (IS_INVALID_NC(altitude_var)) { mlog << Error << "\n" << method_name << " -> " - << "altitude variable not found in file\n"; + << "altitude variable not found in file\n"; return false; } @@ -279,7 +277,7 @@ bool InsituNcFile::open(const char * filename) if (!get_nc_data(&altitude_var, _altitude, _numRecords)) { mlog << Error << "\n" << method_name << " -> " - << "retrieving altitude values from file\n"; + << "retrieving altitude values from file\n"; return false; } @@ -290,7 +288,7 @@ bool InsituNcFile::open(const char * filename) if (IS_INVALID_NC(qc_confidence_var)) { mlog << Error << "\n" << method_name << " -> " - << "QCconfidence variable not found in file\n"; + << "QCconfidence variable not found in file\n"; return false; } @@ -300,7 +298,7 @@ bool InsituNcFile::open(const char * filename) if (!get_nc_data(&qc_confidence_var, _QCconfidence, _numRecords)) { mlog << Error << "\n" << method_name << " -> " - << "error retrieving QCconfidence values from file\n"; + << "error retrieving QCconfidence values from file\n"; return false; } @@ -311,7 +309,7 @@ bool InsituNcFile::open(const char * filename) if (IS_INVALID_NC(med_edr_var)) { mlog << Error << "\n" << method_name << " -> " - << "medEDR variable not found in file\n"; + << "medEDR variable not found in file\n"; return false; } @@ -321,7 +319,7 @@ bool InsituNcFile::open(const char * filename) if (!get_nc_data(&med_edr_var, _medEDR, _numRecords)) { mlog << Error << "\n" << method_name << " -> " - << "error retrieving medEDR values from file\n"; + << "error retrieving medEDR values from file\n"; return false; } @@ -332,7 +330,7 @@ bool InsituNcFile::open(const char * filename) if (IS_INVALID_NC(max_edr_var)) { mlog << Error << "\n" << method_name << " -> " - << "maxEDR variable not found in file\n"; + << "maxEDR variable not found in file\n"; return false; } @@ -342,7 +340,7 @@ bool InsituNcFile::open(const char * filename) if (!get_nc_data(&max_edr_var, _maxEDR, _numRecords)) { mlog << Error << "\n" << method_name << " -> " - << "error retrieving maxEDR values from file\n"; + << "error retrieving maxEDR values from file\n"; return false; } @@ -355,9 +353,9 @@ bool InsituNcFile::open(const char * filename) bool InsituNcFile::getNextRecord(string &aircraftId, time_t &timeObs, - double &latitude, double &longitude, - double &altitude, double &QCconfidence, - double &medEDR, double &maxEDR) + double &latitude, double &longitude, + double &altitude, double &QCconfidence, + double &medEDR, double &maxEDR) { // If we don't have any more records, return From 52e697e17ce7b90a824b5290ea8047a0af867e0c Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 23 Jul 2021 17:48:48 -0600 Subject: [PATCH 089/200] #1855 Removed unused code --- met/src/tools/dev_utils/met_nc_file.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/met/src/tools/dev_utils/met_nc_file.cc b/met/src/tools/dev_utils/met_nc_file.cc index 664ee7fea4..b1e35a2ab6 100644 --- a/met/src/tools/dev_utils/met_nc_file.cc +++ b/met/src/tools/dev_utils/met_nc_file.cc @@ -184,7 +184,6 @@ bool MetNcFile::readFile(const int desired_grib_code, long lengths[2] = { 1, 1 }; lengths[0] = hdr_buf_size; - lengths[1] = strl_count; // // Get the corresponding header message type From 471467c35b875039731c8313088adce77a6bc415 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 23 Jul 2021 17:49:20 -0600 Subject: [PATCH 090/200] #1855 Corrected syntax error --- met/src/tools/tc_utils/tc_dland/tc_dland.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/src/tools/tc_utils/tc_dland/tc_dland.cc b/met/src/tools/tc_utils/tc_dland/tc_dland.cc index e7c378549c..92195d7af1 100644 --- a/met/src/tools/tc_utils/tc_dland/tc_dland.cc +++ b/met/src/tools/tc_utils/tc_dland/tc_dland.cc @@ -290,7 +290,7 @@ void process_distances() { // Write the computed distances to the output file mlog << Debug(3) << "Writing distance to land variable.\n"; if(!put_nc_data_with_dims(&dland_var, &dland[0], grid.ny(), grid.nx())) { - if(dland) { delete dland; dland = (float *) 0; } + if(dland) { delete [] dland; dland = (float *) 0; } mlog << Error << "\nprocess_distances() -> " << "error with dland_var->put\n\n"; exit(1); From 69b5530d88cef6cd59b5cd11f45873424dd6a136 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Tue, 27 Jul 2021 10:18:31 -0600 Subject: [PATCH 091/200] #1855 Changed the second call of close() to release _ncFile --- met/src/tools/dev_utils/insitu_nc_file.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/met/src/tools/dev_utils/insitu_nc_file.cc b/met/src/tools/dev_utils/insitu_nc_file.cc index bdb88f5813..82e0d255ea 100644 --- a/met/src/tools/dev_utils/insitu_nc_file.cc +++ b/met/src/tools/dev_utils/insitu_nc_file.cc @@ -98,7 +98,7 @@ void InsituNcFile::close() // Reclaim the space used for the variables - if (_aircraftId) delete [] _aircraftId; + delete [] _aircraftId; delete [] _timeObs; delete [] _latitude; delete [] _longitude; @@ -138,7 +138,11 @@ bool InsituNcFile::open(const char * filename) if (!(IS_INVALID_NC_P(_ncFile))) { - close(); + if (_ncFile) // close() is called already + { + delete _ncFile; + _ncFile = (NcFile *)0; + } return false; } From 1b977e4ed40bcc6f59f027b092296e2c3befc275 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Tue, 27 Jul 2021 11:37:28 -0600 Subject: [PATCH 092/200] #1855 Deleted break after exit --- met/src/libcode/vx_nc_util/nc_utils.cc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/met/src/libcode/vx_nc_util/nc_utils.cc b/met/src/libcode/vx_nc_util/nc_utils.cc index 14c473702c..50c3ff778e 100644 --- a/met/src/libcode/vx_nc_util/nc_utils.cc +++ b/met/src/libcode/vx_nc_util/nc_utils.cc @@ -2855,7 +2855,6 @@ void copy_nc_att(NcFile *nc_from, NcVar *var_to, const ConcatString attr_name) { mlog << Error << "\ncopy_nc_att(NcFile, NcVar, attr_name) -> " << "Does not copy this type \"" << dataType << "\" global NetCDF attribute.\n\n"; exit(1); - break; } } if(from_att) delete from_att; @@ -2891,7 +2890,6 @@ void copy_nc_att(NcVar *var_from, NcVar *var_to, const ConcatString attr_name) { << "Does not copy this type \"" << dataType << "\" NetCDF attributes from \"" << GET_NC_TYPE_NAME_P(var_from) << "\".\n\n"; exit(1); - break; } } if(from_att) delete from_att; @@ -2931,7 +2929,6 @@ void copy_nc_atts(NcFile *nc_from, NcFile *nc_to, const bool all_attrs) { mlog << Error << "\ncopy_nc_atts(NcFile) -> " << "Does not copy this type \"" << dataType << "\" global NetCDF attributes.\n\n"; exit(1); - break; } } } @@ -2983,7 +2980,6 @@ void copy_nc_atts(NcVar *var_from, NcVar *var_to, const bool all_attrs) { << "Does not copy this type \"" << dataType << "\" NetCDF attributes from \"" << GET_NC_TYPE_NAME_P(var_from) << "\".\n\n"; exit(1); - break; } } } @@ -3083,7 +3079,6 @@ void copy_nc_var_data(NcVar *var_from, NcVar *var_to) { << "Does not copy this type \"" << dataType << "\" NetCDF data from \"" << GET_NC_TYPE_NAME_P(var_from) << "\".\n\n"; exit(1); - break; } } From 658e45e7a22fd7c43f3bdc79fbd259f2cad94fc5 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Tue, 27 Jul 2021 11:40:13 -0600 Subject: [PATCH 093/200] #1855 Chamnged while to if --- met/src/basic/vx_util/GridTemplate.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/met/src/basic/vx_util/GridTemplate.cc b/met/src/basic/vx_util/GridTemplate.cc index 85926d8ae5..f3b83b3252 100644 --- a/met/src/basic/vx_util/GridTemplate.cc +++ b/met/src/basic/vx_util/GridTemplate.cc @@ -182,7 +182,8 @@ GridPoint *GridTemplate::getFirst(const int &base_x, const int &base_y, GridPoint *GridTemplate::getNext(void) const { - while (_pointInGridIterator != _offsetList.end()) + GridPoint *next_point = (GridPoint *)NULL; + if (_pointInGridIterator != _offsetList.end()) { GridOffset *offset = *_pointInGridIterator; @@ -191,11 +192,11 @@ GridPoint *GridTemplate::getNext(void) const _pointInGridReturn.x = _pointInGridBase.x + offset->x_offset; _pointInGridReturn.y = _pointInGridBase.y + offset->y_offset; - return &_pointInGridReturn; + next_point = &_pointInGridReturn; } - return (GridPoint *)NULL; + return next_point; } /********************************************************************** From e6b343bfe86f359f634dd655f271f813131194e1 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 28 Jul 2021 10:13:11 -0600 Subject: [PATCH 094/200] #1855 Added constructor TCLineCounts and initialized the members --- met/src/tools/tc_utils/tc_stat/tc_stat_job.cc | 51 +++++++++++++++++-- met/src/tools/tc_utils/tc_stat/tc_stat_job.h | 2 + 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/met/src/tools/tc_utils/tc_stat/tc_stat_job.cc b/met/src/tools/tc_utils/tc_stat/tc_stat_job.cc index 59e4dd9616..ed0e22757c 100644 --- a/met/src/tools/tc_utils/tc_stat/tc_stat_job.cc +++ b/met/src/tools/tc_utils/tc_stat/tc_stat_job.cc @@ -84,7 +84,6 @@ TCStatJob *TCStatJobFactory::new_tc_stat_job_type(const char *type_str) { mlog << Error << "\nTCStatJobFactory::new_tc_stat_job_type() -> " << "unsupported job type \"" << type_str << "\"\n\n"; exit(1); - break; } // end switch return(job); @@ -3614,6 +3613,7 @@ StringArray TCStatJobProbRIRW::parse_job_command(const char *jobstring) { //////////////////////////////////////////////////////////////////////// void TCStatJobProbRIRW::close_dump_file() { + const char *method_name = "TCStatJobProbRIRW::do_job() -> "; // Close the current output dump file stream if(DumpOut) { @@ -3644,7 +3644,7 @@ void TCStatJobProbRIRW::close_dump_file() { // Open the dump file back up for reading if(!f.open(DumpFile.c_str())) { - mlog << Error << "\nTCStatJobProbRIRW::close_dump_file() -> " + mlog << Error << "\n" << method_name << "can't open the dump file \"" << DumpFile << "\" for reading!\n\n"; exit(1); @@ -3666,7 +3666,10 @@ void TCStatJobProbRIRW::close_dump_file() { TCStatJob::open_dump_file(); // Write the reformatted AsciiTable - *DumpOut << out_at; + + if(DumpOut) *DumpOut << out_at; + else mlog << Warning << "\n" << method_name + << "can't write the reformatted AsciiTable because DumpOut is null\n\n"; // Call parent to close the dump file TCStatJob::close_dump_file(); @@ -3958,6 +3961,48 @@ void TCStatJobProbRIRW::do_output(ostream &out) { //////////////////////////////////////////////////////////////////////// +TCLineCounts::TCLineCounts() { + // Read and keep counts + NRead = 0; + NKeep = 0; + + // Checking entire track + RejTrackWatchWarn = 0; + RejInitThresh = 0; + RejInitStr = 0; + + // Filtering on track attributes + RejRIRW = 0; + RejLandfall = 0; + + // Checking track point attributes + RejAModel = 0; + RejBModel = 0; + RejDesc = 0; + RejStormId = 0; + RejBasin = 0; + RejCyclone = 0; + RejStormName = 0; + RejInit = 0; + RejInitHour = 0; + RejLead = 0; + RejValid = 0; + RejValidHour = 0; + RejInitMask = 0; + RejValidMask = 0; + RejLineType = 0; + RejWaterOnly = 0; + RejColumnThresh = 0; + RejColumnStr = 0; + RejMatchPoints = 0; + RejEventEqual = 0; + RejOutInitMask = 0; + RejOutValidMask = 0; + RejLeadReq = 0; +} + +//////////////////////////////////////////////////////////////////////// + void setup_table(AsciiTable &at, int n_hdr_cols, int prec) { int i; diff --git a/met/src/tools/tc_utils/tc_stat/tc_stat_job.h b/met/src/tools/tc_utils/tc_stat/tc_stat_job.h index 111c6a3564..8eeb816241 100644 --- a/met/src/tools/tc_utils/tc_stat/tc_stat_job.h +++ b/met/src/tools/tc_utils/tc_stat/tc_stat_job.h @@ -158,6 +158,8 @@ struct TCLineCounts { int RejOutInitMask; int RejOutValidMask; int RejLeadReq; + + TCLineCounts(); }; //////////////////////////////////////////////////////////////////////// From 72ac1a889bea17210664d6e982eb954ac5cb4d75 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 28 Jul 2021 10:14:12 -0600 Subject: [PATCH 095/200] #1855 Added break statement back for case '-' --- met/src/basic/vx_config/my_config_scanner.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/src/basic/vx_config/my_config_scanner.cc b/met/src/basic/vx_config/my_config_scanner.cc index a9d8ac7fda..288952689b 100644 --- a/met/src/basic/vx_config/my_config_scanner.cc +++ b/met/src/basic/vx_config/my_config_scanner.cc @@ -264,7 +264,7 @@ switch ( c ) { case '+': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } - case '-': { if ( ! need_number ) { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } } + case '-': { if ( ! need_number ) { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } } break; case '*': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } case '^': { do_single_char_token(lexeme[0]); return ( token(lexeme[0]) ); } From 8d4bf01b128aefdd29efa2628a021ef8dcd84335 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 28 Jul 2021 10:15:46 -0600 Subject: [PATCH 096/200] #1855 Check the new size before extending to avoid thereference of the null pointer --- met/src/tools/other/gsi_tools/gsi_record.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/met/src/tools/other/gsi_tools/gsi_record.cc b/met/src/tools/other/gsi_tools/gsi_record.cc index 23739a1ea9..88f2e6c543 100644 --- a/met/src/tools/other/gsi_tools/gsi_record.cc +++ b/met/src/tools/other/gsi_tools/gsi_record.cc @@ -133,9 +133,13 @@ gsi_clear(); if ( !(g.Buf) ) return; -extend(g.Nalloc); +if (g.Nalloc > 0) { -memcpy(Buf, g.Buf, Nalloc); + extend(g.Nalloc); + + memcpy(Buf, g.Buf, Nalloc); + +} Shuffle = g.Shuffle; From 24a1cc6513d0409b011d0bdf307e7dd457922f2d Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 28 Jul 2021 10:17:57 -0600 Subject: [PATCH 097/200] #1855 Changed count to processed_count for log messages. Initialized variables at get_filtered_nc_data\*() --- met/src/tools/other/madis2nc/madis2nc.cc | 149 +++++++++++++++-------- 1 file changed, 99 insertions(+), 50 deletions(-) diff --git a/met/src/tools/other/madis2nc/madis2nc.cc b/met/src/tools/other/madis2nc/madis2nc.cc index ba85dbffd0..47c327eb06 100644 --- a/met/src/tools/other/madis2nc/madis2nc.cc +++ b/met/src/tools/other/madis2nc/madis2nc.cc @@ -418,28 +418,38 @@ static bool get_filtered_nc_data(NcVar var, float *data, const long dim, const long cur, const char *var_name) { - bool status; + bool status = false; float in_fill_value; const char *method_name = "get_filtered_nc_data(float) "; if (IS_VALID_NC(var)) { - if(!(status = get_nc_data(&var, data, dim, cur))) return status; - - get_nc_att_value(&var, (string)in_fillValue_str, in_fill_value); - mlog << Debug(5) << " " << method_name << GET_NC_NAME(var) << " " - << in_fillValue_str << "=" << in_fill_value << "\n"; - for (int idx=0; idx Date: Wed, 28 Jul 2021 10:20:31 -0600 Subject: [PATCH 098/200] #1855 Corected the number of memory copy --- met/src/tools/other/mode_time_domain/fo_graph.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/src/tools/other/mode_time_domain/fo_graph.cc b/met/src/tools/other/mode_time_domain/fo_graph.cc index 9c22800a4f..d2032d3f66 100644 --- a/met/src/tools/other/mode_time_domain/fo_graph.cc +++ b/met/src/tools/other/mode_time_domain/fo_graph.cc @@ -141,7 +141,7 @@ N_nodes = N*N; TheGraph = new FO_Node [N_nodes]; -memcpy(TheGraph, g.TheGraph, N*sizeof(FO_Node)); +memcpy(TheGraph, g.TheGraph, N_nodes*sizeof(FO_Node)); // // done From 16faedbb7fc91fd0d4cd61595017ec63e4cda61f Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 28 Jul 2021 16:03:23 -0600 Subject: [PATCH 099/200] #1855 Exit with an error message if both fgi & bgi are null --- met/src/tools/tc_utils/tc_gen/tc_gen.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/met/src/tools/tc_utils/tc_gen/tc_gen.cc b/met/src/tools/tc_utils/tc_gen/tc_gen.cc index 21ecc6269f..bfb3960226 100644 --- a/met/src/tools/tc_utils/tc_gen/tc_gen.cc +++ b/met/src/tools/tc_utils/tc_gen/tc_gen.cc @@ -431,6 +431,12 @@ void do_genesis_ctc(const TCGenVxOpt &vx_opt, const GenesisInfo *fgi = gpd.fcst_gen(i); const GenesisInfo *bgi = gpd.best_gen(i); + if(!fgi && !bgi) { + mlog << Error << "\ndo_genesis_ctc() -> " + << "Both the forecast and the best track are null at index " << i << ".\n\n"; + exit(1); + } + // Initialize diff.clear(); From 0d118ca5cd7e4722bc77d496b582fefee8fa0fb3 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 28 Jul 2021 16:27:25 -0600 Subject: [PATCH 100/200] #1855 Clear Lead_Times before extening. Formatting for error messages --- .../other/mode_time_domain/mtd_file_int.cc | 65 ++++++++++--------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/met/src/tools/other/mode_time_domain/mtd_file_int.cc b/met/src/tools/other/mode_time_domain/mtd_file_int.cc index 1d885d85bf..e51024de0e 100644 --- a/met/src/tools/other/mode_time_domain/mtd_file_int.cc +++ b/met/src/tools/other/mode_time_domain/mtd_file_int.cc @@ -279,6 +279,7 @@ int * d = Data; for (j=0; j bad value ... " << r << "\n\n"; + mlog << Error << "\n MtdIntFile::set_radius(int) -> bad value ... " << r << "\n\n"; exit ( 1 ); @@ -324,7 +325,7 @@ void MtdIntFile::set_time_window(int beg, int end) if ( end < beg ) { - mlog << Error << "\n\n MtdIntFile::set_time_window(int) -> bad values ... " << beg << " and " << end << "\n\n"; + mlog << Error << "\n MtdIntFile::set_time_window(int) -> bad values ... " << beg << " and " << end << "\n\n"; exit ( 1 ); @@ -348,7 +349,7 @@ void MtdIntFile::set_threshold(double t) // if ( t < 0.0 ) { // -// mlog << Error << "\n\n MtdIntFile::set_threshold(double) -> bad value ... " << t << "\n\n"; +// mlog << Error << "\n MtdIntFile::set_threshold(double) -> bad value ... " << t << "\n\n"; // // exit ( 1 ); // @@ -444,7 +445,7 @@ var = get_nc_var(&f, data_field_name); //if ( !(var->set_cur(0, 0, 0)) ) { // -// mlog << Error << "\n\n MtdIntFile::read() -> trouble setting corner\n\n"; +// mlog << Error << "\n MtdIntFile::read() -> trouble setting corner\n\n"; // // exit ( 1 ); // @@ -454,7 +455,7 @@ var = get_nc_var(&f, data_field_name); // //if ( ! (var->get(Data, Nt, Ny, Nx)) ) { // -// mlog << Error << "\n\n MtdIntFile::read(const char *) -> trouble getting data\n\n"; +// mlog << Error << "\n MtdIntFile::read(const char *) -> trouble getting data\n\n"; // // exit ( 1 ); // @@ -466,7 +467,7 @@ long lengths[3] = {Nt, Ny, Nx}; //if ( ! get_nc_data(&var, Data, (long *){Nt, Ny, Nx}, (long *){0,0,0}) ) { if ( ! get_nc_data(&var, Data, lengths, offsets) ) { - mlog << Error << "\n\n MtdIntFile::read(const char *) -> trouble getting data\n\n"; + mlog << Error << "\n MtdIntFile::read(const char *) -> trouble getting data\n\n"; exit ( 1 ); @@ -474,7 +475,7 @@ if ( ! get_nc_data(&var, Data, lengths, offsets) ) { // const time_t t_stop = time(0); // for timing the data read operation -// mlog << Debug(5) << "\n\n MtdIntFile::read(): Time to read data = " << (t_stop - t_start) << " seconds\n\n" << flush; +// mlog << Debug(5) << "\n MtdIntFile::read(): Time to read data = " << (t_stop - t_start) << " seconds\n\n" << flush; // // done @@ -570,7 +571,7 @@ long lengths[3] = {Nt, Ny, Nx}; if ( ! put_nc_data(&data_var, Data, lengths, offsets) ) { - mlog << Error << "\n\n MtdIntFile::write(const char *) -> trouble getting data\n\n"; + mlog << Error << "\n MtdIntFile::write(const char *) -> trouble getting data\n\n"; exit ( 1 ); @@ -578,7 +579,7 @@ if ( ! put_nc_data(&data_var, Data, lengths, offsets) ) { //if ( !(data_var->set_cur(0, 0, 0)) ) { // -// mlog << Error << "\n\n MtdIntFile::write() -> trouble setting corner on data field\n\n"; +// mlog << Error << "\n MtdIntFile::write() -> trouble setting corner on data field\n\n"; // // exit ( 1 ); // @@ -588,7 +589,7 @@ if ( ! put_nc_data(&data_var, Data, lengths, offsets) ) { // //if ( !(data_var->put(Data, Nt, Ny, Nx)) ) { // -// mlog << Error << "\n\n MtdIntFile::write() -> trouble writing data field\n\n"; +// mlog << Error << "\n MtdIntFile::write() -> trouble writing data field\n\n"; // // exit ( 1 ); // @@ -606,7 +607,7 @@ if ( is_split ) { if ( !(put_nc_data(&volumes_var, ObjVolume, Nobjects, 0)) ) { - mlog << Error << "\n\n MtdIntFile::write() -> trouble writing object volumes\n\n"; + mlog << Error << "\n MtdIntFile::write() -> trouble writing object volumes\n\n"; exit ( 1 ); @@ -616,7 +617,7 @@ if ( is_split ) { // const time_t t_stop = time(0); // for timing the data write operation -// mlog << Debug(5) << "\n\n MtdIntFile::write(): Time to write data = " << (t_stop - t_start) << " seconds\n\n" << flush; +// mlog << Debug(5) << "\n MtdIntFile::write(): Time to write data = " << (t_stop - t_start) << " seconds\n\n" << flush; // // done @@ -638,7 +639,7 @@ NcFile f(_filename, NcFile::replace); if ( IS_INVALID_NC(f) ) { - mlog << Error << "\n\n MtdIntFile::write(const char *) -> unable to open netcdf output file \"" << _filename << "\"\n\n"; + mlog << Error << "\n MtdIntFile::write(const char *) -> unable to open netcdf output file \"" << _filename << "\"\n\n"; // exit ( 1 ); @@ -666,7 +667,7 @@ MtdIntFile MtdIntFile::const_t_slice(const int t) const if ( (t < 0) || (t >= Nt) ) { - mlog << Error << "\n\n MtdIntFile MtdIntFile::const_t_slice(int) const -> range check error\n\n"; + mlog << Error << "\n MtdIntFile MtdIntFile::const_t_slice(int) const -> range check error\n\n"; exit ( 1 ); @@ -735,7 +736,7 @@ MtdIntFile MtdIntFile::const_t_mask(const int t, const int obj_num) const // if ( (t < 0) || (t >= Nt) ) { - mlog << Error << "\n\n MtdIntFile MtdIntFile::const_t_mask(int) const -> range check error\n\n"; + mlog << Error << "\n MtdIntFile MtdIntFile::const_t_mask(int) const -> range check error\n\n"; exit ( 1 ); @@ -921,7 +922,7 @@ void MtdIntFile::zero_border(int n) if ( !Data ) { - mlog << Error << "\n\n MtdIntFile::zero_border(int) -> no data field!\n\n"; + mlog << Error << "\n MtdIntFile::zero_border(int) -> no data field!\n\n"; exit ( 1 ); @@ -929,7 +930,7 @@ if ( !Data ) { if ( 2*n >= min(Nx, Ny) ) { - mlog << Error << "\n\n MtdIntFile::zero_border(int) -> border size too large!\n\n"; + mlog << Error << "\n MtdIntFile::zero_border(int) -> border size too large!\n\n"; exit ( 1 ); @@ -982,7 +983,7 @@ void MtdIntFile::set_to_zeroes() if ( !Data ) { - mlog << Error << "\n\n MtdIntFile::set_to_zeroes() -> no data!\n\n"; + mlog << Error << "\n MtdIntFile::set_to_zeroes() -> no data!\n\n"; exit ( 1 ); @@ -1008,7 +1009,7 @@ MtdIntFile MtdIntFile::split_const_t(int & n_shapes) const if ( Nt != 1 ) { - mlog << Error << "\n\n split_const_t(int &) -> not const-time slice!\n\n"; + mlog << Error << "\n split_const_t(int &) -> not const-time slice!\n\n"; exit ( 1 ); @@ -1244,7 +1245,7 @@ int MtdIntFile::volume(int k) const if ( !ObjVolume ) { - mlog << Error << "\n\n MtdIntFile::volume(int) -> field not split!\n\n"; + mlog << Error << "\n MtdIntFile::volume(int) -> field not split!\n\n"; exit ( 1 ); @@ -1252,7 +1253,7 @@ if ( !ObjVolume ) { if ( (k < 0) || (k >= Nobjects) ) { - mlog << Error << "\n\n MtdIntFile::volume(int) -> range check error!\n\n"; + mlog << Error << "\n MtdIntFile::volume(int) -> range check error!\n\n"; exit ( 1 ); @@ -1273,7 +1274,7 @@ int MtdIntFile::total_volume() const if ( !ObjVolume ) { - mlog << Error << "\n\n MtdIntFile::total_volume() -> field not split!\n\n"; + mlog << Error << "\n MtdIntFile::total_volume() -> field not split!\n\n"; exit ( 1 ); @@ -1343,7 +1344,7 @@ int * d = Data; // if ( n_new == 0 ) { // -// mlog << Error << "\n\n MtdIntFile::sift_objects() -> no objects left!\n\n"; +// mlog << Error << "\n MtdIntFile::sift_objects() -> no objects left!\n\n"; // // exit ( 1 ); // @@ -1522,7 +1523,7 @@ for (x=0; x empty object!\n\n"; + mlog << Error << "\n MtdIntFile::calc_3d_centroid() const -> empty object!\n\n"; exit ( 1 ); @@ -1572,7 +1573,7 @@ for (x=0; x empty object!\n\n"; + // mlog << Error << "\n MtdIntFile::calc_2d_centroid_at_t() const -> empty object!\n\n"; // exit ( 1 ); @@ -1624,7 +1625,7 @@ MtdIntFile MtdIntFile::select(int n) const // 1-based if ( (n < 1) || (n > Nobjects) ) { - mlog << Error << "\n\n MtdIntFile::select(int) -> range check error on n ... " + mlog << Error << "\n MtdIntFile::select(int) -> range check error on n ... " << "NObjects = " << Nobjects << " ... " << "n = " << n << "\n\n"; @@ -1676,7 +1677,7 @@ MtdIntFile MtdIntFile::select_cluster(const IntArray & a) const // 1-based if ( (a.min() < 0) || (a.max() > Nobjects) ) { - mlog << Error << "\n\n MtdIntFile::select_cluster(const IntArray &) -> range check error\n\n"; + mlog << Error << "\n MtdIntFile::select_cluster(const IntArray &) -> range check error\n\n"; exit ( 1 ); @@ -1737,7 +1738,7 @@ int MtdIntFile::x_left(const int y) const if ( (y < 0) || (y >= Ny) ) { - mlog << Error << "\n\n MtdIntFile::x_left(int) -> range check error\n\n"; + mlog << Error << "\n MtdIntFile::x_left(int) -> range check error\n\n"; exit ( 1 ); @@ -1766,7 +1767,7 @@ int MtdIntFile::x_right(const int y) const if ( (y < 0) || (y >= Ny) ) { - mlog << Error << "\n\n MtdIntFile::x_right(int) -> range check error\n\n"; + mlog << Error << "\n MtdIntFile::x_right(int) -> range check error\n\n"; exit ( 1 ); @@ -1855,7 +1856,7 @@ Mtd_2D_Moments MtdIntFile::calc_2d_moments() const if ( Nt != 1 ) { - mlog << Error << "\n\n MtdIntFile::calc_2d_moments() const -> not a 2D object!\n\n"; + mlog << Error << "\n MtdIntFile::calc_2d_moments() const -> not a 2D object!\n\n"; exit ( 1 ); @@ -1997,7 +1998,7 @@ for (t=0; t<(mask.nt()); ++t) { if ( nc < 0 ) { - mlog << Error << "\n\n split(const MtdIntFile &, int &) -> can't find cell!\n\n"; + mlog << Error << "\n split(const MtdIntFile &, int &) -> can't find cell!\n\n"; exit ( 1 ); @@ -2031,7 +2032,7 @@ void adjust_obj_numbers(MtdIntFile & s, int delta) if ( s.nt() != 1 ) { - mlog << Error << "\n\n adjust_obj_numbers() -> not const-time slice!\n\n"; + mlog << Error << "\n adjust_obj_numbers() -> not const-time slice!\n\n"; exit ( 1 ); From 543a7364f070ca4a47cfa3c2ae047ca7d19d1135 Mon Sep 17 00:00:00 2001 From: MET Tools Test Account Date: Thu, 29 Jul 2021 15:17:12 -0600 Subject: [PATCH 101/200] Add definition for the compilation environment on seneca. --- scripts/environment/development.seneca | 46 ++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 scripts/environment/development.seneca diff --git a/scripts/environment/development.seneca b/scripts/environment/development.seneca new file mode 100644 index 0000000000..d6e13f0543 --- /dev/null +++ b/scripts/environment/development.seneca @@ -0,0 +1,46 @@ +# Define the development environment for NCAR project machine seneca +# Based on settings in /usr/local/src/met/README.snat + +# Top-level MET project directory +MET_PROJ_DIR=/d1/projects/MET + +# Variables required to build MET +export MET_DEVELOPMENT=true +export MET_DST=/usr/local +export MET_NETCDF=${MET_DST}/netcdf-4.7.0/gcc-8.3.0 +export MET_HDF5=${MET_DST}/hdf5-1.8.21 +export MET_HDFINC=${MET_DST}/hdf4-4.2.15/include/hdf +export MET_HDFLIB=${MET_DST}/hdf4-4.2.15/lib +export MET_HDFEOS=${MET_DST}/hdf-eos2-20v1 +export MET_BUFR=${MET_DST} +export MET_GRIB2C=${MET_DST} +export MET_GSL=${MET_PROJ_DIR}/MET_releases/external_libs/gnu_8.3.0 +export MET_CAIROINC=/usr/include/cairo +export MET_CAIROLIB=/usr/lib/x86_64-linux-gnu +export MET_FREETYPEINC=/usr/include/freetype2 +export MET_FREETYPELIB=/usr/lib/x86_64-linux-gnu +export MET_JASPER=${MET_DST}/jasper-1.900.1 + +# For Python 3 in met-9.0 +export MET_PYTHON=/usr/local/met-python3 +export MET_PYTHON_CC="-I${MET_PYTHON}/include/python3.8" +export MET_PYTHON_LD="-L${MET_PYTHON}/lib -lpython3.8 -lcrypt -lpthread -ldl -lutil -lm" + +# -D__64BIT__ is required because we've compiled libgrib2c.a with that flag +export CFLAGS="-DUNDERSCORE -fPIC -D__64BIT__" +export CXXFLAGS=${CFLAGS} + +# Set LDFLAGS to include -rpath settings when compiling MET +export LDFLAGS="-Wl,--disable-new-dtags" +export LDFLAGS="${LDFLAGS} -Wl,-rpath,${MET_DST}/lib:${MET_HDFEOS}/lib:${MET_NETCDF}/lib:${MET_DST}/zlib-1.2.11/lib:${MET_DST}/szip-2.1.1/lib" +export LDFLAGS="${LDFLAGS} -Wl,-rpath,${MET_HDFLIB}:${MET_HDF5}/lib:${MET_GSL}/lib:${MET_PYTHON}/lib:${MET_JASPER}/lib" +export LDFLAGS="${LDFLAGS} -L${MET_JASPER}/lib" + +# Variables required to run MET +export MET_TEST_INPUT=${MET_PROJ_DIR}/MET_test_data/unit_test +export MET_FONT_DIR=${MET_TEST_INPUT}/fonts + +# This is a cron script -- create the shell environment for this job +export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:\ + /usr/bin/X11:/opt/bin:${MET_NETCDF}/bin" + From 0d89f7a535034a56bd3fbc6f26aad97cbd58fc94 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 30 Jul 2021 13:52:07 -0600 Subject: [PATCH 102/200] #1855 Extend Lead_Times for new times --- met/src/tools/other/mode_time_domain/mtd_file_int.cc | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/met/src/tools/other/mode_time_domain/mtd_file_int.cc b/met/src/tools/other/mode_time_domain/mtd_file_int.cc index e51024de0e..0668e26396 100644 --- a/met/src/tools/other/mode_time_domain/mtd_file_int.cc +++ b/met/src/tools/other/mode_time_domain/mtd_file_int.cc @@ -275,12 +275,9 @@ Nx = _nx; Ny = _ny; Nt = _nt; -int * d = Data; - -for (j=0; j Date: Fri, 30 Jul 2021 14:08:57 -0600 Subject: [PATCH 103/200] #1855 Removed break after exit --- met/src/basic/vx_config/dictionary.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/met/src/basic/vx_config/dictionary.cc b/met/src/basic/vx_config/dictionary.cc index cbe3013cba..55ef59a0ac 100644 --- a/met/src/basic/vx_config/dictionary.cc +++ b/met/src/basic/vx_config/dictionary.cc @@ -219,7 +219,6 @@ switch ( entry.Type ) { << "\n\n DictionaryEntry::assign(const DictionaryEntry &) -> bad object type ... \"" << configobjecttype_to_string(entry.Type) << "\"\n\n"; exit ( 1 ); - break; } // switch @@ -300,7 +299,6 @@ switch ( Type ) { << "bad object type ... \"" << configobjecttype_to_string(Type) << "\"\n\n"; exit ( 1 ); - break; } // switch @@ -377,7 +375,6 @@ switch ( Type ) { mlog << Error << "DictionaryEntry::dump_config_format() -> bad threshold type ... " << Thresh->get_type() << "\n"; exit ( 1 ); - break; } // switch if ( Thresh->get_type() != thresh_na ) out << Thresh->get_value(); @@ -402,7 +399,6 @@ switch ( Type ) { << "bad object type ... \"" << configobjecttype_to_string(Type) << "\"\n\n"; exit ( 1 ); - break; } // switch @@ -1313,7 +1309,7 @@ for (j=0; j<(scope.n_elements() - 1); ++j) { // try current dictionary // - const char * stub = scope[scope.n_elements() - 1].c_str(); +const string stub = scope[scope.n_elements() - 1].c_str(); E = D->lookup_simple(stub); From 33d0cebd2fb9c4650c9e08e45dfe50b7f01663ff Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 30 Jul 2021 14:09:57 -0600 Subject: [PATCH 104/200] #1855 define "c" dynamically --- met/src/libcode/vx_data2d_grib/grib_utils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/src/libcode/vx_data2d_grib/grib_utils.cc b/met/src/libcode/vx_data2d_grib/grib_utils.cc index 64c49234b4..3fbbdd23c5 100644 --- a/met/src/libcode/vx_data2d_grib/grib_utils.cc +++ b/met/src/libcode/vx_data2d_grib/grib_utils.cc @@ -565,7 +565,7 @@ double decode_lat_lon(const unsigned char * p, int n) int i, parity; double answer; -unsigned char c[3]; +unsigned char c[n]; // // For all of the lat/lon parameters, the leftmost bit indicates the From c0f678dc8d9c7509ba19f640dbda76fe0ef24cab Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 30 Jul 2021 14:42:39 -0600 Subject: [PATCH 105/200] #1855 Move the log message within if statement to avoid dereferencing a null pointer --- met/src/libcode/vx_grid/goes_grid.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/met/src/libcode/vx_grid/goes_grid.cc b/met/src/libcode/vx_grid/goes_grid.cc index eed67fbaaa..f7cc8e96fa 100644 --- a/met/src/libcode/vx_grid/goes_grid.cc +++ b/met/src/libcode/vx_grid/goes_grid.cc @@ -522,14 +522,14 @@ void GoesImagerData::compute_lat_lon() } } } + + mlog << Debug(4) << method_name << " lon: " << lon_min << " to " << lon_max + << ", lat: " << lat_min << " to " << lat_max << " at index " + << idx_lon_min << " & " << idx_lon_max << ", " + << idx_lat_min << " & " << idx_lat_max << " from " + << " x: " << x_values[0] << " to " << x_values[nx-1] + << " y: " << y_values[0] << " to " << y_values[ny-1] << "\n"; } - - mlog << Debug(4) << method_name << " lon: " << lon_min << " to " << lon_max - << ", lat: " << lat_min << " to " << lat_max << " at index " - << idx_lon_min << " & " << idx_lon_max << ", " - << idx_lat_min << " & " << idx_lat_max << " from " - << " x: " << x_values[0] << " to " << x_values[nx-1] - << " y: " << y_values[0] << " to " << y_values[ny-1] << "\n"; } //////////////////////////////////////////////////////////////////////// From f254c546285b426d3fa98c2b527e5f89ce238689 Mon Sep 17 00:00:00 2001 From: Seth Linden Date: Fri, 30 Jul 2021 15:00:46 -0600 Subject: [PATCH 106/200] Feature 1843 scatter index (#1863) * Added scatter index variables: SI, SI_BCL, SI_BCU to cnt columns. SL * Per issue #1843 Added Scatter Index variables (SI, SI_BCL, SI_BCU) to the CNT stat type. SL * Added Scatter Index (SI, SI_BCL, SI_BCU) to cnt stat type header. SL * Per issue #1843, added Scatter Index variables to write_cnt_cols(). SL * Per issue #1843 added Scatter Index (si) to CNTinfo class. SL * Per issue #1843 added Scatter Index (SI, si) to CNTInfo::get_stat(). SL * Per issue #1843 added Scatter Index (SI, si) calculation to both versions of compute_cntinfo(). SL * Per issue #1843, forgot semi-colon after SI calculation, fixed. SL * Added Scatter Index (si) to some of the clear() and allocate() functions. SL * Per issue #1843, added Scatter Index (si) to compute_cnt_mean(). SL * Per issue #1843, added Scatter Index (si) to bootstrap interval calculation and to the CNT write function. SL * Per issue #1843 added Scatter Index (SI, SI_BCL, SI_BCU) to store_stat_cnt(). SL * Per issue #1843, in get_stat() moved Scatterd Index (SI) line to be below RMSE for consitency. SL * Added Scatter Index (SI) to the CNT output format table. SL * Added Scatter Index (SI) to CNT statistics definitions. SL * Update appendixC.rst * Update stat_columns.cc * Update compute_ci.cc * Update met_stats.cc * Per #1843, update write_cntinfo() function. Since we're READING the SI value immediately after the RMSE value when computing CI's, we also need to write SI immediately after RMSE. Otherwise, we'll be computing CI's using the wrong statistics replicates. * Per #1843, check for divide by zero when computing SI... this could happen if comparing the same input file to itself with Grid-Stat. * Per #1843, correct definition of SI from RMSE/ME to RMSE/OBAR. * Per #1843, updated the SI definition to divide by OBAR instead of ME, but forgot to update the divide-by-zero check. Co-authored-by: Seth Linden Co-authored-by: johnhg --- .../table_files/met_header_columns_V10.1.txt | 2 +- met/docs/Users_Guide/appendixC.rst | 9 ++++++ met/docs/Users_Guide/point-stat.rst | 4 +++ met/src/basic/vx_util/stat_column_defs.h | 3 +- met/src/libcode/vx_stat_out/stat_columns.cc | 12 +++++++- met/src/libcode/vx_statistics/compute_ci.cc | 30 +++++++++++++++++-- .../libcode/vx_statistics/compute_stats.cc | 22 ++++++++++++++ met/src/libcode/vx_statistics/met_stats.cc | 4 +++ met/src/libcode/vx_statistics/met_stats.h | 3 ++ .../core/series_analysis/series_analysis.cc | 3 ++ test/hdr/met_10_1.hdr | 2 +- 11 files changed, 87 insertions(+), 7 deletions(-) diff --git a/met/data/table_files/met_header_columns_V10.1.txt b/met/data/table_files/met_header_columns_V10.1.txt index 6c64d89a5f..d538d74c92 100644 --- a/met/data/table_files/met_header_columns_V10.1.txt +++ b/met/data/table_files/met_header_columns_V10.1.txt @@ -1,4 +1,4 @@ -V10.1 : STAT : CNT : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FBAR FBAR_NCL FBAR_NCU FBAR_BCL FBAR_BCU FSTDEV FSTDEV_NCL FSTDEV_NCU FSTDEV_BCL FSTDEV_BCU OBAR OBAR_NCL OBAR_NCU OBAR_BCL OBAR_BCU OSTDEV OSTDEV_NCL OSTDEV_NCU OSTDEV_BCL OSTDEV_BCU PR_CORR PR_CORR_NCL PR_CORR_NCU PR_CORR_BCL PR_CORR_BCU SP_CORR KT_CORR RANKS FRANK_TIES ORANK_TIES ME ME_NCL ME_NCU ME_BCL ME_BCU ESTDEV ESTDEV_NCL ESTDEV_NCU ESTDEV_BCL ESTDEV_BCU MBIAS MBIAS_BCL MBIAS_BCU MAE MAE_BCL MAE_BCU MSE MSE_BCL MSE_BCU BCMSE BCMSE_BCL BCMSE_BCU RMSE RMSE_BCL RMSE_BCU E10 E10_BCL E10_BCU E25 E25_BCL E25_BCU E50 E50_BCL E50_BCU E75 E75_BCL E75_BCU E90 E90_BCL E90_BCU EIQR EIQR_BCL EIQR_BCU MAD MAD_BCL MAD_BCU ANOM_CORR ANOM_CORR_NCL ANOM_CORR_NCU ANOM_CORR_BCL ANOM_CORR_BCU ME2 ME2_BCL ME2_BCU MSESS MSESS_BCL MSESS_BCU RMSFA RMSFA_BCL RMSFA_BCU RMSOA RMSOA_BCL RMSOA_BCU ANOM_CORR_UNCNTR ANOM_CORR_UNCNTR_BCL ANOM_CORR_UNCNTR_BCU +V10.1 : STAT : CNT : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FBAR FBAR_NCL FBAR_NCU FBAR_BCL FBAR_BCU FSTDEV FSTDEV_NCL FSTDEV_NCU FSTDEV_BCL FSTDEV_BCU OBAR OBAR_NCL OBAR_NCU OBAR_BCL OBAR_BCU OSTDEV OSTDEV_NCL OSTDEV_NCU OSTDEV_BCL OSTDEV_BCU PR_CORR PR_CORR_NCL PR_CORR_NCU PR_CORR_BCL PR_CORR_BCU SP_CORR KT_CORR RANKS FRANK_TIES ORANK_TIES ME ME_NCL ME_NCU ME_BCL ME_BCU ESTDEV ESTDEV_NCL ESTDEV_NCU ESTDEV_BCL ESTDEV_BCU MBIAS MBIAS_BCL MBIAS_BCU MAE MAE_BCL MAE_BCU MSE MSE_BCL MSE_BCU BCMSE BCMSE_BCL BCMSE_BCU RMSE RMSE_BCL RMSE_BCU E10 E10_BCL E10_BCU E25 E25_BCL E25_BCU E50 E50_BCL E50_BCU E75 E75_BCL E75_BCU E90 E90_BCL E90_BCU EIQR EIQR_BCL EIQR_BCU MAD MAD_BCL MAD_BCU ANOM_CORR ANOM_CORR_NCL ANOM_CORR_NCU ANOM_CORR_BCL ANOM_CORR_BCU ME2 ME2_BCL ME2_BCU MSESS MSESS_BCL MSESS_BCU RMSFA RMSFA_BCL RMSFA_BCU RMSOA RMSOA_BCL RMSOA_BCU ANOM_CORR_UNCNTR ANOM_CORR_UNCNTR_BCL ANOM_CORR_UNCNTR_BCU SI SI_BCL SI_BCU V10.1 : STAT : CTC : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FY_OY FY_ON FN_OY FN_ON V10.1 : STAT : CTS : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL BASER BASER_NCL BASER_NCU BASER_BCL BASER_BCU FMEAN FMEAN_NCL FMEAN_NCU FMEAN_BCL FMEAN_BCU ACC ACC_NCL ACC_NCU ACC_BCL ACC_BCU FBIAS FBIAS_BCL FBIAS_BCU PODY PODY_NCL PODY_NCU PODY_BCL PODY_BCU PODN PODN_NCL PODN_NCU PODN_BCL PODN_BCU POFD POFD_NCL POFD_NCU POFD_BCL POFD_BCU FAR FAR_NCL FAR_NCU FAR_BCL FAR_BCU CSI CSI_NCL CSI_NCU CSI_BCL CSI_BCU GSS GSS_BCL GSS_BCU HK HK_NCL HK_NCU HK_BCL HK_BCU HSS HSS_BCL HSS_BCU ODDS ODDS_NCL ODDS_NCU ODDS_BCL ODDS_BCU LODDS LODDS_NCL LODDS_NCU LODDS_BCL LODDS_BCU ORSS ORSS_NCL ORSS_NCU ORSS_BCL ORSS_BCU EDS EDS_NCL EDS_NCU EDS_BCL EDS_BCU SEDS SEDS_NCL SEDS_NCU SEDS_BCL SEDS_BCU EDI EDI_NCL EDI_NCU EDI_BCL EDI_BCU SEDI SEDI_NCL SEDI_NCU SEDI_BCL SEDI_BCU BAGSS BAGSS_BCL BAGSS_BCU V10.1 : STAT : FHO : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL F_RATE H_RATE O_RATE diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 8f508f770a..3285d19e7d 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -507,6 +507,15 @@ Called "RMSE" in CNT output :numref:`table_PS_format_info_CNT` RMSE is simply the square root of the MSE, :math:`\text{RMSE} = \sqrt{\text{MSE}}`. +Scatter Index (SI) +~~~~~~~~~~~~~~~~~~ + +Called "SI" in CNT output :numref:`table_PS_format_info_CNT` + +SI is the ratio of the root mean squared error to the average observation value, :math:`\text{SI} = \text{RMSE} / \text{OBAR}`. + +Smaller values of SI indicate better agreement between the model and observations (less scatter on scatter plot). + Standard deviation of the error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/met/docs/Users_Guide/point-stat.rst b/met/docs/Users_Guide/point-stat.rst index ed99da2a59..162f86926c 100644 --- a/met/docs/Users_Guide/point-stat.rst +++ b/met/docs/Users_Guide/point-stat.rst @@ -852,6 +852,10 @@ The first set of header columns are common to all of the output files generated * - 120-122 - ANOM_CORR_UNCNTR, :raw-html:`
` ANOM_CORR_UNCNTR_BCL, :raw-html:`
` ANOM_CORR_UNCNTR_BCU - The uncentered Anomaly Correlation excluding mean error including bootstrap upper and lower confidence limits + * - 123-125 + - SI, :raw-html:`
` SI_BCL, :raw-html:`
` SI_BCU + - Scatter Index including bootstrap upper and lower confidence limits + .. _table_PS_format_info_MCTC: diff --git a/met/src/basic/vx_util/stat_column_defs.h b/met/src/basic/vx_util/stat_column_defs.h index d34fa22fdd..02f5648ede 100644 --- a/met/src/basic/vx_util/stat_column_defs.h +++ b/met/src/basic/vx_util/stat_column_defs.h @@ -103,7 +103,8 @@ static const char * cnt_columns [] = { "MSESS", "MSESS_BCL", "MSESS_BCU", "RMSFA", "RMSFA_BCL", "RMSFA_BCU", "RMSOA", "RMSOA_BCL", "RMSOA_BCU", - "ANOM_CORR_UNCNTR", "ANOM_CORR_UNCNTR_BCL", "ANOM_CORR_UNCNTR_BCU" + "ANOM_CORR_UNCNTR", "ANOM_CORR_UNCNTR_BCL", "ANOM_CORR_UNCNTR_BCU", + "SI", "SI_BCL", "SI_BCL" }; static const char * sl1l2_columns [] = { diff --git a/met/src/libcode/vx_stat_out/stat_columns.cc b/met/src/libcode/vx_stat_out/stat_columns.cc index e385cfcfc7..b38c2e2992 100644 --- a/met/src/libcode/vx_stat_out/stat_columns.cc +++ b/met/src/libcode/vx_stat_out/stat_columns.cc @@ -2341,7 +2341,8 @@ void write_cnt_cols(const CNTInfo &cnt_info, int i, // MSESS, MSESS_BCL, MSESS_BCU, // RMSFA, RMSFA_BCL, RMSFA_BCU, // RMSOA, RMSOA_BCL, RMSOA_BCU, - // ANOM_CORR_UNCNTR, ANOM_CORR_UNCNTR_BCL, ANOM_CORR_UNCNTR_BCU + // ANOM_CORR_UNCNTR, ANOM_CORR_UNCNTR_BCL, ANOM_CORR_UNCNTR_BCU, + // SI, SI_BCL, SI_BCU // at.set_entry(r, c+0, // Total Number of Grid Points @@ -2635,6 +2636,15 @@ void write_cnt_cols(const CNTInfo &cnt_info, int i, at.set_entry(r, c+96, // Anomaly Correlation Uncentered BCU cnt_info.anom_corr_uncntr.v_bcu[i]); + at.set_entry(r, c+97, // Scatter Index + cnt_info.si.v); + + at.set_entry(r, c+98, // Scatter Index BCL + cnt_info.si.v_bcl[i]); + + at.set_entry(r, c+99, // Scatter Index BCU + cnt_info.si.v_bcu[i]); + return; } diff --git a/met/src/libcode/vx_statistics/compute_ci.cc b/met/src/libcode/vx_statistics/compute_ci.cc index dc58de48cf..c3dcd1ee7f 100644 --- a/met/src/libcode/vx_statistics/compute_ci.cc +++ b/met/src/libcode/vx_statistics/compute_ci.cc @@ -1265,6 +1265,18 @@ void compute_cnt_stats_ci_bca(const gsl_rng *rng_ptr, cnt_info.rmse.v_bcl[i], cnt_info.rmse.v_bcu[i]); + // + // Compute bootstrap interval for si + // + s = cnt_info.si.v; + read_ldf(cnt_i_file, c, si_na); + read_ldf(cnt_r_file, c++, sr_na); + for(i=0; i Date: Fri, 30 Jul 2021 15:05:27 -0600 Subject: [PATCH 107/200] #1855 Corected typo - compare the numnber of U and V --- met/src/tools/core/grid_stat/grid_stat.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/src/tools/core/grid_stat/grid_stat.cc b/met/src/tools/core/grid_stat/grid_stat.cc index 1d75923bf3..f0daf3f6a9 100644 --- a/met/src/tools/core/grid_stat/grid_stat.cc +++ b/met/src/tools/core/grid_stat/grid_stat.cc @@ -2134,7 +2134,7 @@ void do_vl1l2(VL1L2Info *&v_info, int i_vx, int i; // Check that the number of pairs are the same - if(pd_u_ptr->n_obs != pd_u_ptr->n_obs) { + if(pd_u_ptr->n_obs != pd_v_ptr->n_obs) { mlog << Error << "\ndo_vl1l2() -> " << "unequal number of UGRD and VGRD pairs (" << pd_u_ptr->n_obs << " != " << pd_v_ptr->n_obs From 6846f629f1a608df053c1855835d415ddb223de7 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 30 Jul 2021 15:13:52 -0600 Subject: [PATCH 108/200] #1855 Check if var_info is hull --- met/src/tools/core/pcp_combine/pcp_combine.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/met/src/tools/core/pcp_combine/pcp_combine.cc b/met/src/tools/core/pcp_combine/pcp_combine.cc index 6ff36272aa..98353430b2 100644 --- a/met/src/tools/core/pcp_combine/pcp_combine.cc +++ b/met/src/tools/core/pcp_combine/pcp_combine.cc @@ -1320,6 +1320,11 @@ void write_nc_data(unixtime nc_init, unixtime nc_valid, int nc_accum, StringArray sa; NcVar nc_var; + if (!var_info) { + mlog << Error << "\nwrite_nc_data() var_info is null.\n\n"; + exit(1); + } + // // Write to the -name command line argument, if specified. // From f7a0aead1be22eed61047c3f93d03b8e11d64685 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 30 Jul 2021 15:41:19 -0600 Subject: [PATCH 109/200] #1855 Avoid un-initialized variables: dt at open(), v at lat() & lon(), and local variables at data() --- .../tools/other/modis_regrid/modis_file.cc | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/met/src/tools/other/modis_regrid/modis_file.cc b/met/src/tools/other/modis_regrid/modis_file.cc index c3825f8d85..33327eed82 100644 --- a/met/src/tools/other/modis_regrid/modis_file.cc +++ b/met/src/tools/other/modis_regrid/modis_file.cc @@ -369,9 +369,11 @@ status = get_double_data(sst, n0, n1, dt); if ( !status || (dt < 0.0) ) { - mlog << Error - << "\n\n ModisFile::open(const char *) -> bad scan start time (" - << dt << ") in file \"" << _filename << "\"\n\n"; + if ( status ) { + mlog << Error + << "\n\n ModisFile::open(const char *) -> bad scan start time (" + << dt << ") in file \"" << _filename << "\"\n\n"; + } close(); @@ -794,12 +796,10 @@ double ModisFile::lat(int n0, int n1) const { -double v; +double v = bad_data_double; float f[2]; -(void) get_float_data(Latitude, n0, n1, f[0]); - -v = f[0]; +if (get_float_data(Latitude, n0, n1, f[0])) v = f[0]; return ( v ); @@ -813,14 +813,16 @@ double ModisFile::lon(int n0, int n1) const { -double v; +double v = bad_data_double; float f[2]; -(void) get_float_data(Longitude, n0, n1, f[0]); +if (get_float_data(Longitude, n0, n1, f[0])) { + + v = f[0]; -v = f[0]; + v = -v; // west longitude positive -v = -v; // west longitude positive +} return ( v ); @@ -881,22 +883,22 @@ switch ( NumberType ) { case nt_int_8: status = get_int8_data (Field, n0, n1, c); - value = (double) c; + if (status) value = (double) c; break; case nt_int_16: status = get_int16_data (Field, n0, n1, s); - value = (double) s; + if (status) value = (double) s; break; case nt_float_32: status = get_float_data (Field, n0, n1, f); - value = (double) f; + if (status) value = (double) f; break; case nt_float_64: status = get_double_data (Field, n0, n1, d); - value = d; + if (status) value = d; break; @@ -907,7 +909,6 @@ switch ( NumberType ) { << "\n\n"; exit ( 1 ); - break; } // switch From 72cc21ebca265f2fd71ab4182d6f0374a0810a5f Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 30 Jul 2021 15:49:23 -0600 Subject: [PATCH 110/200] #1855 Check if ldf is null pointer --- met/src/basic/vx_util/data_line.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/met/src/basic/vx_util/data_line.cc b/met/src/basic/vx_util/data_line.cc index 0a155a8eb2..155e7a449e 100644 --- a/met/src/basic/vx_util/data_line.cc +++ b/met/src/basic/vx_util/data_line.cc @@ -522,6 +522,8 @@ bool DataLine::read_single_text_line(LineDataFile * ldf) { +if ( !ldf ) return ( false ); + #ifdef WITH_PYTHON PyLineDataFile * pldf = dynamic_cast(ldf); @@ -530,7 +532,7 @@ if ( pldf ) { const bool status = read_py_single_text_line(pldf); - return ( status ); + return ( status ); } From 4935a50f92872d43558a21a2d8eeebc8167c67ac Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 30 Jul 2021 15:50:39 -0600 Subject: [PATCH 111/200] #1855 Removed break after exit --- met/src/libcode/vx_data2d_factory/var_info_factory.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/met/src/libcode/vx_data2d_factory/var_info_factory.cc b/met/src/libcode/vx_data2d_factory/var_info_factory.cc index 354be867c0..5deb64d629 100644 --- a/met/src/libcode/vx_data2d_factory/var_info_factory.cc +++ b/met/src/libcode/vx_data2d_factory/var_info_factory.cc @@ -71,13 +71,13 @@ VarInfo * VarInfoFactory::new_var_info(GrdFileType type) case FileType_Gb2: #ifdef WITH_GRIB2 vi = new VarInfoGrib2; + break; #else mlog << Error << "\nVarInfoFactory::new_var_info() -> " << "Support for GRIB2 has not been compiled!\n" << "To read GRIB2 files, recompile with the --enable-grib2 option.\n\n"; exit(1); #endif - break; case FileType_NcMet: vi = new VarInfoNcMet; @@ -94,31 +94,29 @@ VarInfo * VarInfoFactory::new_var_info(GrdFileType type) p->set_file_type(type); vi = p; p = 0; + break; #else mlog << Error << "\nVarInfoFactory::new_var_info() -> " << "Support for Python has not been compiled!\n" << "To run Python scripts, recompile with the --enable-python option.\n\n"; exit(1); #endif - break; case FileType_NcCF: - vi = new VarInfoNcCF; - break; + vi = new VarInfoNcCF; + break; case FileType_HdfEos: mlog << Error << "\nVarInfoFactory::new_var_info() -> " << "Support for GrdFileType = " << grdfiletype_to_string(type) << " not yet implemented!\n\n"; exit(1); - break; default: mlog << Error << "\nVarInfoFactory::new_var_info() -> " << "unsupported gridded data file type \"" << grdfiletype_to_string(type) << "\"\n\n"; exit(1); - break; } // end switch mlog << Debug(4) From 07b700fe583794821c406d6039afd3dd8fb77015 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 30 Jul 2021 15:51:39 -0600 Subject: [PATCH 112/200] #1855 Removed break after exit --- met/src/basic/vx_log/concat_string.cc | 1 - met/src/basic/vx_util/data_plane_util.cc | 1 - met/src/basic/vx_util/interp_util.cc | 4 -- met/src/basic/vx_util/ordinal.cc | 1 - met/src/basic/vx_util/read_fortran_binary.cc | 3 -- met/src/basic/vx_util/roman_numeral.cc | 1 - met/src/basic/vx_util/two_to_one.cc | 2 - met/src/libcode/vx_afm/afm.cc | 41 ------------------- met/src/libcode/vx_afm/afm_token.cc | 1 - met/src/libcode/vx_analysis_util/stat_job.cc | 2 - .../vx_data2d_factory/data2d_factory.cc | 4 -- .../vx_data2d_grib/data2d_grib_utils.cc | 2 - .../libcode/vx_data2d_grib/grib_strings.cc | 1 - .../libcode/vx_data2d_python/data2d_python.cc | 1 - met/src/libcode/vx_grid/st_grid.cc | 1 - met/src/libcode/vx_pb_util/do_blocking.cc | 1 - met/src/libcode/vx_pb_util/do_unblocking.cc | 2 - met/src/libcode/vx_pb_util/pblock.cc | 1 - met/src/libcode/vx_ps/vx_ps.cc | 9 ---- met/src/libcode/vx_regrid/vx_regrid.cc | 1 - met/src/libcode/vx_render/render_pbm.cc | 2 - met/src/libcode/vx_render/render_pcm.cc | 2 - met/src/libcode/vx_render/render_pgm.cc | 2 - met/src/libcode/vx_render/render_ppm.cc | 2 - met/src/libcode/vx_render/rle_filter.cc | 1 - met/src/libcode/vx_shapedata/shapedata.cc | 2 - .../libcode/vx_statistics/pair_data_point.cc | 1 - met/src/libcode/vx_tc_util/track_point.cc | 1 - .../ensemble_stat/ensemble_stat_conf_info.cc | 1 - .../core/grid_stat/grid_stat_conf_info.cc | 1 - .../core/point_stat/point_stat_conf_info.cc | 1 - .../core/series_analysis/series_analysis.cc | 1 - .../tools/other/gen_vx_mask/gen_vx_mask.cc | 1 - met/src/tools/other/gis_utils/gis_dump_shp.cc | 1 - met/src/tools/other/lidar2nc/hdf_utils.cc | 1 - met/src/tools/other/lidar2nc/lidar2nc.cc | 1 - met/src/tools/other/madis2nc/madis2nc.cc | 1 - .../tools/other/mode_graphics/cgraph_main.cc | 4 -- .../mode_graphics/mode_nc_output_file.cc | 1 - .../other/mode_graphics/plot_mode_field.cc | 4 +- .../other/modis_regrid/cloudsat_swath_file.cc | 2 - met/src/tools/other/wwmca_tool/af_file.cc | 1 - met/src/tools/other/wwmca_tool/wwmca_ref.cc | 2 - 43 files changed, 1 insertion(+), 115 deletions(-) diff --git a/met/src/basic/vx_log/concat_string.cc b/met/src/basic/vx_log/concat_string.cc index 9fea23870b..d325f0ad8c 100644 --- a/met/src/basic/vx_log/concat_string.cc +++ b/met/src/basic/vx_log/concat_string.cc @@ -834,7 +834,6 @@ switch ( c ) { mlog << Error << "\noperator<<(ostream &, CSInlineCommand) -> " << "bad CSInlineCommand value\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/basic/vx_util/data_plane_util.cc b/met/src/basic/vx_util/data_plane_util.cc index 7b01b09f71..0004abe0f8 100644 --- a/met/src/basic/vx_util/data_plane_util.cc +++ b/met/src/basic/vx_util/data_plane_util.cc @@ -155,7 +155,6 @@ void smooth_field(const DataPlane &dp, DataPlane &smooth_dp, << interpmthd_to_string(mthd) << "(" << mthd << ")\n\n"; exit(1); - break; } // Store the smoothed value diff --git a/met/src/basic/vx_util/interp_util.cc b/met/src/basic/vx_util/interp_util.cc index 98cfa27ea4..1f1de88bea 100644 --- a/met/src/basic/vx_util/interp_util.cc +++ b/met/src/basic/vx_util/interp_util.cc @@ -1014,8 +1014,6 @@ double compute_sfc_interp(const DataPlane &dp, mlog << Error << "\ncompute_sfc_interp() -> " << "unsupported interpolation method encountered: " << interpmthd_to_string(mthd) << "(" << mthd << ")\n\n"; - exit(1); - break; } delete gt; @@ -1187,7 +1185,6 @@ double compute_horz_interp(const DataPlane &dp, << "unsupported interpolation method encountered: " << interpmthd_to_string(mthd) << "(" << mthd << ")\n\n"; exit(1); - break; } delete gt; @@ -1331,7 +1328,6 @@ DataPlane valid_time_interp(const DataPlane &in1, const DataPlane &in2, << "unsupported interpolation method encountered: " << interpmthd_to_string(mthd) << "(" << mthd << ")\n\n"; exit(1); - break; } // Initialize diff --git a/met/src/basic/vx_util/ordinal.cc b/met/src/basic/vx_util/ordinal.cc index 415a9e2634..b99768acde 100644 --- a/met/src/basic/vx_util/ordinal.cc +++ b/met/src/basic/vx_util/ordinal.cc @@ -94,7 +94,6 @@ switch ( n ) { // mlog << Error << "\nordinal_suffix() -> totally confused!\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/basic/vx_util/read_fortran_binary.cc b/met/src/basic/vx_util/read_fortran_binary.cc index 2c37d4b16a..2d2edf38b0 100644 --- a/met/src/basic/vx_util/read_fortran_binary.cc +++ b/met/src/basic/vx_util/read_fortran_binary.cc @@ -71,7 +71,6 @@ switch ( rec_pad_length ) { mlog << Error << "\n\n read_fortran_binary() -> bad record pad size ... " << rec_pad_length << "\n\n"; exit ( 1 ); - break; } @@ -179,7 +178,6 @@ switch ( rec_pad_length ) { mlog << Error << "\n\n read_fortran_binary() -> bad record pad size ... " << rec_pad_length << "\n\n"; exit ( 1 ); - break; } @@ -316,7 +314,6 @@ switch ( rec_pad_length ) { default: mlog << Error << "\n\n peek_record_size() -> bad record pad length\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/basic/vx_util/roman_numeral.cc b/met/src/basic/vx_util/roman_numeral.cc index 61af948566..5ce42c0109 100644 --- a/met/src/basic/vx_util/roman_numeral.cc +++ b/met/src/basic/vx_util/roman_numeral.cc @@ -178,7 +178,6 @@ switch ( n/modulus ) { default: // shouldn't ever happen mlog << Error << "\nrn_add() -> can't handle integer " << n << "\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/basic/vx_util/two_to_one.cc b/met/src/basic/vx_util/two_to_one.cc index 3eb7142a18..584d53a17c 100644 --- a/met/src/basic/vx_util/two_to_one.cc +++ b/met/src/basic/vx_util/two_to_one.cc @@ -643,7 +643,6 @@ switch ( k ) { mlog << Error << "\nget_two_to_one() -> " << "bad input values\n\n"; exit ( 1 ); - break; } // switch @@ -696,7 +695,6 @@ switch ( k ) { mlog << Error << "\nget_one_to_two() -> " << "bad input values\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/libcode/vx_afm/afm.cc b/met/src/libcode/vx_afm/afm.cc index 23df3616e3..a36bb6b8e3 100644 --- a/met/src/libcode/vx_afm/afm.cc +++ b/met/src/libcode/vx_afm/afm.cc @@ -1412,7 +1412,6 @@ while ( (*in) >> line ) { mlog << Error << "\nAfm::read() -> bad keyword\n\n"; tok.dump(cerr); exit ( 1 ); - break; } // switch @@ -1614,7 +1613,6 @@ while ( (*in) >> line ) { mlog << Error << "\nAfm::do_startfontmetrics() -> bad keyword\n\n"; tok.dump(cerr); exit ( 1 ); - break; } // switch @@ -1623,10 +1621,6 @@ while ( (*in) >> line ) { } // while - - - - return; } @@ -1681,21 +1675,14 @@ while ( (*in) >> line ) { mlog << Error << "\nAfm::do_startcharmetrics() -> bad keyword\n\n"; tok.dump(cerr); exit ( 1 ); - break; } // switch - if ( tok.keyword == afm_keyword_EndCharMetrics ) break; - } // while - - - - return; } @@ -1746,7 +1733,6 @@ while ( (*in) >> line ) { mlog << Error << "\nAfm::do_startkerndata() -> bad keyword\n\n"; tok.dump(cerr); exit ( 1 ); - break; } // switch @@ -1757,10 +1743,6 @@ while ( (*in) >> line ) { } // while - - - - return; } @@ -1821,23 +1803,14 @@ while ( (*in) >> line ) { mlog << Error << "\nAfm::do_startkernpairs() -> bad keyword\n\n"; tok.dump(cerr); exit ( 1 ); - break; } // switch if ( tok.keyword == afm_keyword_EndKernPairs ) break; - } // while - - - - - - - return; } @@ -1894,7 +1867,6 @@ while ( (*in) >> line ) { mlog << Error << "\nAfm::do_startcomposites() -> bad keyword\n\n"; tok.dump(cerr); exit ( 1 ); - break; } // switch @@ -1902,11 +1874,6 @@ while ( (*in) >> line ) { } // while - - - - - return; } @@ -1992,7 +1959,6 @@ while ( 1 ) { mlog << Error << "\nAfm::do_c(AfmLine &) -> bad token (2)\n\n"; tok.dump(cerr); exit ( 1 ); - break; } // switch @@ -2096,7 +2062,6 @@ while ( 1 ) { mlog << Error << "\nAfm::do_c(AfmLine &) -> bad token (2)\n\n"; tok.dump(cerr); exit ( 1 ); - break; } // switch @@ -2104,12 +2069,6 @@ while ( 1 ) { } // while - - - - - - return; } diff --git a/met/src/libcode/vx_afm/afm_token.cc b/met/src/libcode/vx_afm/afm_token.cc index 45d59be0f3..9dbf1926b4 100644 --- a/met/src/libcode/vx_afm/afm_token.cc +++ b/met/src/libcode/vx_afm/afm_token.cc @@ -239,7 +239,6 @@ switch ( type ) { mlog << Error << "\nAfmToken::as_double() const -> bad token type!\n\n"; dump(cerr); exit ( 1 ); - break; }; diff --git a/met/src/libcode/vx_analysis_util/stat_job.cc b/met/src/libcode/vx_analysis_util/stat_job.cc index dcd03688dc..c6cfafddea 100644 --- a/met/src/libcode/vx_analysis_util/stat_job.cc +++ b/met/src/libcode/vx_analysis_util/stat_job.cc @@ -1974,7 +1974,6 @@ void STATAnalysisJob::setup_stat_file(int n_row, int n) { << "unexpected stat line type \"" << statlinetype_to_string(cur_lt) << "\"!\n\n"; exit(1); - break; } if(c > n_col) n_col = c; } @@ -2052,7 +2051,6 @@ void STATAnalysisJob::setup_stat_file(int n_row, int n) { << "unexpected stat line type \"" << statlinetype_to_string(out_lt) << "\"!\n\n"; exit(1); - break; } // diff --git a/met/src/libcode/vx_data2d_factory/data2d_factory.cc b/met/src/libcode/vx_data2d_factory/data2d_factory.cc index 75664a0d1a..8f2b4fcda8 100644 --- a/met/src/libcode/vx_data2d_factory/data2d_factory.cc +++ b/met/src/libcode/vx_data2d_factory/data2d_factory.cc @@ -108,7 +108,6 @@ MetPythonDataFile * p = 0; << "Support for Python has not been compiled!\n" << "To run Python scripts, recompile with the --enable-python option.\n\n"; exit(1); - break; #endif @@ -118,7 +117,6 @@ MetPythonDataFile * p = 0; << "Support for GrdFileType = \"" << grdfiletype_to_string(type) << "\" not yet implemented!\n\n"; exit(1); - break; case FileType_Bufr: @@ -126,7 +124,6 @@ MetPythonDataFile * p = 0; << "cannot use this factory to read files of type \"" << grdfiletype_to_string(type) << "\"\n\n"; exit(1); - break; case FileType_None: // For FileType_None, silently return a NULL pointer @@ -138,7 +135,6 @@ MetPythonDataFile * p = 0; << "unsupported gridded data file type \"" << grdfiletype_to_string(type) << "\"\n\n"; exit(1); - break; } // end switch diff --git a/met/src/libcode/vx_data2d_grib/data2d_grib_utils.cc b/met/src/libcode/vx_data2d_grib/data2d_grib_utils.cc index 8e6a694bdc..337526cc4c 100644 --- a/met/src/libcode/vx_data2d_grib/data2d_grib_utils.cc +++ b/met/src/libcode/vx_data2d_grib/data2d_grib_utils.cc @@ -664,7 +664,6 @@ void read_pds(const GribRecord &r, int &bms_flag, << "unexpected time unit of " << (int) pds->fcst_unit << ".\n\n"; exit(1); - break; } // @@ -735,7 +734,6 @@ void read_pds(const GribRecord &r, int &bms_flag, << "unexpected time range indicator of " << (int) pds->tri << ".\n\n"; exit(1); - break; } return; diff --git a/met/src/libcode/vx_data2d_grib/grib_strings.cc b/met/src/libcode/vx_data2d_grib/grib_strings.cc index 2380f10c2f..37a0152c7c 100644 --- a/met/src/libcode/vx_data2d_grib/grib_strings.cc +++ b/met/src/libcode/vx_data2d_grib/grib_strings.cc @@ -124,7 +124,6 @@ ConcatString get_grib_level_list_str(int k, int grib_level) << "unexpected value for k: " << k << "\n\n"; exit(1); - break; } // switch diff --git a/met/src/libcode/vx_data2d_python/data2d_python.cc b/met/src/libcode/vx_data2d_python/data2d_python.cc index 97fab35c6a..3aca4f0119 100644 --- a/met/src/libcode/vx_data2d_python/data2d_python.cc +++ b/met/src/libcode/vx_data2d_python/data2d_python.cc @@ -208,7 +208,6 @@ switch ( Type ) { // assumes Type is already set << "MetPythonDataFile::open(const char * script_filename) -> bad file type: " << grdfiletype_to_string(Type) << "\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/libcode/vx_grid/st_grid.cc b/met/src/libcode/vx_grid/st_grid.cc index 64ed1a062d..65246ae5fc 100644 --- a/met/src/libcode/vx_grid/st_grid.cc +++ b/met/src/libcode/vx_grid/st_grid.cc @@ -96,7 +96,6 @@ switch ( data.hemisphere ) { mlog << Error << "\nStereographicGrid::StereographicGrid(const StereographicData &) -> " << "bad hemisphere ...\"" << (data.hemisphere) << "\"\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/libcode/vx_pb_util/do_blocking.cc b/met/src/libcode/vx_pb_util/do_blocking.cc index 814da8beb5..1e3d48d6dc 100644 --- a/met/src/libcode/vx_pb_util/do_blocking.cc +++ b/met/src/libcode/vx_pb_util/do_blocking.cc @@ -131,7 +131,6 @@ switch ( padsize ) { mlog << Error << "\nwrite_pad() -> " << "bad pad size\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/libcode/vx_pb_util/do_unblocking.cc b/met/src/libcode/vx_pb_util/do_unblocking.cc index f4d5af6cf2..6e8b6b250f 100644 --- a/met/src/libcode/vx_pb_util/do_unblocking.cc +++ b/met/src/libcode/vx_pb_util/do_unblocking.cc @@ -99,7 +99,6 @@ switch ( padsize ) { mlog << Error << "\nread_pad() -> " << "bad pad size\n\n"; exit ( 1 ); - break; } // switch @@ -132,7 +131,6 @@ switch ( padsize ) { mlog << Error << "\nread_pad() -> " << "bad pad size\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/libcode/vx_pb_util/pblock.cc b/met/src/libcode/vx_pb_util/pblock.cc index 26196a8421..643dc06540 100644 --- a/met/src/libcode/vx_pb_util/pblock.cc +++ b/met/src/libcode/vx_pb_util/pblock.cc @@ -79,7 +79,6 @@ void pblock(const char *infile, const char *outfile, Action action) { << "unexpected action requested!\n\n"; exit(1); - break; } // diff --git a/met/src/libcode/vx_ps/vx_ps.cc b/met/src/libcode/vx_ps/vx_ps.cc index 68d311077b..668efdbaba 100644 --- a/met/src/libcode/vx_ps/vx_ps.cc +++ b/met/src/libcode/vx_ps/vx_ps.cc @@ -290,7 +290,6 @@ switch ( Orientation ) { mlog << Error << "\nvoid PSfile::do_prolog() -> bad document orientation ... " << documentorientation_to_string(Orientation) << "\n\n"; exit ( 1 ); - break; } @@ -303,7 +302,6 @@ switch ( Media ) { mlog << Error << "\nvoid PSfile::do_prolog() -> bad document media ... " << documentmedia_to_string(Media) << "\n\n"; exit ( 1 ); - break; } @@ -708,7 +706,6 @@ switch ( fill_flag ) { mlog << Error << "\nPSfile::write_single_node() -> " << "unrecognized fill flag: \"" << fill_flag << "\"\n\n"; exit ( 1 ); - break; } // switch @@ -1154,7 +1151,6 @@ switch ( Media ) { mlog << Error << "\nPSfile::set_media(DocumentMedia) -> bad media size ... " << documentmedia_to_string(Media) << "\n\n"; exit ( 1 ); - break; } @@ -1469,7 +1465,6 @@ switch ( f ) { mlog << Error << "\n\n PSfile::set_family(FontFamily) -> bad font family ... " << fontfamily_to_string(f) << "\n\n"; exit ( 1 ); - break; } // switch @@ -1971,7 +1966,6 @@ switch ( f ) { mlog << Error << "\n\n ff_to_roman() -> bad font family ... " << fontfamily_to_string(f) << "\n\n"; exit ( 1 ); - break; } // switch @@ -2005,7 +1999,6 @@ switch ( f ) { mlog << Error << "\n\n ff_to_italic() -> bad font family ... " << fontfamily_to_string(f) << "\n\n"; exit ( 1 ); - break; } // switch @@ -2039,7 +2032,6 @@ switch ( f ) { mlog << Error << "\n\n ff_to_bold() -> bad font family ... " << fontfamily_to_string(f) << "\n\n"; exit ( 1 ); - break; } // switch @@ -2073,7 +2065,6 @@ switch ( f ) { mlog << Error << "\n\n ff_to_bolditalic() -> bad font family ... " << fontfamily_to_string(f) << "\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/libcode/vx_regrid/vx_regrid.cc b/met/src/libcode/vx_regrid/vx_regrid.cc index 1094fd6c86..0a7da68e3e 100644 --- a/met/src/libcode/vx_regrid/vx_regrid.cc +++ b/met/src/libcode/vx_regrid/vx_regrid.cc @@ -64,7 +64,6 @@ switch ( info.method ) { << "bad interpolation method ... " << interpmthd_to_string(info.method) << "\n\n"; exit(1); - break; } // switch info.method diff --git a/met/src/libcode/vx_render/render_pbm.cc b/met/src/libcode/vx_render/render_pbm.cc index af98e535fd..979c3bb12c 100644 --- a/met/src/libcode/vx_render/render_pbm.cc +++ b/met/src/libcode/vx_render/render_pbm.cc @@ -102,7 +102,6 @@ for (j=0; j<(info.n_filters()); ++j) { default: mlog << Error << "\nrender()(pbm) -> bad filter: \"" << (info.filter(j)) << "\"\n\n"; exit ( 1 ); - break; } // switch @@ -161,7 +160,6 @@ for (j=(info.n_filters() - 1); j>= 0; --j) { default: mlog << Error << "\nrender() -> bad filter: \"" << (info.filter(j)) << "\"\n\n"; exit ( 1 ); - break; } // swtich diff --git a/met/src/libcode/vx_render/render_pcm.cc b/met/src/libcode/vx_render/render_pcm.cc index 3246800645..eb8e82bb4b 100644 --- a/met/src/libcode/vx_render/render_pcm.cc +++ b/met/src/libcode/vx_render/render_pcm.cc @@ -90,7 +90,6 @@ for (j=0; j<(info.n_filters()); ++j) { default: mlog << Error << "\nrender_color_24() -> bad filter: \"" << (info.filter(j)) << "\"\n\n"; exit ( 1 ); - break; } // switch @@ -150,7 +149,6 @@ for (j=(info.n_filters() - 1); j>= 0; --j) { default: mlog << Error << "\nrender() -> bad filter: \"" << (info.filter(j)) << "\"\n\n"; exit ( 1 ); - break; } // swtich diff --git a/met/src/libcode/vx_render/render_pgm.cc b/met/src/libcode/vx_render/render_pgm.cc index 9a199c6d47..76f2d4a33e 100644 --- a/met/src/libcode/vx_render/render_pgm.cc +++ b/met/src/libcode/vx_render/render_pgm.cc @@ -86,7 +86,6 @@ for (j=0; j<(info.n_filters()); ++j) { default: mlog << Error << "\nrender()(pgm) -> bad filter: \"" << (info.filter(j)) << "\"\n\n"; exit ( 1 ); - break; } // switch @@ -145,7 +144,6 @@ for (j=(info.n_filters() - 1); j>= 0; --j) { default: mlog << Error << "\nrender() -> bad filter: \"" << (info.filter(j)) << "\"\n\n"; exit ( 1 ); - break; } // swtich diff --git a/met/src/libcode/vx_render/render_ppm.cc b/met/src/libcode/vx_render/render_ppm.cc index 2b1a63ff6c..20d9f2e1ad 100644 --- a/met/src/libcode/vx_render/render_ppm.cc +++ b/met/src/libcode/vx_render/render_ppm.cc @@ -77,7 +77,6 @@ for (j=0; j<(info.n_filters()); ++j) { default: mlog << Error << "\nrender()(ppm) -> bad filter: \"" << (info.filter(j)) << "\"\n\n"; exit ( 1 ); - break; } // switch @@ -140,7 +139,6 @@ for (j=(info.n_filters() - 1); j>= 0; --j) { default: mlog << Error << "\nrender() -> bad filter: \"" << (info.filter(j)) << "\"\n\n"; exit ( 1 ); - break; } // swtich diff --git a/met/src/libcode/vx_render/rle_filter.cc b/met/src/libcode/vx_render/rle_filter.cc index 39607b27b7..951c974d3a 100644 --- a/met/src/libcode/vx_render/rle_filter.cc +++ b/met/src/libcode/vx_render/rle_filter.cc @@ -76,7 +76,6 @@ switch ( mode ) { default: mlog << Error << "\nRunLengthEncodeFilter::eat(unsigned char) -> bad mode\n\n"; exit ( 1 ); - break; } diff --git a/met/src/libcode/vx_shapedata/shapedata.cc b/met/src/libcode/vx_shapedata/shapedata.cc index 4a0016ea59..319aa69e81 100644 --- a/met/src/libcode/vx_shapedata/shapedata.cc +++ b/met/src/libcode/vx_shapedata/shapedata.cc @@ -1801,7 +1801,6 @@ void boundary_step(const ShapeData &sd, int &xn, int &yn, int &direction) { mlog << Error << "\nboundary_step() -> " << "bad direction: " << direction << "\n\n"; exit(1); - break; } // @@ -1836,7 +1835,6 @@ void boundary_step(const ShapeData &sd, int &xn, int &yn, int &direction) { << "bad step case: " << get_step_case(lr, ur, ul, ll) << "\n\n"; exit(1); - break; } return; diff --git a/met/src/libcode/vx_statistics/pair_data_point.cc b/met/src/libcode/vx_statistics/pair_data_point.cc index 361939a010..daa40d1e9d 100644 --- a/met/src/libcode/vx_statistics/pair_data_point.cc +++ b/met/src/libcode/vx_statistics/pair_data_point.cc @@ -1476,7 +1476,6 @@ bool check_fo_thresh(double f, double o, double cmn, double csd, mlog << Error << "\ncheck_fo_thresh() -> " << "Unexpected SetLogic value of " << type << ".\n\n"; exit(1); - break; } return(status); diff --git a/met/src/libcode/vx_tc_util/track_point.cc b/met/src/libcode/vx_tc_util/track_point.cc index 17946957f0..c3ae422777 100644 --- a/met/src/libcode/vx_tc_util/track_point.cc +++ b/met/src/libcode/vx_tc_util/track_point.cc @@ -270,7 +270,6 @@ void QuadInfo::set_quad_vals(QuadrantType ref_quad, << "unexpected quadrant type encountered \"" << quadranttype_to_string(ref_quad) << "\".\n\n"; exit(1); - break; } return; diff --git a/met/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc b/met/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc index ff21bcd27d..c3d1235197 100644 --- a/met/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc +++ b/met/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc @@ -1023,7 +1023,6 @@ int EnsembleStatVxOpt::n_txt_row(int i_txt_row) const { << "unexpected output type index value: " << i_txt_row << "\n\n"; exit(1); - break; } return(n); diff --git a/met/src/tools/core/grid_stat/grid_stat_conf_info.cc b/met/src/tools/core/grid_stat/grid_stat_conf_info.cc index 0bae27039c..d26a5fe088 100644 --- a/met/src/tools/core/grid_stat/grid_stat_conf_info.cc +++ b/met/src/tools/core/grid_stat/grid_stat_conf_info.cc @@ -1108,7 +1108,6 @@ int GridStatVxOpt::n_txt_row(int i_txt_row) const { << "unexpected output type index value: " << i_txt_row << "\n\n"; exit(1); - break; } return(n); diff --git a/met/src/tools/core/point_stat/point_stat_conf_info.cc b/met/src/tools/core/point_stat/point_stat_conf_info.cc index 02cb465771..e56352d4ad 100644 --- a/met/src/tools/core/point_stat/point_stat_conf_info.cc +++ b/met/src/tools/core/point_stat/point_stat_conf_info.cc @@ -1241,7 +1241,6 @@ int PointStatVxOpt::n_txt_row(int i_txt_row) const { << "unexpected output type index value: " << i_txt_row << "\n\n"; exit(1); - break; } return(n); diff --git a/met/src/tools/core/series_analysis/series_analysis.cc b/met/src/tools/core/series_analysis/series_analysis.cc index f00ce209ea..11462290e2 100644 --- a/met/src/tools/core/series_analysis/series_analysis.cc +++ b/met/src/tools/core/series_analysis/series_analysis.cc @@ -479,7 +479,6 @@ void get_series_data(int i_series, << "unexpected SeriesType value: " << series_type << "\n\n"; exit(1); - break; } // Setup the verification grid diff --git a/met/src/tools/other/gen_vx_mask/gen_vx_mask.cc b/met/src/tools/other/gen_vx_mask/gen_vx_mask.cc index 18eabfd993..3b20c7ad60 100644 --- a/met/src/tools/other/gen_vx_mask/gen_vx_mask.cc +++ b/met/src/tools/other/gen_vx_mask/gen_vx_mask.cc @@ -391,7 +391,6 @@ void process_mask_file(DataPlane &dp) { mlog << Error << "\nprocess_mask_file() -> " << "Unxpected MaskType value (" << mask_type << ")\n\n"; exit(1); - break; } // Clean up diff --git a/met/src/tools/other/gis_utils/gis_dump_shp.cc b/met/src/tools/other/gis_utils/gis_dump_shp.cc index a9ecb7c350..b41841931b 100644 --- a/met/src/tools/other/gis_utils/gis_dump_shp.cc +++ b/met/src/tools/other/gis_utils/gis_dump_shp.cc @@ -144,7 +144,6 @@ switch ( shape_type ) { << "\n\n " << program_name << ": shape file type \"" << shapetype_to_string(shape_type) << "\" is not supported\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/tools/other/lidar2nc/hdf_utils.cc b/met/src/tools/other/lidar2nc/hdf_utils.cc index d7cd7d5740..165d500bc3 100644 --- a/met/src/tools/other/lidar2nc/hdf_utils.cc +++ b/met/src/tools/other/lidar2nc/hdf_utils.cc @@ -152,7 +152,6 @@ switch ( type ) { mlog << Error << "sizeof_hdf_type() -> unrecognized hdf data type\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/tools/other/lidar2nc/lidar2nc.cc b/met/src/tools/other/lidar2nc/lidar2nc.cc index 547692cf24..4ee2e1adb9 100644 --- a/met/src/tools/other/lidar2nc/lidar2nc.cc +++ b/met/src/tools/other/lidar2nc/lidar2nc.cc @@ -252,7 +252,6 @@ switch ( hdf_type ) { << program_name << ": hdf_type_to_nc_type() -> unrecognized hdf data type ... " << hdf_type << "\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/tools/other/madis2nc/madis2nc.cc b/met/src/tools/other/madis2nc/madis2nc.cc index 47c327eb06..29c5479f40 100644 --- a/met/src/tools/other/madis2nc/madis2nc.cc +++ b/met/src/tools/other/madis2nc/madis2nc.cc @@ -335,7 +335,6 @@ void process_madis_file(const char *madis_file) { << "MADIS type (" << my_mtype << ") not currently supported.\n\n"; exit(1); - break; } // Close the input NetCDF file diff --git a/met/src/tools/other/mode_graphics/cgraph_main.cc b/met/src/tools/other/mode_graphics/cgraph_main.cc index 6ed1092825..2e596a23b4 100644 --- a/met/src/tools/other/mode_graphics/cgraph_main.cc +++ b/met/src/tools/other/mode_graphics/cgraph_main.cc @@ -292,7 +292,6 @@ switch ( Ptype ) { << cgraphbase_plottype_to_string(Ptype) << " is not yet supported.\n\n"; exit ( 1 ); - break; } // switch @@ -1035,7 +1034,6 @@ if ( render_flag ) { mlog << Error << "\n\n CgraphBase::write_centered_text() -> fill_flag " << fill_flag << " is not supported\n\n"; exit ( 1 ); - break; } // switch @@ -1461,7 +1459,6 @@ switch ( k ) { default: mlog << Error << "\n\n CgraphBase::setlinecap(int) -> bad value ... " << k << "\n\n"; exit ( 1 ); - break; } // switch @@ -1495,7 +1492,6 @@ switch ( k ) { default: mlog << Error << "\n\n CgraphBase::setlinejoin(int) -> bad value ... " << k << "\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/tools/other/mode_graphics/mode_nc_output_file.cc b/met/src/tools/other/mode_graphics/mode_nc_output_file.cc index 708ece18cf..641bf1b408 100644 --- a/met/src/tools/other/mode_graphics/mode_nc_output_file.cc +++ b/met/src/tools/other/mode_graphics/mode_nc_output_file.cc @@ -725,7 +725,6 @@ for (x=0; x bad field\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/tools/other/mode_graphics/plot_mode_field.cc b/met/src/tools/other/mode_graphics/plot_mode_field.cc index 51516be279..23f12ba4bc 100644 --- a/met/src/tools/other/mode_graphics/plot_mode_field.cc +++ b/met/src/tools/other/mode_graphics/plot_mode_field.cc @@ -472,10 +472,9 @@ switch ( plot_field ) { n_obs = mode_in.n_obs_clus_objs(); break; - default: + default: mlog << Error << "\n\n " << program_name << ": do_plot() -> bad field selected\n\n"; exit ( 1 ); - break; } // switch @@ -1329,7 +1328,6 @@ switch ( plot_field ) { default: mlog << Error << "\n\n " << program_name << ": annotate() -> bad plot field\n\n"; exit ( 1 ); - break; } diff --git a/met/src/tools/other/modis_regrid/cloudsat_swath_file.cc b/met/src/tools/other/modis_regrid/cloudsat_swath_file.cc index 49d6fc5d4d..c3d60ab1ab 100644 --- a/met/src/tools/other/modis_regrid/cloudsat_swath_file.cc +++ b/met/src/tools/other/modis_regrid/cloudsat_swath_file.cc @@ -401,7 +401,6 @@ for (j=0; j bad number type ... " << numbertype_to_string(Numbertype) << "\n\n"; exit ( 1 ); - break; } // switch @@ -573,7 +572,6 @@ switch ( Numbertype ) { << "\n\n SatAttribute::set_value() -> bad numbertype ... " << numbertype_to_string(Numbertype) << "\n\n"; exit ( 1 ); - break; } // switch diff --git a/met/src/tools/other/wwmca_tool/af_file.cc b/met/src/tools/other/wwmca_tool/af_file.cc index 8e42f35045..1a60ecd0f8 100644 --- a/met/src/tools/other/wwmca_tool/af_file.cc +++ b/met/src/tools/other/wwmca_tool/af_file.cc @@ -163,7 +163,6 @@ switch ( Hemisphere ) { default: mlog << Error << "\nAFDataFile::assign(const AFDataFile &) -> bad hemisphere ... " << Hemisphere << "\n\n"; exit ( 1 ); - break; } diff --git a/met/src/tools/other/wwmca_tool/wwmca_ref.cc b/met/src/tools/other/wwmca_tool/wwmca_ref.cc index 828e517485..ab52792d8b 100644 --- a/met/src/tools/other/wwmca_tool/wwmca_ref.cc +++ b/met/src/tools/other/wwmca_tool/wwmca_ref.cc @@ -384,7 +384,6 @@ if ( Width > 1 ) { << "\n\n WwmcaRegridder::set_config(MetConfig & wc, const char * config_filename) -> " << "bad interpolation method ... " << interpmthd_to_string(Method) << "\n\n"; exit ( 1 ); - break; } // switch @@ -479,7 +478,6 @@ switch ( Hemi ) { mlog << Error << "\nWwmcaRegridder::get_interpolated_data(DataPlane &) const -> " << "bad hemisphere ... " << junk << "\n\n"; exit ( 1 ); - break; } // switch From ce3fcee8f03fe2910cf3c5760d52029adf035463 Mon Sep 17 00:00:00 2001 From: johnhg Date: Mon, 2 Aug 2021 10:52:25 -0600 Subject: [PATCH 113/200] Update pcp_combine.cc --- met/src/tools/core/pcp_combine/pcp_combine.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/met/src/tools/core/pcp_combine/pcp_combine.cc b/met/src/tools/core/pcp_combine/pcp_combine.cc index 98353430b2..56d24002b5 100644 --- a/met/src/tools/core/pcp_combine/pcp_combine.cc +++ b/met/src/tools/core/pcp_combine/pcp_combine.cc @@ -1321,7 +1321,8 @@ void write_nc_data(unixtime nc_init, unixtime nc_valid, int nc_accum, NcVar nc_var; if (!var_info) { - mlog << Error << "\nwrite_nc_data() var_info is null.\n\n"; + mlog << Error << "\nwrite_nc_data() -> " + << "var_info is null.\n\n"; exit(1); } From 87de938fc07203bf016b9810583c04c74cbd9e5b Mon Sep 17 00:00:00 2001 From: johnhg Date: Mon, 2 Aug 2021 12:18:49 -0600 Subject: [PATCH 114/200] Feature 1864 config urls (#1868) * Per #1864, remove stale GitHub pages URL for the MET User's Guide. * Per #1864, found stale GitHub IO links in the issue templates. Should make this same fix in the develop and default branches for all the METplus repos. * Per #1864, fix stale GitHub IO link in the PR template. --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/ISSUE_TEMPLATE/enhancement_request.md | 2 +- .github/ISSUE_TEMPLATE/new_feature_request.md | 2 +- .github/ISSUE_TEMPLATE/task.md | 2 +- .github/pull_request_template.md | 2 +- met/data/config/TCStatConfig_default | 3 +-- 6 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index a22e24ef90..2bbe76335b 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -57,7 +57,7 @@ Consider the impact to the other METplus components. - [ ] [METplus](https://github.com/dtcenter/METplus/issues/new/choose), [MET](https://github.com/dtcenter/MET/issues/new/choose), [METdatadb](https://github.com/dtcenter/METdatadb/issues/new/choose), [METviewer](https://github.com/dtcenter/METviewer/issues/new/choose), [METexpress](https://github.com/dtcenter/METexpress/issues/new/choose), [METcalcpy](https://github.com/dtcenter/METcalcpy/issues/new/choose), [METplotpy](https://github.com/dtcenter/METplotpy/issues/new/choose) ## Bugfix Checklist ## -See the [METplus Workflow](https://dtcenter.github.io/METplus/Contributors_Guide/github_workflow.html) for details. +See the [METplus Workflow](https://metplus.readthedocs.io/en/latest/Contributors_Guide/github_workflow.html) for details. - [ ] Complete the issue definition above, including the **Time Estimate** and **Funding Source**. - [ ] Fork this repository or create a branch of **main_\**. Branch name: `bugfix__main__` diff --git a/.github/ISSUE_TEMPLATE/enhancement_request.md b/.github/ISSUE_TEMPLATE/enhancement_request.md index f84aa44202..0c7f6c1331 100644 --- a/.github/ISSUE_TEMPLATE/enhancement_request.md +++ b/.github/ISSUE_TEMPLATE/enhancement_request.md @@ -46,7 +46,7 @@ Consider the impact to the other METplus components. - [ ] [METplus](https://github.com/dtcenter/METplus/issues/new/choose), [MET](https://github.com/dtcenter/MET/issues/new/choose), [METdatadb](https://github.com/dtcenter/METdatadb/issues/new/choose), [METviewer](https://github.com/dtcenter/METviewer/issues/new/choose), [METexpress](https://github.com/dtcenter/METexpress/issues/new/choose), [METcalcpy](https://github.com/dtcenter/METcalcpy/issues/new/choose), [METplotpy](https://github.com/dtcenter/METplotpy/issues/new/choose) ## Enhancement Checklist ## -See the [METplus Workflow](https://dtcenter.github.io/METplus/Contributors_Guide/github_workflow.html) for details. +See the [METplus Workflow](https://metplus.readthedocs.io/en/latest/Contributors_Guide/github_workflow.html) for details. - [ ] Complete the issue definition above, including the **Time Estimate** and **Funding Source**. - [ ] Fork this repository or create a branch of **develop**. Branch name: `feature__` diff --git a/.github/ISSUE_TEMPLATE/new_feature_request.md b/.github/ISSUE_TEMPLATE/new_feature_request.md index 5fa488ead3..c76da8ce50 100644 --- a/.github/ISSUE_TEMPLATE/new_feature_request.md +++ b/.github/ISSUE_TEMPLATE/new_feature_request.md @@ -50,7 +50,7 @@ Consider the impact to the other METplus components. - [ ] [METplus](https://github.com/dtcenter/METplus/issues/new/choose), [MET](https://github.com/dtcenter/MET/issues/new/choose), [METdatadb](https://github.com/dtcenter/METdatadb/issues/new/choose), [METviewer](https://github.com/dtcenter/METviewer/issues/new/choose), [METexpress](https://github.com/dtcenter/METexpress/issues/new/choose), [METcalcpy](https://github.com/dtcenter/METcalcpy/issues/new/choose), [METplotpy](https://github.com/dtcenter/METplotpy/issues/new/choose) ## New Feature Checklist ## -See the [METplus Workflow](https://dtcenter.github.io/METplus/Contributors_Guide/github_workflow.html) for details. +See the [METplus Workflow](https://metplus.readthedocs.io/en/latest/Contributors_Guide/github_workflow.html) for details. - [ ] Complete the issue definition above, including the **Time Estimate** and **Funding source**. - [ ] Fork this repository or create a branch of **develop**. Branch name: `feature__` diff --git a/.github/ISSUE_TEMPLATE/task.md b/.github/ISSUE_TEMPLATE/task.md index 88dfc5c9d3..93e889017d 100644 --- a/.github/ISSUE_TEMPLATE/task.md +++ b/.github/ISSUE_TEMPLATE/task.md @@ -46,7 +46,7 @@ Consider the impact to the other METplus components. - [ ] [METplus](https://github.com/dtcenter/METplus/issues/new/choose), [MET](https://github.com/dtcenter/MET/issues/new/choose), [METdatadb](https://github.com/dtcenter/METdatadb/issues/new/choose), [METviewer](https://github.com/dtcenter/METviewer/issues/new/choose), [METexpress](https://github.com/dtcenter/METexpress/issues/new/choose), [METcalcpy](https://github.com/dtcenter/METcalcpy/issues/new/choose), [METplotpy](https://github.com/dtcenter/METplotpy/issues/new/choose) ## Task Checklist ## -See the [METplus Workflow](https://dtcenter.github.io/METplus/Contributors_Guide/github_workflow.html) for details. +See the [METplus Workflow](https://metplus.readthedocs.io/en/latest/Contributors_Guide/github_workflow.html) for details. - [ ] Complete the issue definition above, including the **Time Estimate** and **Funding Source**. - [ ] Fork this repository or create a branch of **develop**. Branch name: `feature__` diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f3d05479d2..450355440e 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -14,7 +14,7 @@ If **yes**, describe the new output and/or changes to the existing output:
- [ ] Please complete this pull request review by **[Fill in date]**.
## Pull Request Checklist ## -See the [METplus Workflow](https://dtcenter.github.io/METplus/Contributors_Guide/github_workflow.html) for details. +See the [METplus Workflow](https://metplus.readthedocs.io/en/latest/Contributors_Guide/github_workflow.html) for details. - [ ] Complete the PR definition above. - [ ] Ensure the PR title matches the feature or bugfix branch name. - [ ] Define the PR metadata, as permissions allow. diff --git a/met/data/config/TCStatConfig_default b/met/data/config/TCStatConfig_default index 3857a8501f..a9ea169154 100644 --- a/met/data/config/TCStatConfig_default +++ b/met/data/config/TCStatConfig_default @@ -17,8 +17,7 @@ // the analyses will be performed on their union. // // Each configuration filtering option may be overridden by a corresponding -// job command option of the same name, as described in the MET User's Guide: -// https://dtcenter.github.io/MET/latest/Users_Guide/tc-stat.html +// job command option of the same name, as described in the MET User's Guide. // // From 401af08df382f2977d5d8b8259cd8af9ad88d921 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 5 Aug 2021 13:50:07 -0600 Subject: [PATCH 115/200] Move ROC curve in Appendix C --- met/docs/Users_Guide/appendixC.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 3285d19e7d..754bd47729 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -924,14 +924,14 @@ MET produces hit rate (POD) and false alarm rate (POFD) values for each user-spe A ROC plot is shown for an example set of forecasts, with a solid line connecting the points for six user-specified thresholds (0.25, 0.35, 0.55, 0.65, 0.75, 0.85). The diagonal dashed line indicates no skill while the dash-dot line shows the ROC for a perfect forecast. -An ROC curve shows how well the forecast discriminates between two outcomes, so it is a measure of resolution. The ROC is invariant to linear transformations of the forecast, and is thus unaffected by bias. An unbiased (i.e., well-calibrated) forecast can have the same ROC as a biased forecast, though most would agree that an unbiased forecast is "better". Since the ROC is conditioned on the observations, it is often paired with the reliability diagram, which is conditioned on the forecasts. - .. _appendixC-roc_example: .. figure:: figure/appendixC-roc_example.jpg Example of ROC Curve +A ROC curve shows how well the forecast discriminates between two outcomes, so it is a measure of resolution. The ROC is invariant to linear transformations of the forecast, and is thus unaffected by bias. An unbiased (i.e., well-calibrated) forecast can have the same ROC as a biased forecast, though most would agree that an unbiased forecast is "better". Since the ROC is conditioned on the observations, it is often paired with the reliability diagram, which is conditioned on the forecasts. + Area Under the ROC curve (AUC) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 99475ae0a38b31f3771432a4e03bba158bd24710 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 5 Aug 2021 13:58:10 -0600 Subject: [PATCH 116/200] Crop ROC image for better PDF formatting --- .../figure/appendixC-roc_example.jpg | Bin 109405 -> 181295 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/met/docs/Users_Guide/figure/appendixC-roc_example.jpg b/met/docs/Users_Guide/figure/appendixC-roc_example.jpg index 5f3e25ba8e8ac5822bd646b3d9734522e6aa1013..6e7dc88a01ba5e5f8604bc85c9163bf8170c4c61 100644 GIT binary patch literal 181295 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±w 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�_0&qU+LEI?Ps_H1lVuVMg`*%VG^E8I4 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 z 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�gssXj=dDL)Mh=pZ;Dj@gEwc>iQD zSTv(-UY5Gf2rglV^cw92PL3Ek&(Pc(ul@JL2UW%fV}B+E+-J5MksE0$OOU8)%j}IH z>In}VtRBKTc>rrrL6~AaW~iTc)4i-#LPJtgBdN+W>SU!oK!|&= z;eoNT1|^M6u-FvOC2@!*20@%2SL>m|&3OCZ733w8ON$quZ%x`Q7leOAsLXpBf12fV z*XD$xG=yY;d-4UcZ06_Uhvun&z<$uN;YAS0g_Frc0$04}#Tx
kKo;9)h^xwYkXQ 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⪻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 Nt)X|n@}AxE{{vzvoeBT| literal 109405 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 w#0wKn4evgjwC$nGz2x6Qgv5Lj^)-mB zDGS;h7-og0-%1+EZUXoP%9=|5KDm}9iMed6Hv>y|m39)kF6N%{x|mopqphmes`5?f zAwRxn2uKJ5ISN}mm5LfBv6p#?TnAvt*I_hU5OO#*sKn}ZAJ!o6G-Nb(tan+I?j7U( z+FNy7g0<^J;9|>5In$RNe~RySat}j=ppMjn7@3_yX61A3`g^BZe#&Oua5;J>h&>hI z@3jj#pZMB4-J)ga=(-P*sM1kn|Wlx%6eYM@7v9kQZsHnvq zTqkwO9s8cg-Q4j!QCQ{XF~Jg+2w!aJMJISW5D|i$$A8<|{Ttg`(x%n(XH4JtWA?F= z+%gIic`gC_fTfQvFPJ&us#%&0B5^iX7Y7Edfz0cvORkDZVfTBu3MRptE1a*S$@h- zY7MEsd^`NjRT0J?peFdczbm)o-_Cvj++ni%(f&p=z4?#li!ED{7JdYZgOdd}b|)L$Gya|IJ56<-n&;J68PU|l2?xHilmic#sh0q@4nSeCC-%c9 zeRd#6$42$Be~-QBR%^xFhwHgB<3x9E-n?P%zL4L^RtkL_oA>Tnd%E@57nWT=_WzMQ zHmm=zb^WdB59c2}`tSUY)`$8Mw`KGFre0mvmY|pW?5St?ZPP7XUXzUb&KUo8eR!WU zGfrUpBzex4v+AacoJ*Ogt2>Fc+%}?xLHKSw1N9}Z zTl=43!R_m>YJsNSeU$$*=JDbC-+X};itl#O-^#8)(d$5iH`brB+9y$e)4dreF{`z1 zH|WUON%0T&|7N`f+=V%HEil$UzW&DtEJK>|UVq;Ox?~{7|Hg^C8TZBPxNXd@k(`sCF+Abt z``ftB@(*a|fUNVv8n?e&YdBZbC||WR|Ka!U^`U?ASM9tzO0I62bnj#;JI`dRmy_Ow za~yLjSS1;@e}Q&B+ly~;3e&?jU)pkGYjo>P-A7T2?s)9$RgmuZrnY4T^M~*MxYvHH z1>VtI|Dm89cpK{y><+uJ(y}%!h{qaIKUKrhMu3ZsPyGV0W?&G3M zo;=^Gqc~2BdoDfZ_2A!;xX8mRZk=RXC{lb_bAr6i;& Date: Thu, 5 Aug 2021 16:41:31 -0600 Subject: [PATCH 117/200] Shrink ROC image for better PDF formatting --- .../figure/appendixC-roc_example.jpg | Bin 181295 -> 95574 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/met/docs/Users_Guide/figure/appendixC-roc_example.jpg b/met/docs/Users_Guide/figure/appendixC-roc_example.jpg index 6e7dc88a01ba5e5f8604bc85c9163bf8170c4c61..d0680257f734c865fbea30be7cd7576aa86497c5 100644 GIT binary patch literal 95574 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±w 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�_0&qU+LEI?Ps_H1lVuVMg`*%VG^E8I4 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 z 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�gssXj=dDL)Mh=pZ;Dj@gEwc>iQD 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⪻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 Nt)X|n@}AxE{{vzvoeBT| From 71335ca099f09ac00c55367fd9d320041e967c89 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 5 Aug 2021 16:52:13 -0600 Subject: [PATCH 118/200] Modify figure alignment in conf.py --- met/docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/conf.py b/met/docs/conf.py index 16bb9bcd99..def45c32d7 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -47,11 +47,11 @@ 'papersize': 'letterpaper', 'releasename':"{version}", 'fncychap': '\\usepackage{fncychap}', - 'fontpkg': '\\usepackage{amsmath,amsfonts,amssymb,amsthm}', + 'fontpkg': '\\usepackage{amsmath,amsfonts,amssymb,amsthm,float}', 'inputenc': '\\usepackage[utf8]{inputenc}', 'fontenc': '\\usepackage[LGR,T1]{fontenc}', - 'figure_align':'htbp', + 'figure_align':'H', 'pointsize': '11pt', 'preamble': r''' From b1cced128dabb54364e1d3f5114cf36cedb33420 Mon Sep 17 00:00:00 2001 From: Keith Searight Date: Thu, 5 Aug 2021 17:00:55 -0600 Subject: [PATCH 119/200] Change text placement for ROC curve figure --- met/docs/Users_Guide/appendixC.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 754bd47729..10eb14f5d8 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -924,14 +924,14 @@ MET produces hit rate (POD) and false alarm rate (POFD) values for each user-spe A ROC plot is shown for an example set of forecasts, with a solid line connecting the points for six user-specified thresholds (0.25, 0.35, 0.55, 0.65, 0.75, 0.85). The diagonal dashed line indicates no skill while the dash-dot line shows the ROC for a perfect forecast. +A ROC curve shows how well the forecast discriminates between two outcomes, so it is a measure of resolution. The ROC is invariant to linear transformations of the forecast, and is thus unaffected by bias. An unbiased (i.e., well-calibrated) forecast can have the same ROC as a biased forecast, though most would agree that an unbiased forecast is "better". Since the ROC is conditioned on the observations, it is often paired with the reliability diagram, which is conditioned on the forecasts. + .. _appendixC-roc_example: .. figure:: figure/appendixC-roc_example.jpg Example of ROC Curve -A ROC curve shows how well the forecast discriminates between two outcomes, so it is a measure of resolution. The ROC is invariant to linear transformations of the forecast, and is thus unaffected by bias. An unbiased (i.e., well-calibrated) forecast can have the same ROC as a biased forecast, though most would agree that an unbiased forecast is "better". Since the ROC is conditioned on the observations, it is often paired with the reliability diagram, which is conditioned on the forecasts. - Area Under the ROC curve (AUC) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 68473951629aaade3a85cdd23ee42912af33345e Mon Sep 17 00:00:00 2001 From: lisagoodrich <33230218+lisagoodrich@users.noreply.github.com> Date: Thu, 12 Aug 2021 15:15:05 -0600 Subject: [PATCH 120/200] Feature 1834 faq (#1867) * testing possible new drop-down menus for FAQ * adding sphinx-panels to extensions to be able to use drop down menus in appendixA * Per #1834, adding sphinx-panels to requirements.txt to see if that fixes the error * Per #1834, added sphinx.ext to beginning of sphinx_panels to see if that fixes the error * Per #1834, remove sphinx.ext and add trailing comma to end of extensions to see if that fixed the error * Per #1834, added sphinx-panels to pip install command to see if that fixes the error * Per #1834, added extra space in comment to get docs to build to see if change to documentation.yml will fix an error * Per #1834, added return character to get rid of warning * testing dropdown menus #1 * testing dropdown menus #2 removing lines and dotted lines * testing #3 * testing 4 * fixing numbering, removing 2nd pulldown menu, trying to fix box width * adding code block in dropdown * trying to fix width * trying to fix width with spacing * trying to fix width with spacing 2nd dropdown * removing panels * solved problem, just use dropdown no panels * adding second dropdown menu * removing the dropdown menus and fixing the spacing. * fixing typos * adding in matched pairs * adding in formating files for NetCDF and making FILE_IO a header * fixing spacing * time slice * fixing spacing * UNIX time conversion * fixing spacing * fixed-width * scientific notation * removing which per Julie P * adding Gen_Vx_Mask section * fixing formatting * changing to numbers * complex masking region * neighborhood methods boundaries * Neighborhood Methods to Compute Fraction * adding Grid_Stat - How do I use Config File Setup to Read a NetCDF file * using backticks with asterics * one more backtick with asterics * Grid_Stat - What would be an example of Verifying Probabilities * fixing typos * What is an example of using Grid-Stat with Regridding and Masking Turned On * fixing typos * Grid_Stat - What would be an example of Verifying Probabilities Example2 * trying to fix typos * trying to fix code-block spacing * Per #1834, attempting to fix warning. * How do I use different masks in MET tools using MODE as an example * trying to fix bullet list * trying to fix bullet list 2 * trying to fix bullet list 2 * trying to fix bullet list 3 * Per #1834, attempting formatting changes * Per #1834, attempting formatting changes * Per #1834, attempting formatting changes * Per #1834, attempting formatting changes * Per #1834, attempting formatting changes * Per #1834, modified formatting, including adding backslashes and removing extra returns in command line calls, and adding indentation for config file notation, and adding a return after each 'A.' * Per #1834, changed code-block from ini to none to fix formatting * *Pcp-Combine - What are some examples using -add * Pcp-Combine - How do I add and subtract with Pcp-Combine * Pcp-Combine - How do I Combine 12-hour Accumulated Precipitation from Two Different Initialization Times * Pcp-Combine - How Do I Correct a Precipitation Time Range * Pcp-Combine - What Data Formats does MET Read * Pcp-Combine - How does pass through work * Pcp_Combine - How do I use -pcprx to run a project faster * Pcp-Combine - How Do I Enter the Time Format Correctly * Pcp-Combine - How do I use -subtract * fixing formatting * Pcp_Combine - How Do I Use -sum, -add, and -subtract to Achieve Same Accumulation Interval * Pcp-Combine - What is the difference between -sum vs. -add * Pcp-Combine - How Do I Select a Specific GRIB Record to Use * fixing spacing for original text * Plot-Data-Plane - How Do I Inspect Gen_Vx_Mask Output * fixing typo * Plot-Data-Plane - How Do I Specify GRIB Version * Plot-Data-Plane - last 2 entries * 2 misc. entries * fixing typo * Stat_Analysis - How does -aggregate_stat work * Stat_Analysis - remaining entries * fixing typo * tc-pairs * tc-stat * troubleshooting area * another stat-analysis * another stat-analysis * utilities * fixing dashes * Per #1834, trying out syntax * Per #1834, removing added syntax * fixing returns with bolding * Per #1834, modified formatting * adding italics for directories #1834 * replacing code-block ini with none to remove red lettering * fixing questions to lower case #1834 * linking to section using numref #1834 * linking to section using numref #1834 attempt 2 * linking to section using numref #1834 attempt 3 * linking to section using numref #1834 attempt 4 * linking to section using numref #1834 attempt 5 * linking to section using numref #1834 attempt 6 * linking to section using numref #1834 attempt 7 * linking to section using numref #1834 attempt 8 * linking to anothre section #1834 * linking to another section #1834 * removing old info #1834 * grammar updates #1834 * grammar updates #1834 * fixing typos #1834 * email changes with Julie #1834 * trying to fix warning #1834 * changes #1834 * Per #1834, updating question titles and answers * Per #1834, made updates to the content. * Per #1834, made updates to the content * Per #1834, made updates to the content * Per #1834, made some major changes to the first 3 FAQ's. I don't have the time/bandwidth to review these completely at this time, but wanted to include at least these updates. * testing some of the updates John O. suggested. * updates John O. suggested take 2 #1834. * updates John O. suggested take 3 #1834. * updates John O. suggested take 4 #1834. * updates John O. suggested take 5 #1834. * updates John O. suggested. Some didn't show up even though they've been removed #1834. * trying to fix numbered list indenting #1834 * fixing numbered list indenting #1834 * cleaning up formatting #1834 * fixing broken links #1834 Co-authored-by: Julie.Prestopnik Co-authored-by: John Halley Gotway --- .github/workflows/documentation.yml | 2 +- met/docs/Users_Guide/appendixA.rst | 1820 +++++++++++++++++++++++- met/docs/Users_Guide/reformat_grid.rst | 1 + met/docs/conf.py | 3 +- met/docs/requirements.txt | 3 +- 5 files changed, 1791 insertions(+), 38 deletions(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 62c284aded..4c09b72413 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -24,7 +24,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade python-dateutil requests sphinx \ - sphinx-gallery Pillow sphinx_rtd_theme + sphinx-gallery Pillow sphinx_rtd_theme sphinx-panels - name: Build docs run: ./.github/jobs/build_documentation.sh - uses: actions/upload-artifact@v2 diff --git a/met/docs/Users_Guide/appendixA.rst b/met/docs/Users_Guide/appendixA.rst index f681f48361..7271ecb1de 100644 --- a/met/docs/Users_Guide/appendixA.rst +++ b/met/docs/Users_Guide/appendixA.rst @@ -6,97 +6,1847 @@ Appendix A FAQs & How do I ... ? Frequently Asked Questions __________________________ -**Q. Why was the MET written largely in C++ instead of FORTRAN?** +File-IO +~~~~~~~ + +**Q. File-IO - How do I improve the speed of MET tools using Gen-Vx-Mask?** + +A. +The main reason to run gen_vx_mask is to make the MET +statistics tools (e.g. point_stat, grid_stat, or ensemble_stat) run +faster. The verification masking regions in those tools can be specified +as Lat/Lon polyline files or the NetCDF output of gen_vx_mask. However, +determining which grid points are inside/outside a polyline region can be +slow if the polyline contains many points or the grid is dense. Running +gen_vx_mask once to create a binary mask is much more efficient than +recomputing the mask when each MET statistics tool is run. If the polyline +only contains a small number of points or the grid is sparse running +gen_vx_mask first would only save a second or two. + +**Q. File-IO - How do I use map_data?** + +A. +The MET repository includes several map data files. Users can modify which +map datasets are included in the plots created by modifying the +configuration files for those tools. The default map datasets are defined +by the map_data dictionary in the ConfigMapData file. + +.. code-block:: none + + map_data = { + + line_color = [ 25, 25, 25 ]; // rgb triple values, 0-255 + line_width = 0.5; + line_dash = ""; + + source = [ + { file_name = "MET_BASE/map/country_data"; }, + { file_name = "MET_BASE/map/usa_state_data"; }, + { file_name = "MET_BASE/map/major_lakes_data"; } + ]; + } + +Users can modify the ConfigMapData contents prior to running 'make install'. +This will change the default map data for all of the MET tools which plots. +Alternatively, users can copy/paste/modify the map_data dictionary into the +configuration file for a MET tool. For example, you could add map_data to +the end of the MODE configuration file to customize plots created by MODE. + +Here is an example of running plot_data_plane and specifying the map_data +in the configuration string on the command line: + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/plot_data_plane + sample.grib china_tmp_2m_admin.ps \ + 'name="TMP"; level="Z2"; \ + map_data = { source = [ { file_name = \ + "${MET_BUILD_BASE}/data/map/admin_by_country/admin_China_data"; } \ + ]; }' + +**Q. FILE-IO - How can I understand the number of matched pairs?** + +A. +Statistics are computed on matched forecast/observation pairs data. +For example, if the dimension of the grid is 37x37 up to +1369 matched pairs are possible. However, if the forecast or +observation contains bad data at a point, that matched pair would +not be included in the calculations. There are a number of reasons that +observations could be rejected - mismatches in station id, variable names, +valid times, bad values, data off the grid, etc. +For example, if the forecast field contains missing data around the +edge of the domain, then that is a reason there may be 992 matched pairs +instead of 1369. Users can use the ncview tool to look at an example +netCDF file or run their files through plot_data_plane to help identify +any potential issues. + +One common support question is "Why am I getting 0 matched pairs from +Point-Stat?". As mentioned above, there are many reasons why point +observations can be excluded from your analysis. If running point_stat with +at least verbosity level 2 (-v 2, the default value), zero matched pairs +will result in the following type of log messages to be printed: + +.. code-block:: none + + DEBUG 2: Processing TMP/Z2 versus TMP/Z2, for observation type ADPSFC, over region FULL, for interpolation method UW_MEAN(1), using 0 pairs. + DEBUG 2: Number of matched pairs = 0 + DEBUG 2: Observations processed = 1166 + DEBUG 2: Rejected: station id = 0 + DEBUG 2: Rejected: obs var name = 1166 + DEBUG 2: Rejected: valid time = 0 + DEBUG 2: Rejected: bad obs value = 0 + DEBUG 2: Rejected: off the grid = 0 + DEBUG 2: Rejected: topography = 0 + DEBUG 2: Rejected: level mismatch = 0 + DEBUG 2: Rejected: quality marker = 0 + DEBUG 2: Rejected: message type = 0 + DEBUG 2: Rejected: masking region = 0 + DEBUG 2: Rejected: bad fcst value = 0 + DEBUG 2: Rejected: bad climo mean = 0 + DEBUG 2: Rejected: bad climo stdev = 0 + DEBUG 2: Rejected: mpr filter = 0 + DEBUG 2: Rejected: duplicates = 0 + +This list of the rejection reason counts above matches the order in +which the filtering logic is applied in the code. In this example, +none of the point observations match the variable name requested +in the configuration file. So all of the 1166 observations are rejected +for the same reason. + +**Q. FILE-IO - What types of NetCDF files can MET read?** + +A. +There are three flavors of NetCDF that MET can read directly. + +1. Gridded NetCDF output from one of the MET tools + +2. Output from the WRF model that has been post-processed using the wrf_interp utility + +3. NetCDF data following the `climate-forecast (CF) convention + `_ + +Lastly, users can write python scripts to pass data that's gridded to the +MET tools in memory. If the data doesn't fall into one of those categories, +then it's not a gridded dataset that MET can handle directly. Satellite data, +in general, will not be gridded. Typically it contains a dense mesh of data at +lat/lon points, but typically those lat/lon points are not evenly spaced onto +a regular grid. + +While MET's point2grid tool does support some satellite data inputs, it is +limited. Using python embedding is another option for handling new datasets +not supported natively by MET. + +**Q. FILE-IO - How do I choose a time slice in a NetCDF file?** + +A. +When processing NetCDF files, the level information needs to be +specified to tell MET which 2D slice of data to use. There is +currently no way to explicitly define which time slice to use +other than selecting the time index. + +Let's use plot_data_plane as an example: + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/plot_data_plane \ + MERGE_20161201_20170228.nc \ + obs.ps \ + 'name="APCP"; level="(5,*,*)";' + +Assuming that the first array is the time, this will select the 6-th +time slice of the APCP data and plot it since these indices are 0-based. + +**Q. FILE-IO - How do I use the UNIX time conversion?** + +A. +Regarding the timing information in the NetCDF variable attributes: + +.. code-block:: none + + APCP_24:init_time_ut = 1306886400 ; + +“ut” stands for UNIX time, which is the number of seconds +since Jan 1, 1970. It is a convenient way of storing timing +information since it is easy to add/subtract. The UNIX date command +can be used to convert back/forth between unix time and time strings: + +To convert unix time to ymd_hms date: + +.. code-block:: none + + date -ud '1970-01-01 UTC '1306886400' seconds' +%Y%m%d_%H%M%S 20110601_000000 + +To convert ymd_hms to unix date: + +.. code-block:: none + + date -ud ''2011-06-01' UTC '00:00:00'' +%s 1306886400 + +Regarding TRMM data, it may be easier to work with the binary data and +use the trmm2nc.R script described on this +`page `_ +under observation datasets. + +Follow the TRMM binary links to either the 3 or 24-hour accumulations, +save the files, and run them through that script. That is faster +and easier than trying to get an ASCII dump. That Rscript can also +subset the TRMM data if needed. Look for the section of it titled +"Output domain specification" and define the lat/lon's that needs +to be included in the output. + +**Q. Does MET use a fixed-width output format for its ASCII output files?** + +A. +MET does not use the Fortran-like fixed width format in its +ASCII output file. Instead, the column widths are adjusted for each +run to insert at least one space between adjacent columns. The header +columns of the MET output contain user-defined strings which may be +of arbitrary length. For example, columns such as MODEL, OBTYPE, and +DESC may be set by the user to any string value. Additionally, the +amount of precision written is also configurable. The +"output_precision" config file entry can be changed from its default +value of 5 decimal places to up to 12 decimal places, which would also +impact the column widths of the output. + +Due to these issues, it is not possible to select a reasonable fixed +width for each column ahead of time. The AsciiTable class in MET does +a lot of work to line up the output columns, to make sure there is +at least one space between them. + +If a fixed-width format is needed, the easiest option would be +writing a script to post-process the MET output into the fixed-width +format that is needed or that the code expects. + +**Q. Do the ASCII output files created by MET use scientific notation?** + +A. +By default, the ASCII output files created by MET make use of +scientific notation when appropriate. The formatting of the +numbers that the AsciiTable class writes is handled by a call +to printf. The "%g" formatting option can result in +scientific notation: +http://www.cplusplus.com/reference/cstdio/printf/ + +It has been recommended that a configuration option be added to +MET to disable the use of scientific notation. That enhancement +is planned for a future release. + +Gen-Vx-Mask +~~~~~~~~~~~ + +**Q. Gen-Vx-Mask - I have a list of stations to use for verification. +I also have a poly region defined. If I specify both of these should +the result be a union of them?** + +A. +These settings are defined in the "mask" section of the Point-Stat +configuration file. You can define masking regions in one of 3 ways, +as a "grid", a "poly" line file, or a "sid" list of station ID's. + +If you specify one entry for "poly" and one entry for "sid", you +should see output for those two different masks. Note that each of +these settings is an array of values, as indicated by the square +brackets "[]" in the default config file. If you specify 5 grids, +3 poly's, and 2 SID lists, you'd get output for those 10 separate +masking regions. Point-Stat does not compute unions or intersections +of masking regions. Instead, they are each processed separately. + +Is it true that you really want to use a polyline to define an area +and then use a SID list to capture additional points outside of +that polyline? + +If so, your options are: + +1. Define one single SID list which include all the points currently + inside the polyline as well as the extra ones outside. + +2. Continue verifying using one polyline and one SID list and + write partial sums and contingency table counts. + +Then aggregate the results together by running a Stat-Analysis job. + +**Q. Gen-Vx-Mask - How do I define a masking region with a GFS file?** + +A. +Grab a sample GFS file: + +.. code-block:: none + + wget + http://www.ftp.ncep.noaa.gov/data/nccf/com/gfs/prod/gfs/2016102512/gfs.t12z.pgrb2.0p50.f000 + +Use the MET regrid_data_plane tool to put some data on a +lat/lon grid over Europe: + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/regrid_data_plane gfs.t12z.pgrb2.0p50.f000 \ + 'latlon 100 100 25 0 0.5 0.5' gfs_euro.nc -field 'name="TMP"; level="Z2";' + +Run the MET gen_vx_mask tool to apply your polyline to the European domain: + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/gen_vx_mask gfs_euro.nc POLAND.poly POLAND_mask.nc + +Run the MET plot_data_plane tool to display the resulting mask field: + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/plot_data_plane POLAND_mask.nc POLAND_mask.ps 'name="POLAND"; level="(*,*)";' + +In this example, the mask is in roughly the right spot, but there +are obvious problems with the latitude and longitude values used +to define that mask for Poland. + +Grid-Stat +~~~~~~~~~ + +**Q. Grid-Stat - How do I define a complex masking region?** + +A. +A user can define intersections and unions of multiple fields to define masks. +Prior to running Grid-Stat, the user can run the Gen-VX-Mask tool one or +more times to define a more complex masking area by thresholding multiple +fields. + +For example, using a forecast GRIB file (fcst.grb) which contains 2 records, +one for 2-m temperature and a second for 6-hr accumulated precip. The only +grid points that are desired are grid points below freezing with non-zero +precip. The user should run Gen-Vx-Mask twice - once to define the +temperature mask and a second time to intersect that with the precip mask: + +.. code-block:: none + + gen_vx_mask fcst.grb fcst.grb tmp_mask.nc \ + -type data \ + -mask_field 'name="TMP"; level="Z2"' -thresh le273 + gen_vx_mask tmp_mask.nc fcst.grb tmp_and_precip_mask.nc \ + -type data \ + -input_field 'name="TMP_Z2"; level="(*,*)";' \ + -mask_field 'name="APCP"; level="A6";' -thresh gt0 \ + -intersection -name "FREEZING_PRECIP" + +The first one is pretty straight-forward. + +1. The input field (fcst.grb) defines the domain for the mask. + +2. Since we're doing data masking and the data we want lives in + fcst.grb, we pass it in again as the mask_file. + +3. Lastly "-mask_field" specifies the data we want from the mask file + and "-thresh" specifies the event threshold. + + +The second call is a bit tricky. + +1. Do data masking (-type data) + +2. Read the NetCDF variable named "TMP_Z2" from the input file (tmp_mask.nc) + +3. Define the mask by reading 6-hour precip from the mask file + (fcst.grb) and looking for values > 0 (-mask_field) + +4. Apply intersection logic when combining the "input" value with + the "mask" value (-intersection). + +5. Name the output NetCDF variable as "FREEZING_PRECIP" (-name). + This is totally optional, but convenient. + +A user can write a script with multiple calls to Gen-Vx-Mask to +apply complex masking logic and then pass the output mask file +to Grid-Stat in its configuration file. + + +**Q. Grid-Stat - How do I use neighborhood methods to compute fraction +skill score?** + +A. +A common application of fraction skill score (FSS) is comparing forecast +and observed thunderstorms. When computing FSS, first threshold the fields +to define events and non-events. Then look at successively larger and +larger areas around each grid point to see how the forecast event frequency +compares to the observed event frequency. + +Applying this method to rainfall (and monsoons) is also reasonable. +Keep in mind that Grid-Stat is the tool that computes FSS. Grid-Stat will +need to be run once for each evaluation time. As an example, evaluating +once per day, run Grid-Stat 122 times for the 122 days of a monsoon season. +This will result in 122 FSS values. These can be viewed as a time series, +or the Stat-Analysis tool could be used to aggregate them together into +a single FSS value, like this: + +.. code-block:: none + + stat_analysis -job aggregate -line_type NBRCNT \ + -lookin out/grid_stat + +Be sure to pick thresholds (e.g. for the thunderstorms and monsoons) +that capture the "events" that are of interest in studying. + +Also be aware that MET uses the "vld_thresh" setting in the configuration +file to decide how to handle data along the edge of the domain. Let us say +it is computing a fractional coverage field using a 5x5 neighborhood +and it is at the edge of the domain. 15 points contain valid data and +10 points are outside the domain. Grid-Stat computes the valid data ratio +as 15/25 = 0.6. Then it applies the valid data threshold. Suppose +vld_thresh = 0.5. Since 0.6 > 0.5 MET will compute a fractional coverage +value for that point using the 15 valid data points. Next suppose +vld_thresh = 1.0. Since 0.6 is less than 1.0, MET will just skip that +point by setting it to bad data. + +Setting vld_thresh = 1.0 will ensure that FSS will only be computed at +points where all NxN values contain valid data. Setting it to 0.5 only +requires half of them. + +**Q. Grid-Stat - Is an example of verifying forecast probabilities?** + +A. +There is an example of verifying probabilities in the test scripts +included with the MET release. Take a look in: + +.. code-block:: none + + ${MET_BUILD_BASE}/scripts/config/GridStatConfig_POP_12 + +The config file should look something like this: + +.. code-block:: none + + fcst = { + wind_thresh = [ NA ]; + field = [ + { + name = "LCDC"; + level = [ "L0" ]; + prob = TRUE; + cat_thresh = [ >=0.0, >=0.1, >=0.2, >=0.3, >=0.4, >=0.5, >=0.6, >=0.7, >=0.8, >=0.9]; + } + ]; + }; + + obs = { + wind_thresh = [ NA ]; + field = [ + { + name = "WIND"; + level = [ "Z2" ]; + cat_thresh = [ >=34 ]; + } + ]; + }; + +The PROB flag is set to TRUE to tell grid_stat to process this as +probability data. The cat_thresh is set to partition the probability +values between 0 and 1. Note that if the probability data contains +values from 0 to 100, MET automatically divides by 100 to rescale to +the 0 to 1 range. + +**Q. What is an example of using Grid-Stat with regridding and masking +turned on?** + +A. +Run Grid-Stat using the following commands and the attached config file + +.. code-block:: none + + mkdir out + ${MET_BUILD_BASE}/bin/grid_stat \ + gfs_4_20160220_0000_012.grb2 \ + ST4.2016022012.06h \ + GridStatConfig \ + -outdir out + +Note the following two sections of the Grid-Stat config file: + +.. code-block:: none + + regrid = { + to_grid = OBS; + vld_thresh = 0.5; + method = BUDGET; + width = 2; + } + +This tells Grid-Stat to do verification on the "observation" grid. +Grid-Stat reads the GFS and Stage4 data and then automatically regrids +the GFS data to the Stage4 domain using budget interpolation. +Use "FCST" to verify the forecast domain. And use either a named +grid or a grid specification string to regrid both the forecast and +observation to a common grid. For example, to_grid = "G212"; will +regrid both to NCEP Grid 212 before comparing them. + +.. code-block:: none + + mask = { grid = [ "FULL" ]; + poly = [ "MET_BASE/poly/CONUS.poly" ]; } + +This will compute statistics over the FULL model domain as well +as the CONUS masking area. + +To demonstrate that Grid-Stat worked as expected, run the following +commands to plot its NetCDF matched pairs output file: + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/plot_data_plane \ + out/grid_stat_120000L_20160220_120000V_pairs.nc \ + out/DIFF_APCP_06_A06_APCP_06_A06_CONUS.ps \ + 'name="DIFF_APCP_06_A06_APCP_06_A06_CONUS"; level="(*,*)";' + +Examine the resulting plot of that difference field. + +Lastly, there is another option for defining that masking region. +Rather than passing the ascii CONUS.poly file to grid_stat, run the +gen_vx_mask tool and pass the NetCDF output of that tool to grid_stat. +The advantage to gen_vx_mask is that it will make grid_stat run a +bit faster. It can be used to construct much more complex masking areas. + +**Q. How do I use one mask for the forecast field and a different +mask for the observation field??** + +A. +You can't define different +masks for the forecast and observation fields in MET tools. MET only lets you +define a single mask (a masking grid or polyline) and then you choose +whether you want to apply it to the FCST, OBS, or BOTH of them. + +Nonetheless, there is a way you can accomplish this logic using the +gen_vx_mask tool. You run it once to pre-process the forecast field +and a second time to pre-process the observation field. And then pass +those output files to your desired MET tool. + +Below is an example using sample data that is included with the MET +release tarball. To illustrate, this command will read 3-hour +precip and 2-meter temperature, and resets the precip at any grid +point where the temperature is less than 290 K to a value of 0: + +.. code-block:: none + + {MET_BUILD_BASE}/bin/gen_vx_mask \ + data/sample_fcst/2005080700/wrfprs_ruc13_12.tm00_G212 \ + data/sample_fcst/2005080700/wrfprs_ruc13_12.tm00_G212 \ + APCP_03_where_2m_TMPge290.nc \ + -type data \ + -input_field 'name="APCP"; level="A3";' \ + -mask_field 'name="TMP"; level="Z2";' \ + -thresh 'lt290&&ne-9999' -v 4 -value 0 + +So this is a bit confusing. Here's what is happening: + +* The first argument is the input file which defines the grid. + +* The second argument is used to define the masking region and + since I'm reading data from the same input file, I've listed + that file twice. + +* The third argument is the output file name. + +* The type of masking is "data" masking where we read a 2D field of + data and apply a threshold. + +* By default, gen_vx_mask initializes each grid point to a value + of 0. Specifying "-input_field" tells it to initialize each grid + point to the value of that field (in my example 3-hour precip). + +* The "-mask_field" option defines the data field that should be + thresholded. + +* The "-thresh" option defines the threshold to be applied. + +* The "-value" option tells it what "mask" value to write to the + output, and I've chosen 0. + +The example threshold is less than 290 and not -9999 (which is MET's +internal missing data value). So any grid point where the 2 meter +temperature is less than 290 K and is not bad data will be replaced +by a value of 0. + +To more easily demonstrate this, I changed to using "-value 10" and ran +the output through plot_data_plane: + +.. code-block:: none + + {MET_BUILD_BASE}/bin/plot_data_plane \ + + APCP_03_where_2m_TMPge290.nc APCP_03_where_2m_TMPge290.ps \ + + 'name="data_mask"; level="(*,*)";' + +In the resulting plot, anywhere you see the pink value of 10, that's +where gen_vx_mask has masked out the grid point. + +Pcp-Combine +~~~~~~~~~~~ + +**Q. Pcp-Combine - How do I add and subtract with Pcp-Combine?** + +A. +An example of running the MET pcp_combine tool to put NAM 3-hourly +precipitation accumulations data into user-desired 3 hour intervals is +provided below. + +If the user wanted a 0-3 hour accumulation, this is already available +in the 03 UTC file. Run this file +through pcp_combine as a pass-through to put it into NetCDF format: + +.. code-block:: none + + [MET_BUILD_BASE}/pcp_combine -add 03_file.grb 03 APCP_00_03.nc + +If the user wanted the 3-6 hour accumulation, they would subtract +0-6 and 0-3 accumulations: + +.. code-block:: none + + [MET_BUILD_BASE}/pcp_combine -subtract 06_file.grb 06 03_file.grb 03 APCP_03_06.nc + +Similarly, if they wanted the 6-9 hour accumulation, they would +subtract 0-9 and 0-6 accumulations: + +.. code-block:: none + + [MET_BUILD_BASE}/pcp_combine -subtract 09_file.grb 09 06_file.grb 06 APCP_06_09.nc + +And so on. + +Run the 0-3 and 12-15 through pcp_combine even though they already have +the 3-hour accumulation. That way, all of the NAM files will be in the +same file format, and can use the same configuration file settings for +the other MET tools (grid_stat, mode, etc.). If the NAM files are a mix +of GRIB and NetCDF, the logic would need to be a bit more complicated. + +**Q. Pcp-Combine - How do I combine 12-hour accumulated precipitation +from two different initialization times?** + +A. +The "-sum" command assumes the same initialization time. Use the "-add" +option instead. + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/pcp_combine -add \ + WRFPRS_1997-06-03_APCP_A12.nc 'name="APCP_12"; level="(*,*)";' \ + WRFPRS_d01_1997-06-04_00_APCP_A12.grb 12 \ + Sum.nc + +For the first file, list the file name followed by a config string +describing the field to use from the NetCDF file. For the second file, +list the file name followed by the accumulation interval to use +(12 for 12 hours). The output file, Sum.nc, will contain the +combine 12-hour accumulated precipitation. + +Here is a small excerpt from the pcp_combine usage statement: + +Note: For “-add” and "-subtract”, the accumulation intervals may be +substituted with config file strings. For that first file, we replaced +the accumulation interval with a config file string. + +Here are 3 commands you could use to plot these data files: + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/plot_data_plane WRFPRS_1997-06-03_APCP_A12.nc \ + WRFPRS_1997-06-03_APCP_A12.ps 'name="APCP_12"; level="(*,*)";' + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/plot_data_plane WRFPRS_d01_1997-06-04_00_APCP_A12.grb \ + WRFPRS_d01_1997-06-04_00_APCP_A12.ps 'name="APCP" level="A12";' + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/plot_data_plane sum.nc sum.ps 'name="APCP_24"; level="(*,*)";' + +**Q. Pcp-Combine - How do I correct a precipitation time range?** + +A. +Typically, accumulated precipitation is stored in GRIB files using an +accumulation interval with a "time range" indicator value of 4. Here is +a description of the different time range indicator values and +meanings: http://www.nco.ncep.noaa.gov/pmb/docs/on388/table5.html + +For example, take a look at the APCP in the GRIB files included in the +MET tar ball: + +.. code-block:: none + + wgrib ${MET_BUILD_BASE}/data/sample_fcst/2005080700/wrfprs_ruc13_12.tm00_G212 | grep APCP + 1:0:d=05080700:APCP:kpds5=61:kpds6=1:kpds7=0:TR=4:P1=0: \ + P2=12:TimeU=1:sfc:0- 12hr acc:NAve=0 + 2:31408:d=05080700:APCP:kpds5=61:kpds6=1:kpds7=0:TR=4: \ + P1=9:P2=12:TimeU=1:sfc:9- 12hr acc:NAve=0 + +The "TR=4" indicates that these records contain an accumulation +between times P1 and P2. In the first record, the precip is accumulated +between 0 and 12 hours. In the second record, the precip is accumulated +between 9 and 12 hours. + +However, the GRIB data uses a time range indicator of 5, not 4. + +.. code-block:: none + + wgrib rmf_gra_2016040600.24 | grep APCP + 291:28360360:d=16040600:APCP:kpds5=61:kpds6=1:kpds7=0: \ + TR=5:P1=0:P2=24:TimeU=1:sfc:0-24hr diff:NAve=0 + +pcp_combine is looking in "rmf_gra_2016040600.24" for a 24 hour +*accumulation*, but since the time range indicator is no 4, it doesn't +find a match. + +If possible switch the time range indicator to 4 on the GRIB files. If +this is not possible, there is another workaround. Instead of telling +pcp_combine to look for a particular accumulation interval, give it a +more complete description of the chosen field to use from each file. +Here is an example: + +.. code-block:: none + + pcp_combine -add rmf_gra_2016040600.24 'name="APCP"; level="L0-24";' \ + rmf_gra_2016040600_APCP_00_24.nc + +The resulting file should have the accumulation listed at 24h rather than 0-24. + +**Pcp-Combine - How do I use Pcp-Combine as a pass-through to simply reformat +from GRIB to NetCDF or to change output variable name?** + +A. +The pcp_combine tool is typically used to modify the accumulation interval +of precipitation amounts in model and/or analysis datasets. For example, +when verifying model output in GRIB format containing runtime accumulations +of precipitation, run the pcp_combine -subtract option every 6 hours to +create 6-hourly precipitation amounts. In this example, it is not really +necessary to run pcp_combine on the 6-hour GRIB forecast file since the +model output already contains the 0 to 6 hour accumulation. However, the +output of pcp_combine is typically passed to point_stat, grid_stat, or mode +for verification. Having the 6-hour forecast in GRIB format and all other +forecast hours in NetCDF format (output of pcp_combine) makes the logic +for configuring the other MET tools messy. To make the configuration +consistent for all forecast hours, one option is to choose to run +pcp_combine as a pass-through to simply reformat from GRIB to NetCDF. +Listed below is an example of passing a single record to the +pcp_combine -add option to do the reformatting: + +.. code-block:: none + + $MET_BUILD/bin/pcp_combine -add forecast_F06.grb \ + 'name="APCP"; level="A6";' \ + forecast_APCP_06_F06.nc -name APCP_06 + +Reformatting from GRIB to NetCDF may be done for any other reason the +user may have. For example, the -name option can be used to define the +NetCDF output variable name. Presuming this file is then passed to +another MET tool, the new variable name (CompositeReflectivity) will +appear in the output of downstream tools: + +.. code-block:: none + + $MET_BUILD/bin/pcp_combine -add forecast.grb \ + 'name="REFC"; level="L0"; GRIB1_ptv=129; lead_time="120000";' \ + forecast.nc -name CompositeReflectivity + +**Q. Pcp-Combine - How do I use “-pcprx" to run a project faster?** + +A. +To run a project faster, the “-pcprx” option may be used to narrow the +search down to whatever regular expression you provide. Here are a two +examples: + +.. code-block:: none + + # Only using Stage IV data (ST4) + ${MET_BUILD_BASE}/bin/pcp_combine -sum 00000000_000000 06 \ + 20161015_18 12 ST4.2016101518.APCP_12_SUM.nc -pcprx "ST4.*.06h" + + # Specify that files starting with pgbq[number][number]be used: + [MET_BUILD_BASE]/bin/pcp_combine \ + -sum 20160221_18 06 20160222_18 24 \ + gfs_APCP_24_20160221_18_F00_F24.nc \ + -pcpdir /scratch4/BMC/shout/ptmp/Andrew.Kren/pre2016c3_corr/temp \ + -pcprx 'pgbq[0-9][0-9].gfs.2016022118' -v 3 + +**Q. Pcp-Combine - How do I enter the time format correctly?** + +A. +Here is an **incorrect example** of running pcp_combine with sub-hourly +accumulation intervals: + +.. code-block:: none + + # incorrect example: + pcp_combine -subtract forecast.grb 0055 \ + forecast2.grb 0005 forecast.nc -field APCP + +The time signature is entered incorrectly. Let’s assume that "0055" +meant 0 hours and 55 minutes and "0005" meant 0 hours and 5 minutes. + +Looking at the usage statement for pcp_combine (just type pcp_combine with +no arguments): "accum1" indicates the accumulation interval to be used +from in_file1 in HH[MMSS] format (required). + +The time format listed "HH[MMSS]" means specifying hours or +hours/minutes/seconds. The incorrect example is using hours/minutes. + +Below is the **correct example**. Add the seconds to the end of the +time strings, like this: + +.. code-block:: none + + # correct example: + pcp_combine -subtract forecast.grb 005500 \ + forecast2.grb 000500 forecast.nc -field APCP + +**Q. Pcp-Combine - How do I use Pcp-Combine when my GRIB data doesn't have the +appropriate accumulation interval time range indicator?** + +A. +Run wgrib on the data files and the output is listed below: + +.. code-block:: none + + 279:503477484:d=15062313:APCP:kpds5=61:kpds6=1:kpds7=0:TR= 10:P1=3:P2=247:TimeU=0:sfc:1015min \ + fcst:NAve=0 \ + 279:507900854:d=15062313:APCP:kpds5=61:kpds6=1:kpds7=0:TR= 10:P1=3:P2=197:TimeU=0:sfc:965min \ + fcst:NAve=0 + +Notice the output which says "TR=10". TR means time range indicator and +a value of 10 means that the level information contains an instantaneous +forecast time, not an accumulation interval. + +Here's a table describing the TR values: +http://www.nco.ncep.noaa.gov/pmb/docs/on388/table5.html + +The default logic for pcp_combine is to look for GRIB code 61 (i.e. APCP) +defined with an accumulation interval (TR = 4). Since the data doesn't +meet that criteria, the default logic of pcp_combine won't work. The +arguments need to be more specific to tell pcp_combine exactly what to do. + +Try the command: + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/pcp_combine -subtract \ + forecast.grb 'name="APCP"; level="L0"; lead_time="165500";' \ + forecast2.grb 'name="APCP"; level="L0"; lead_time="160500";' \ + forecast.nc -name APCP_A005000 + +Some things to point out here: + +1. Notice in the wgrib output that the forecast times are 1015 min and + 965 min. In HHMMSS format, that's "165500" and "160500". + +2. An accumulation interval can’t be specified since the data isn't stored + that way. Instead, use a config file string to describe the data to use. + +3. The config file string specifies a "name" (APCP) and "level" string. APCP + is defined at the surface, so a level value of 0 (L0) was specified. + +4. Technically, the "lead_time" doesn’t need to be specified at all, + pcp_combine + would find the single APCP record in each input GRIB file and use them. + But just in case, the lead_time option was included to be extra certain to + get exactly the data that is needed. + +5. The default output variable name pcp_combine would write would be + "APCP_L0". However, to indicate that its a 50-minute + "accumulation interval" use a + different output variable name (APCP_A005000). Any string name is + possible. Maybe "Precip50Minutes" or "RAIN50". But whatever string is + chosen will be used in the Grid-Stat, Point-Stat, or MODE config file to + tell that tool what variable to process. + +**Q. Pcp_Combine - How do I use “-sum”, “-add”, and “-subtract“ to achieve +the same accumulation interval?** + +A. +Here is an example of using pcp_combine to put GFS into 24- hour intervals +for comparison against 24-hourly StageIV precipitation with GFS data +through the pcp_combine tool. Be aware that the 24-hour StageIV data is +defined as an accumulation from 12Z on one day to 12Z on the next day: +http://www.emc.ncep.noaa.gov/mmb/ylin/pcpanl/stage4/ + +Therefore, only the 24-hour StageIV data can be used to evaluate 12Z to +12Z accumulations from the model. Alternatively, the 6- hour StageIV +accumulations could be used to evaluate any 24 hour accumulation from +the model. For the latter, run the 6-hour StageIV files through pcp_combine +to generate the desired 24-hour accumulation. + +Here is an example. Run pcp_combine to compute 24-hour accumulations for +GFS. In this example, process the 20150220 00Z initialization of GFS. + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/pcp_combine \ + -sum 20150220_00 06 20150221_00 24 \ + gfs_APCP_24_20150220_00_F00_F24.nc \ + -pcprx "gfs_4_20150220_00.*grb2" \ + -pcpdir /d1/model_data/20150220 + +pcp_combine is looking in the */d1/SBU/GFS/model_data/20150220* directory +at files which match this regular expression "gfs_4_20150220_00.*grb2". +That directory contains data for 00, 06, 12, and 18 hour initializations, +but the "-pcprx" option narrows the search down to the 00 hour +initialization which makes it run faster. It inspects all the matching +files, looking for 6-hour APCP data to sum up to a 24-hour accumulation +valid at 20150221_00. This results in a 24-hour accumulation between +forecast hours 0 and 24. -A. MET relies upon the object-oriented aspects of C++, particularly in using the MODE tool. Due to time and budget constraints, it also makes use of a pre-existing forecast verification library that was developed at NCAR. +The following command will compute the 24-hour accumulation between forecast +hours 12 and 36: -**Q. Why is PrepBUFR used?** +.. code-block:: none -A. The first goal of MET was to replicate the capabilities of existing verification packages and make these capabilities available to both the DTC and the public. + ${MET_BUILD_BASE}/bin/pcp_combine \ + -sum 20150220_00 06 20150221_12 24 \ + gfs_APCP_24_20150220_00_F12_F36.nc \ + -pcprx "gfs_4_20150220_00.*grb2" \ + -pcpdir /d1/model_data/20150220 -**Q. Why is GRIB used?** +The "-sum" command is meant to make things easier by searching the +directory. But instead of using "-sum", another option would be the +"- add" command. Explicitly list the 4 files that need to be extracted +from the 6-hour APCP and add them up to 24. In the directory structure, +the previous "-sum" job could be rewritten with "-add" like this: -A. Forecast data from both WRF cores can be processed into GRIB format, and it is a commonly accepted output format for many NWP models. +.. code-block:: none -**Q. Is GRIB2 supported?** + ${MET_BUILD_BASE}/bin/pcp_combine -add \ + /d1/model_data/20150220/gfs_4_20150220_0000_018.grb2 06 \ + /d1/model_data/20150220/gfs_4_20150220_0000_024.grb2 06 \ + /d1/model_data/20150220/gfs_4_20150220_0000_030.grb2 06 \ + /d1/model_data/20150220/gfs_4_20150220_0000_036.grb2 06 \ + gfs_APCP_24_20150220_00_F12_F36_add_option.nc -A. Yes, forecast output in GRIB2 format can be read by MET. Be sure to compile the GRIB2 code by setting the appropriate configuration file options (see Chapter 2). +This example explicitly tells pcp_combine which files to read and +what accumulation interval (6 hours) to extract from them. The resulting +output should be identical to the output of the "-sum" command. -**Q. How does MET differ from the previously mentioned existing verification packages?** +**Q. Pcp-Combine - What is the difference between “-sum” vs. “-add”?** -A. MET is an actively maintained, evolving software package that is being made freely available to the public through controlled version releases. +A. +The -sum and -add options both do the same thing. It's just that +'-sum' could find files more quickly with the use of the -pcprx flag. +This could also be accomplished by using a calling script. -**Q. How does the MODE tool differ from the Grid-Stat tool?** +**Q. Pcp-Combine - How do I select a specific GRIB record?** -A. They offer different ways of viewing verification. The Grid-Stat tool provides traditional verification statistics, while MODE provides specialized spatial statistics. +A. +In this example, record 735 needs to be selected. + +.. code-block:: none + + pcp_combine -add 20160101_i12_f015_HRRR_wrfnat.grb2 \ + 'name="APCP"; level="R735";' \ + -name "APCP_01" HRRR_wrfnat.20160101_i12_f015.nc + +Instead of having the level as "L0", tell it to use "R735" to select +grib record 735. + +Plot-Data-Plane +~~~~~~~~~~~~~~~ + +**Q. Plot-Data-Plane - How do I inspect Gen-Vx-Mask output?** + +A. +Check to see if the call to Gen-Vx-Mask actually did create good output +with Plot-Data-Plane. +Try running the following command from the top-level ${MET_BUILD_BASE} +directory. + +.. code-block:: none + + bin/plot_data_plane \ + out/gen_vx_mask/CONUS_poly.nc \ + out/gen_vx_mask/CONUS_poly.ps \ + 'name="CONUS"; level="(*,*)";' + +View that postscript output file, using something like "gv" +for ghostview: + +.. code-block:: none + + gv out/gen_vx_mask/CONUS_poly.ps + +Please review a map of 0's and 1's over the USA to determine if the output +file is what the user expects. It always a good idea to start with +plot_data_plane when working with data to make sure MET +is plotting the data correctly and in the expected location. + +**Q. Plot-Data-Plane - How do I specify the GRIB version?** + +A. +When MET reads Gridded data files, it must determine the type of +file it's reading. The first thing it checks is the suffix of the file. +The following are all interpreted as GRIB1: .grib, .grb, and .gb. +While these mean GRIB2: .grib2, .grb2, and .gb2. + +There are 2 choices to control how MET interprets a grib file. Renaming +the files to use a particular suffix, or keep them +named and explicitly tell MET to interpret them as GRIB1 or GRIB2 using +the "file_type" configuration option. + +The examples below use the plot_data_plane tool to plot the data. Set + +.. code-block:: none + + "file_type = GRIB2;" + +To keep the files named this as they are, add "file_type = GRIB2;" to all the +MET configuration files (i.e. Grid-Stat, MODE, and so on) that you use: + +.. code-block:: none + + {MET_BASE}/bin/plot_data_plane \ + test_2.5_prog.grib \ + test_2.5_prog.ps \ + 'name="TSTM"; level="A0"; file_type=GRIB2;' \ + -plot_range 0 100 + + +**Q. Plot-Data-Plane - How do I test the variable naming convention? +(Record number example)** + +A. +Make sure MET can read GRIB2 data. Plot the data from that GRIB2 file +by running: + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/plot_data_plane LTIA98_KWBR_201305180600.grb2 tmp_z2.ps 'name="TMP"; level="R2"; + +"R2" tells MET to plot record number 2. Record numbers 1 and 2 both +contain temperature data and 2-meters. Here's some wgrib2 output: + +.. code-block:: none + + 1:0:d=2013051806:TMP:2 m above ground:anl:analysis/forecast error 2:3323062:d=2013051806:TMP:2 m above ground:anl: + +The GRIB id info has been the same between records 1 and 2. + +**Q. Plot-Data-Plane - How do I compute and verify wind speed?** + +A. +Here's how to compute and verify wind speed using MET. Good news, MET +already includes logic for deriving wind speed on the fly. The GRIB +abbreviation for wind speed is WIND. To request WIND from a GRIB1 or +GRIB2 file, MET first checks to see if it already exists in the current +file. If so, it'll use it as is. If not, it'll search for the corresponding +U and V records and derive wind speed to use on the fly. + +In this example the RTMA file is named rtma.grb2 and the UPP file is +named wrf.grb, please try running the following commands to plot wind speed: + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/plot_data_plane wrf.grb wrf_wind.ps \ + 'name"WIND"; level="Z10";' -v 3 + ${MET_BUILD_BASE}/bin/plot_data_plane rtma.grb2 rtma_wind.ps \ + 'name"WIND"; level="Z10";' -v 3 + +In the first call, the log message should be similar to this: + +.. code-block:: none + + DEBUG 3: MetGrib1DataFile::data_plane_array() -> + Attempt to derive winds from U and V components. + +In the second one, this won't appear since wind speed already exists +in the RTMA file. + +Stat-Analysis +~~~~~~~~~~~~~ + +**Q. Stat-Analysis - How does '-aggregate_stat' work?** + +A. +In Stat-Analysis, there is a "-vx_mask" job filtering option. That option +reads the VX_MASK column from the input STAT lines and applies string +matching with the values in that column. Presumably, all of the MPR lines +will have the value of "FULL" in the VX_MASK column. + +Stat-Analysis has the ability to read MPR lines and recompute statistics +from them using the same library code that the other MET tools use. The +job command options which begin with "-out" are used to specify settings +to be applied to the output of that process. For example, the "-fcst_thresh" +option filters strings from the input "FCST_THRESH" header column. The +"-out_fcst_thresh" option defines the threshold to be applied to the output +of Stat-Analysis. So reading MPR lines and applying a threshold to define +contingency table statistics (CTS) would be done using the +"-out_fcst_thresh" option. + +Stat-Analysis does have the ability to filter MPR lat/lon locations +using the "-mask_poly" option for a lat/lon polyline and the "-mask_grid" +option to define a retention grid. + +However, there is currently no "-mask_sid" option. + +With met-5.2 and later versions, one option is to apply column string +matching using the "-column_str" option to define the list of station +ID's you would like to aggregate. That job would look something like this: + +.. code-block:: none + + stat_analysis -lookin path/to/mpr/directory \ + -job aggregate_stat -line_type MPR -out_line_type CNT \ + -column_str OBS_SID SID1,SID2,SID3,...,SIDN \ + -set_hdr VX_MASK SID_GROUP_NAME \ + -out_stat mpr_to_cnt.stat + +Where SID1...SIDN is a comma-separated list of the station id's in the +group. Notice that a value for the output VX_MASK column using the +"-set_hdr" option has been specified. Otherwise, this would show a list +of the unique values found in that column. Presumably, all the input +VX_MASK columns say "FULL" so that's what the output would say. Use +"-set_hdr" to explicitly set the output value. + +**Q. Stat-Analysis - What is the best way to average the FSS scores +within several days or even several months using +'Aggregate to Average Scores'?** + +A. +Below is the best way to aggregate together the Neighborhood Continuous +(NBRCNT) lines across multiple days, specifically the fractions skill +score (FSS). The Stat-Analysis tool is designed to do this. This example +is for aggregating scores for the accumulated precipitation (APCP) field. + +Run the "aggregate" job type in stat_analysis to do this: + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/stat_analysis -lookin directory/file*_nbrcnt.txt \ + -job aggregate -line_type NBRCNT -by FCST_VAR,FCST_LEAD,FCST_THRESH,INTERP_MTHD,INTERP_PNTS -out_stat agg_nbrcnt.txt + +This job reads all the files that are passed to it on the command line with +the "-lookin" option. List explicit filenames to read them directly. +Listing a top-level directory name will search that directory for files +ending in ".stat". + +In this case, the job running is to "aggregate" the "NBRCNT" line type. + +In this case, the "-by" option is being used and lists several header +columns. Stat-Analysis will run this job separately for each unique +combination of those header column entries. + +The output is printed to the screen, or use the "-out_stat" option to +also write the aggregated output to a file named "agg_nbrcnt.txt". + +**Q. Stat-Analysis - How do I use '-by' to capture unique entries?** + +A. +Here is a stat-analysis job that could be used to run, read the MPR lines, +define the probabilistic forecast thresholds, define the single observation +threshold, and compute a PSTD output line. Using "-by FCST_VAR" tells it +to run the job separately for each unique entry found in the FCST_VAR column. + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/stat_analysis \ + -lookin point_stat_model2_120000L_20160501_120000V.stat \ + -job aggregate_stat -line_type MPR -out_line_type PSTD \ + -out_fcst_thresh ge0,ge0.1,ge0.2,ge0.3,ge0.4,ge0.5,ge0.6,ge0.7,ge0.8,ge0.9,ge1.0 \ + -out_obs_thresh eq1.0 \ + -by FCST_VAR \ + -out_stat out_pstd.txt + +The output statistics are written to "out_pstd.txt". + +**Q. Stat-Analysis - How do I use '-filter' to refine my output?** + +A. +Here is an example of running a Stat-Analysis filter job to discard any +CNT lines (continuous statistics) where the forecast rate and observation +rate are less than 0.05. This is an alternative way of tossing out those +cases without having to modify the source code. + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/stat_analysis \ + -lookin out/grid_stat/grid_stat_120000L_20050807_120000V.stat \ + -job filter -dump_row filter_cts.txt -line_type CTS \ + -column_min BASER 0.05 -column_min FMEAN 0.05 + DEBUG 2: STAT Lines read = 436 + DEBUG 2: STAT Lines retained = 36 + DEBUG 2: + DEBUG 2: Processing Job 1: -job filter -line_type CTS -column_min BASER + 0.05 -column_min + FMEAN 0.05 -dump_row filter_cts.txt + DEBUG 1: Creating + STAT output file "filter_cts.txt" + FILTER: -job filter -line_type + CTS -column_min + BASER 0.05 -column_min + FMEAN 0.05 -dump_row filter_cts.txt + DEBUG 2: Job 1 used 36 out of 36 STAT lines. + +This job reads find 56 CTS lines, but only keeps 36 of them where both +the BASER and FMEAN columns are at least 0.05. + +**Q. Stat-Analysis - How do I use the “-by” flag to stratify results?** + +A. +Adding "-by FCST_VAR" is a great way to associate a single value, +of say RMSE, with each of the forecast variables (UGRD,VGRD and WIND). + +Run the following job on the output from Grid-Stat generated when the +"make test" command is run: + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/stat_analysis -lookin out/grid_stat \ + -job aggregate_stat -line_type SL1L2 -out_line_type CNT \ + -by FCST_VAR,FCST_LEV \ + -out_stat cnt.txt + +The resulting cnt.txt file includes separate output for 6 different +FCST_VAR values at different levels. + +**Q. Stat-Analysis - How do I speed up run times?** + +A. +By default, Stat-Analysis has two options enabled which slow it down. +Disabling these two options will create quicker run times: + +1. The computation of rank correlation statistics, Spearman's Rank + Correlation and Kendall's Tau. Disable them using "-rank_corr_flag FALSE". + +2. The computation of bootstrap confidence intervals. Disable them using + "-n_boot_rep 0". + +Two more suggestions for faster run times. + +1. Instead of using "-fcst_var u", use "-by fcst_var". This will compute + statistics separately for each unique entry found in the FCST_VAR column. + +2. Instead of using "-out" to write the output to a text file, use "-out_stat" + which will write a full STAT output file, including all the header columns. + This will create a long list of values in the OBTYPE column. To avoid the + long, OBTYPE column value, manually set the output using + "-set_hdr OBTYPE ALL_TYPES". Or set its value to whatever is needed. + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/stat_analysis \ + -lookin diag_conv_anl.2015060100.stat \ + -job aggregate_stat -line_type MPR -out_line_type CNT -by FCST_VAR \ + -out_stat diag_conv_anl.2015060100_cnt.txt -set_hdr OBTYPE ALL_TYPES \ + -n_boot_rep 0 -rank_corr_flag FALSE -v 4 + +Adding the "-by FCST_VAR" option to compute stats for all variables and +runs quickly. + +TC-Stat +~~~~~~~ + +**Q. TC-Stat - How do I use the “-by” flag to stratify results?** + +A. +To perform tropical cyclone evaluations for multiple models use the +"-by AMODEL" option with the tc_stat tool. Here is an example. + +In this case the tc_stat job looked at the 48 hour lead time for the HWRF +and H3HW models. Without the “-by AMODEL” option, the output would be +all grouped together. + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/tc_stat \ + -lookin d2014_vx_20141117_reset/al/tc_pairs/tc_pairs_H3WI_* \ + -lookin d2014_vx_20141117_reset/al/tc_pairs/tc_pairs_HWFI_* \ + -job summary -lead 480000 -column TRACK -amodel HWFI,H3WI \ + -by AMODEL -out sample.out + +This will result in all 48 hour HWFI and H3WI track forecasts to be +aggregated (statistics and scores computed) for each model separately. + +**Q. TC-Stat - How do I use rapid intensification verification?** + +A. +To get the most output, run something like this: + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/tc_stat \ + -lookin path/to/tc_pairs/output \ + -job rirw -dump_row test \ + -out_line_type CTC,CTS,MPR + +By default, rapid intensification (RI) is defined as a 24-hour exact +change exceeding 30kts. To define RI differently, modify that definition +using the ADECK, BDECK, or both using -rirw_time, -rirw_exact, +and -rirw_thresh options. Set -rirw_window to something larger than 0 +to enable false alarms to be considered hits when they were "close enough" +in time. + +.. code-block:: none + + {MET_BASE}/bin/tc_stat \ + -lookin path/to/tc_pairs/output \ + -job rirw -dump_row test \ + -rirw_time 36 -rirw_window 12 \ + -out_line_type CTC,CTS,MPR + +To evaluate Rapid Weakening (RW) by setting "-rirw_thresh <=-30". +To stratify your results by lead time, you could add the "-by LEAD" option. + +.. code-block:: none + + {MET_BASE}/bin/tc_stat \ + -lookin path/to/tc_pairs/output \ + -job rirw -dump_row test \ + -rirw_time 36 -rirw_window 12 \ + -rirw_thresh <=-30 -by LEAD \ + -out_line_type CTC,CTS,MPR + +Utilities +~~~~~~~~~ + +**Q. Utilities - What would be an example of scripting to call MET?** + +A. +The following is an example of how to call MET from a bash script +including passing in variables. This shell script is listed below to run +Grid-Stat, call Plot-Data-Plane to plot the resulting difference field, +and call convert to reformat from PostScript to PNG. + +.. code-block:: none + + #!/bin/sh + for case in `echo "FCST OBS"`; do + export TO_GRID=${case} + /usr/local/${MET_BUILD_BASE}/bin/grid_stat gfs.t00z.pgrb2.0p25.f000 \ + nam.t00z.conusnest.hiresf00.tm00.grib2 GridStatConfig \ + /usr/local/${MET_BUILD_BASE}/bin/plot_data_plane \ + *TO_GRID_${case}*_pairs.nc TO_GRID_${case}.ps 'name="DIFF_TMP_P500_TMP_P500_FULL"; \ + level="(*,*)";' + convert -rotate 90 -background white -flatten TO_GRID_${case}.ps + TO_GRID_${case}.png + done + + +**Q. Utility - How do I convert TRMM data files?** + +A. +Here is an example of NetCDF that the MET software is not expecting. Here +is an option for accessing that same TRMM data, following links from the +MET website: +http://dtcenter.org/community-code/model-evaluation-tools-met/input-data + +.. code-block:: none + + # Pull binary 3-hourly TRMM data file + wget + ftp://disc2.nascom.nasa.gov/data/TRMM/Gridded/3B42_V7/201009/3B42.100921.00z.7. + precipitation.bin + # Pull Rscript from MET website + wget http://dtcenter.org/sites/default/files/community-code/met/r-scripts/trmmbin2nc.R + # Edit that Rscript by setting + out_lat_ll = -50 + out_lon_ll = 0 + out_lat_ur = 50 + out_lon_ur = 359.75 + # Run the Rscript + Rscript trmmbin2nc.R 3B42.100921.00z.7.precipitation.bin \ + 3B42.100921.00z.7.precipitation.nc + # Plot the result + ${MET_BUILD_BASE}/bin/plot_data_plane 3B42.100921.00z.7.precipitation.nc \ + 3B42.100921.00z.7.precipitation.ps 'name="APCP_03"; level="(*,*)";' + +It may be possible that the domain of the data is smaller. Here are some options: + +1. In that Rscript, choose different boundaries (i.e. out_lat/lon_ll/ur) + to specify the tile of data to be selected. + +2. As of version 5.1, MET includes support for regridding the data it reads. + Keep TRMM on it's native domain and use the MET tools to do the regridding. + For example, the Regrid-Data-Plane" tool reads a NetCDF file, regrids + the data, and writes a NetCDF file. Alternatively, the "regrid" section + of the configuration files for the MET tools may be used to do the + regridding on the fly. For example, run Grid-Stat to compare to the model + output to TRMM and say + +.. code-block:: none + + "regrid = { field = FCST; + ...}" + +That tells Grid-Stat to automatically regrid the TRMM observations to +the model domain. + +**Q. Other Utilities - How do I convert a PostScript to png?** + +A. +Use the linux “convert” tool to convert a Plot-Data-Plane PostScript +file to a png: + +.. code-block:: none + + convert -rotate 90 -background white plot_dbz.ps plot_dbz.png + +To convert a MODE PostScript to png + +.. code-block:: none + + convert mode_out.ps mode_out.png + +Will result in all 6-7 pages in the PostScript file be written out to a +seperate .png with the following naming convention: + +mode_out-0.png, mode_out-1.png, mode_out-2.png, etc. + +**Q. Utility - How does pairwise differences using plot_tcmpr.R work?** + +A. +One necessary step in computing pairwise differences is "event equalizing" +the data. This means extracting a subset of cases that are common to +both models. + +While the tc_stat tool does not compute pairwise differences, it can apply +the "event_equalization" logic to extract the cases common to two models. +This is done using the config file "event_equal = TRUE;" option or +setting "-event_equal true" on the command line. + +Most of the hurricane track analysis and plotting is done using the +plot_tcmpr.R Rscript. It makes a call to the tc_stat tool to track +data down to the desired subset, compute pairwise differences if needed, +and then plot the result. + +.. code-block:: none + + setenv MET_BUILD_BASE `pwd` + Rscript scripts/Rscripts/plot_tcmpr.R \ + -lookin tc_pairs_output.tcst \ + -filter '-amodel AHWI,GFSI' \ + -series AMODEL AHWI,GFSI,AHWI-GFSI \ + -plot MEAN,BOXPLOT + +The resulting plots include three series - one for AHWI, one for GFSI, +and one for their pairwise difference. + +It's a bit cumbersome to understand all the options available, but this may +be really useful. If nothing else, it could be adapted to dump out the +pairwise differences that are needed. + + +Miscellaneous +~~~~~~~~~~~~~ + +**Q. Regrid-Data-Plane - How do I define a LatLon grid?** + +A. +Here is an example of the NetCDF variable attributes that MET uses to +define a LatLon grid: + +.. code-block:: none + + :Projection = "LatLon" ; + :lat_ll = "25.063000 degrees_north" ; + :lon_ll = "-124.938000 degrees_east" ; + :delta_lat = "0.125000 degrees" ; + :delta_lon = "0.125000 degrees" ; + :Nlat = "224 grid_points" ; + :Nlon = "464 grid_points" ; + +This can be created by running the Regrid-Data-Plane" tool to regrid +some GFS data to a LatLon grid: + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/regrid_data_plane \ + gfs_2012040900_F012.grib G110 \ + gfs_g110.nc -field 'name="TMP"; level="Z2";' + +Use ncdump to look at the attributes. As an exercise, try defining +these global attributes (and removing the other projection-related ones) +and then try again. + +**Q. Pre-processing - How do I use wgrib2, pcp_combine regrid and +reformat to format NetCDF files?** + +A. +If you are extracting only one or two fields from a file, using MET's +Regrid-Data-Plane can be used to generate a Lat-Lon projection. If +regridding all fields, the wgrib2 utility may be more useful. Here's an +example of using wgrib2 and pcp_combine to generate NetCDF files +MET can read: + +.. code-block:: none + + wgrib2 gfsrain06.grb -new_grid latlon 112:131:0.1 \ + 25:121:0.1 gfsrain06_regrid.grb2 + +And then run that GRIB2 file through pcp_combine using the "-add" option +with only one file provided: + +.. code-block:: none + + pcp_combine -add gfsrain06_regrid.grb2 'name="APCP"; \ + level="A6";' gfsrain06_regrid.nc + +Then the output NetCDF file does not have this problem: + +.. code-block:: none + + ncdump -h 2a_wgrib2_regrid.nc | grep "_ll" + :lat_ll = "25.000000 degrees_north" ; + :lon_ll = "112.000000 degrees_east" ; + +**Q. TC-Pairs - How do I get rid of WARNING: TrackInfo Using Specify +Model Suffix?** + +A. +Below is a command example to run: + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/tc_pairs \ + -adeck aep142014.h4hw.dat \ + -bdeck bep142014.dat \ + -config TCPairsConfig_v5.0 \ + -out tc_pairs_v5.0_patch \ + -log tc_pairs_v5.0_patch.log \ + -v 3 + +Below is a warning message: + +.. code-block:: none + + WARNING: TrackInfo::add(const ATCFLine &) -> + skipping ATCFLine since the valid time is not + increasing (20140801_000000 < 20140806_060000): + WARNING: AL, 03, 2014080100, 03, H4HW, 000, + 120N, 547W, 38, 1009, XX, 34, NEQ, 0084, 0000, + 0000, 0083, -99, -99, 59, 0, 0, , 0, , 0, 0, + +As a sanity check, the MET-TC code makes sure that the valid time of +the track data doesn't go backwards in time. This warning states that +this is +occurring. The very likely reason for this is that the data being used +are probably passing tc_pairs duplicate track data. + +Using grep, notice that the same track data shows up in +"aal032014.h4hw.dat" and "aal032014_hfip_d2014_BERTHA.dat". Try this: + +.. code-block:: none + + grep H4HW aal*.dat | grep 2014080100 | grep ", 000," + aal032014.h4hw.dat:AL, 03, 2014080100, 03, H4HW, 000, + 120N, 547W, 38, 1009, XX, 34, NEQ, 0084, + 0000, 0000, 0083, -99, -99, 59, 0, 0, , + 0, , 0, 0, , , , , 0, 0, 0, 0, THERMO PARAMS, + -9999, -9999, -9999, Y, 10, DT, -999 + aal032014_hfip_d2014_BERTHA.dat:AL, 03, 2014080100, + 03, H4HW, 000, 120N, 547W, 38, 1009, XX, 34, NEQ, + 0084, 0000, 0000, 0083, -99, -99, 59, 0, 0, , 0, , 0, + 0, , , , , 0, 0, 0, 0, THERMOPARAMS, -9999 ,-9999 , + -9999 ,Y ,10 ,DT ,-999 + +Those 2 lines are nearly identical, except for the spelling of +"THERMO PARAMS" with a space vs "THERMOPARAMS" with no space. + +Passing tc_pairs duplicate track data results in this sort of warning. +The DTC had the same sort of problem when setting up a real-time +verification system. The same track data was making its way into +multiple ATCF files. + +If this really is duplicate track data, work on the logic for where/how +to store the track data. However, if the H4HW data in the first file +actually differs from that in the second file, there is another option. +You can specify a model suffix to be used for each ADECK source, as in +this example (suffix=_EXP): + +.. code-block:: none + + ${MET_BUILD_BASE}/bin/tc_pairs \ + -adeck aal032014.h4hw.dat suffix=_EXP \ + -adeck aal032014_hfip_d2014_BERTHA.dat \ + -bdeck bal032014.dat \ + -config TCPairsConfig_match \ + -out tc_pairs_v5.0_patch \ + -log tc_pairs_v5.0_patch.log -v 3 + +Any model names found in "aal032014.h4hw.dat" will now have _EXP tacked +onto the end. Note that if a list of model names in the TCPairsConfig file +needs specifying, include the _EXP variants to get them to show up in +the output or it won’t show up. + +That'll get rid of the warnings because they will be storing the track +data from the first source using a slightly different model name. This +feature was added for users who are testing multiple versions of a +model on the same set of storms. They might be using the same ATCF ID +in all their output. But this enables them to distinguish the output +in tc_pairs. + +**Q. Why is the grid upside down?** + +A. +The user provides a gridded data file to MET and it runs without error, +but the data is packed upside down. + +Try using the "file_type" entry. The "file_type" entry specifies the +input file type (e.g. GRIB1, GRIB2, NETCDF_MET, NETCDF_PINT, NETCDF_NCCF) +rather than letting the code determine it itself. For valid file_type +values, see "File types" in the *data/config/ConfigConstants* file. This +entry should be defined within the "fcst" or "obs" dictionaries. +Sometimes, directly specifying the type of file will help MET figure +out what to properly do with the data. + +Another option is to use the Regrid-Data-Plane tool. The Regrid-Data-Plane +tool may be run to read data from any gridded data file MET supports +(i.e. GRIB1, GRIB2, and a variety of NetCDF formats), interpolate to a +user-specified grid, and write the field(s) out in NetCDF format. See the +Regrid-Data-Plane tool :numref:`regrid-data-plane` in the MET +User's Guide for more +detailed information. While the Regrid-Data-Plane tool is useful as a +stand-alone tool, the capability is also included to automatically regrid +data in most of the MET tools that handle gridded data. This "regrid" +entry is a dictionary containing information about how to handle input +gridded data files. The "regird" entry specifies regridding logic and +has a "to_grid" entry that can be set to NONE, FCST, OBS, a named grid, +the path to a gridded data file defining the grid, or an explicit grid +specification string. See the :ref:`regrid` entry in +the Configuration File Overview in the MET User's Guide for a more detailed +description of the configuration file entries that control automated +regridding. + +A single model level can be plotted using the plot_data_plane utility. +This tool can assist the user by showing the data to be verified to +ensure that times and locations matchup as expected. + +**Q. Why was the MET written largely in C++ instead of FORTRAN?** + +A. +MET relies upon the object-oriented aspects of C++, particularly in +using the MODE tool. Due to time and budget constraints, it also makes +use of a pre-existing forecast verification library that was developed +at NCAR. + +**Q. How does MET differ from the previously mentioned existing +verification packages?** + +A. +MET is an actively maintained, evolving software package that is being +made freely available to the public through controlled version releases. **Q. Will the MET work on data in native model coordinates?** -A. No - it will not. In the future, we may add options to allow additional model grid coordinate systems. +A. +No - it will not. In the future, we may add options to allow additional +model grid coordinate systems. **Q. How do I get help if my questions are not answered in the User's Guide?** -A. First, look on our `MET User's Guide website `_. If that doesn't answer your question, create a post in the `METplus GitHub Discussions Forum `_. +A. +First, look on our +`MET User's Guide website `_. +If that doesn't answer your question, create a post in the +`METplus GitHub Discussions Forum `_. + -**Q. Where are the graphics?** +**Q. What graphical features does MET provide?** -A. Currently, very few graphics are included. The plotting tools (plot_point_obs, plot_data_plane, and plot_mode_field) can help you visualize your raw data. Also, ncview can be used with the NetCDF output from MET tools to visualize results. Further graphics support will be made available in the future on the MET website. +A. +MET provides some :ref:`plotting and graphics support`. The plotting +tools, including plot_point_obs, plot_data_plane, and plot_mode_field, can +help users visualize the data. + +MET is intended to be a set of command line tools for evaluating forecast +quality. So, the development effort is focused on providing the latest, +state of the art verification approaches, rather than on providing nice +plotting features. However, the ASCII output statistics of MET may be plotted +with a wide variety of plotting packages, including R, NCL, IDL, and GNUPlot. +METViewer is also currently being developed and used by the DTC and NOAA +It creates basic plots of MET output verification statistics. The types of +plots include series plots with confidence intervals, box plots, x-y scatter +plots and histograms. + +R is a language and environment for statistical computing and graphics. +It's a free package that runs on most operating systems and provides nice +plotting features and a wide array of powerful statistical analysis tools. +There are sample scripts on the +`MET website `_ +that you can use and modify to perform the type of analysis you need. If +you create your own scripts, we encourage you to submit them to us through the +`METplus GitHub Discussions Forum `_ +so that we can post them for other users. **Q. How do I find the version of the tool I am using?** -A. Type the name of the tool followed by **-version**. For example, type "pb2nc **-version**". +A. +Type the name of the tool followed by **-version**. For example, +type “pb2nc **-version**”. -**Q. What are MET's conventions for latitude, longitude, azimuth and bearing angles?** +**Q. What are MET's conventions for latitude, longitude, azimuth and +bearing angles?** -A. MET considers north latitude and east longitude positive. Latitudes have range from :math:`-90^\circ` to :math:`+90^\circ`. Longitudes have range from :math:`-180^\circ` to :math:`+180^\circ`. Plane angles such as azimuths and bearing (example: horizontal wind direction) have range :math:`0^\circ` to :math:`360^\circ` and are measured clockwise from the north. +A. +MET considers north latitude and east longitude positive. Latitudes +have range from :math:`-90^\circ` to :math:`+90^\circ`. Longitudes have +range from :math:`-180^\circ` to :math:`+180^\circ`. Plane angles such +as azimuths and bearing (example: horizontal wind direction) have +range :math:`0^\circ` to :math:`360^\circ` and are measured clockwise +from the north. .. _Troubleshooting: Troubleshooting _______________ -The first place to look for help with individual commands is this user's guide or the usage statements that are provided with the tools. Usage statements for the individual MET tools are available by simply typing the name of the executable in MET's *bin/* directory. Example scripts available in the MET's *scripts/* directory show examples of how one might use these commands on example datasets. Here are suggestions on other things to check if you are having problems installing or running MET. +The first place to look for help with individual commands is this +User's Guide or the usage statements that are provided with the tools. +Usage statements for the individual MET tools are available by simply +typing the name of the executable in MET's *bin/* directory. Example +scripts available in the MET's *scripts/* directory show examples of how +one might use these commands on example datasets. Here are suggestions +on other things to check if you are having problems installing or running MET. **MET won't compile** -* Have you specified the locations of NetCDF, GNU Scientific Library, and BUFRLIB, and optional additional libraries using corresponding MET\_ environment variables prior to running configure? +* Have you specified the locations of NetCDF, GNU Scientific Library, + and BUFRLIB, and optional additional libraries using corresponding + MET\_ environment variables prior to running configure? + +* Have these libraries been compiled and installed using the same set + of compilers used to build MET? + +* Are you using NetCDF version 3.4 or version 4? Currently, only NetCDF + version 3.6 can be used with MET. + +**BUFRLIB Errors during MET installation** + +.. code-block:: none + + error message: /usr/bin/ld: cannot find -lbufr + The linker can not find the BUFRLIB library archive file it needs. + + export MET_BUFRLIB=/home/username/BUFRLIB_v10.2.3:$MET_BUFRLIB + +It isn't making it's way into the configuration because BUFRLIB_v10.2.3 +isn't showing up in the output of make. This may indicate the wrong shell +type. The .bashrc file sets the environment for the Bourne shell, but +the above error could indicate that the c- shell is being used instead. -* Have these libraries been compiled and installed using the same set of compilers used to build MET? +Try the following 2 things: -* Are you using NetCDF version 3.4 or version 4? Currently, only NetCDF version 3.6 can be used with MET. +1. Check to make sure this file exists: -**Grid_stat won't run** + .. code-block:: none -* Are both the observational and forecast datasets on the same grid? + ls /home/username/BUFRLIB_v10.2.3/libbufr.a -**MODE won't run** +2. Rerun the MET configure command using the following option on the + command line: -* If using precipitation, do you have the same accumulation periods for both the forecast and observations? (If you aren't sure, run pcp_combine.) + .. code-block:: none + + MET_BUFRLIB=/home/username/BUFRLIB_v10.2.3 -* Are both the observation and forecast datasets on the same grid? +After doing that, please try recompiling MET. If it fails, +please send met_help@ucar.edu the following log files. +"make_install.log" as well as "config.log". -**Point-Stat won't run** +**Command line double quotes** -* Have you run pb2nc first on your PrepBUFR observation data? +Single quotes, double quotes, and escape characters can be difficult for +MET to parse. If there are problems, especially in Python code, try +breaking the command up like the below example. + +.. code-block:: none + + ['/h/WXQC/{MET_BUILD_BASE}/bin/regrid_data_plane', + '/h/data/global/WXQC/data/umm/1701150006', + 'G003', '/h/data/global/WXQC/data/met/nc_mdl/umm/1701150006', '- field', + '\'name="HGT"; level="P500";\'', '-v', '6'] + +**Environment variable settings** + +In the below incorrect example for many environment variables have both +the main variable set and the INC and LIB variables set: + +.. code-block:: none + + export MET_GSL=$MET_LIB_DIR/gsl + export MET_GSLINC=$MET_LIB_DIR/gsl/include/gsl + export MET_GSLLIB=$MET_LIB_DIR/gsl/lib + +**only MET_GSL *OR *MET_GSLINC *AND *MET_GSLLIB need to be set.** +So, for example, either set: + +.. code-block:: none + + export MET_GSL=$MET_LIB_DIR/gsl + +or set: + +.. code-block:: none + + export MET_GSLINC=$MET_LIB_DIR/gsl/include/gsl export MET_GSLLIB=$MET_LIB_DIR/gsl/lib + +Additionally, MET does not use MET_HDF5INC and MET_HDF5LIB. +It only uses MET_HDF5. + +Our online tutorial can help figure out what should be set and what the +value should be: +https://met.readthedocs.io/en/latest/Users_Guide/installation.html + +**NetCDF install issues** + +This example shows a problem with NetCDF in the make_install.log file: + +.. code-block:: none + + /usr/bin/ld: warning: libnetcdf.so.11, + needed by /home/zzheng25/metinstall/lib/libnetcdf_c++4.so, + may conflict with libnetcdf.so.7 + +Below are examples of too many MET_NETCDF options: + +.. code-block:: none + + MET_NETCDF='/home/username/metinstall/' + MET_NETCDFINC='/home/username/local/include' + MET_NETCDFLIB='/home/username/local/lib' + + +Either MET_NETCDF **OR** MET_NETCDFINC **AND** MET_NETCDFLIB need to be set. +If the NetCDF include files are in */home/username/local/include* and the +NetCDF library files are in */home/username/local/lib*, unset the +MET_NETCDF environment variable, then run "make clean", reconfigure, +and then run "make install" and "make test" again. **Error while loading shared libraries** -* Add the lib dir to your LD_LIBRARY_PATH. For example, if you receive the following error: "./mode_analysis: error while loading shared libraries: libgsl.so.19: cannot open shared object file: No such file or directory", you should add the path to the gsl lib (for example, */home/user/MET/gsl-2.1/lib*) to your LD_LIBRARY_PATH. + +* Add the lib dir to your LD_LIBRARY_PATH. For example, if you receive + the following error: "./mode_analysis: error while loading shared + libraries: libgsl.so.19: cannot open shared object file: + No such file or directory", you should add the path to the + gsl lib (for example, */home/user/MET/gsl-2.1/lib*) + to your LD_LIBRARY_PATH. **General troubleshooting** -* For configuration files used, make certain to use empty square brackets (e.g. [ ]) to indicate no stratification is desired. Do NOT use empty double quotation marks inside square brackets (e.g. [""]). +* For configuration files used, make certain to use empty square brackets + (e.g. [ ]) to indicate no stratification is desired. Do NOT use empty + double quotation marks inside square brackets (e.g. [""]). * Have you designated all the required command line arguments? -* Try rerunning with a higher verbosity level. Increasing the verbosity level to 4 or 5 prints much more diagnostic information to the screen. +* Try rerunning with a higher verbosity level. Increasing the verbosity + level to 4 or 5 prints much more diagnostic information to the screen. Where to get help _________________ -If none of the above suggestions have helped solve your problem, help is available through the `METplus GitHub Discussions Forum `_. +If none of the above suggestions have helped solve your problem, help +is available through the +`METplus GitHub Discussions Forum `_. + How to contribute code ______________________ -If you have code you would like to contribute, we will gladly consider your contribution. Please create a post in the `METplus GitHub Discussions Forum `_. +If you have code you would like to contribute, we will gladly consider +your contribution. Please create a post in the +`METplus GitHub Discussions Forum `_. + diff --git a/met/docs/Users_Guide/reformat_grid.rst b/met/docs/Users_Guide/reformat_grid.rst index 5975de88d1..191ef4e1a4 100644 --- a/met/docs/Users_Guide/reformat_grid.rst +++ b/met/docs/Users_Guide/reformat_grid.rst @@ -201,6 +201,7 @@ Each NetCDF file generated by the Pcp-Combine tool contains the dimensions and v - lat, lon - Data value (i.e. accumulated precipitation) for each point in the grid. The name of the variable describes the name and level and any derivation logic that was applied. +.. _regrid-data-plane: Regrid-Data-Plane tool ______________________ diff --git a/met/docs/conf.py b/met/docs/conf.py index def45c32d7..2b646244a6 100644 --- a/met/docs/conf.py +++ b/met/docs/conf.py @@ -32,7 +32,8 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx'] +# Adding 'sphinx_panels' to use drop-down menus in appendixA. +extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx','sphinx_panels',] # settings for ReadTheDocs PDF creation latex_engine = 'pdflatex' diff --git a/met/docs/requirements.txt b/met/docs/requirements.txt index f6b879164e..14529e46cf 100644 --- a/met/docs/requirements.txt +++ b/met/docs/requirements.txt @@ -7,4 +7,5 @@ sphinxcontrib-devhelp==1.0.2 sphinxcontrib-htmlhelp==1.0.3 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 -sphinxcontrib-serializinghtml==1.1.4 \ No newline at end of file +sphinxcontrib-serializinghtml==1.1.4 +sphinx-panels==0.6.0 From 09f3cf1306f062153146ff64179773177b4dba6d Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Mon, 16 Aug 2021 12:24:02 -0600 Subject: [PATCH 121/200] bugfix 1872 plot_tcmpr.R -lookin directory (develop) (#1874) --- met/scripts/Rscripts/plot_tcmpr.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/scripts/Rscripts/plot_tcmpr.R b/met/scripts/Rscripts/plot_tcmpr.R index f42ba17c94..cad729c484 100644 --- a/met/scripts/Rscripts/plot_tcmpr.R +++ b/met/scripts/Rscripts/plot_tcmpr.R @@ -377,7 +377,7 @@ if(length(file_list) == 0) { } # Expand any wildcards in the input file list -file_list = system(paste("ls -1", paste(file_list, collapse=" ")), +file_list = system(paste("ls -1d", paste(file_list, collapse=" ")), intern=TRUE); # Read the plotting configuration file, if specified From f903075eb4d0fb0ded5a0b48d221ef63a184d110 Mon Sep 17 00:00:00 2001 From: johnhg Date: Tue, 17 Aug 2021 08:46:30 -0600 Subject: [PATCH 122/200] Bugfix 1875 develop memory (#1877) * Per #1875, fix set_cdf_ta() to initialize cdf_ta prior to populating it. * Per #1875, add debug(4) log messages whenever defining a new aggregation case in stat-analysis. * Per #1875, switch log messages about new cases from Debug(4) to Debug(3). --- met/src/basic/vx_config/config_util.cc | 3 ++ .../core/stat_analysis/aggr_stat_line.cc | 52 +++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/met/src/basic/vx_config/config_util.cc b/met/src/basic/vx_config/config_util.cc index 64720d41de..5e8e8593b9 100644 --- a/met/src/basic/vx_config/config_util.cc +++ b/met/src/basic/vx_config/config_util.cc @@ -1493,6 +1493,9 @@ void ClimoCDFInfo::set_cdf_ta(int n_bin, bool ¢er) { exit(1); } + // Initialize + cdf_ta.clear(); + // Even number of bins cannot be centered if(n_bin%2 == 0 && center) { mlog << Warning << "\nClimoCDFInfo::set_cdf_ta() -> " diff --git a/met/src/tools/core/stat_analysis/aggr_stat_line.cc b/met/src/tools/core/stat_analysis/aggr_stat_line.cc index e6f621feb0..a26a3df46b 100644 --- a/met/src/tools/core/stat_analysis/aggr_stat_line.cc +++ b/met/src/tools/core/stat_analysis/aggr_stat_line.cc @@ -765,6 +765,9 @@ void aggr_summary_lines(LineDataFile &f, STATAnalysisJob &job, aggr.wgt[req_stat[i]] = empty_na; } m[key] = aggr; + mlog << Debug(3) << "[Case " << m.size() + << "] Added new case for key \"" + << key << "\".\n"; } // @@ -952,6 +955,9 @@ void aggr_ctc_lines(LineDataFile &f, STATAnalysisJob &job, aggr.cts_info = cur; aggr.hdr.clear(); m[key] = aggr; + mlog << Debug(3) << "[Case " << m.size() + << "] Added new case for key \"" + << key << "\".\n"; } // // Increment counts in the existing map entry @@ -1136,6 +1142,9 @@ void aggr_mctc_lines(LineDataFile &f, STATAnalysisJob &job, aggr.mcts_info = cur; aggr.hdr.clear(); m[key] = aggr; + mlog << Debug(3) << "[Case " << m.size() + << "] Added new case for key \"" + << key << "\".\n"; } // // Increment counts in the existing map entry @@ -1313,6 +1322,9 @@ void aggr_pct_lines(LineDataFile &f, STATAnalysisJob &job, aggr.pct_info = cur; aggr.hdr.clear(); m[key] = aggr; + mlog << Debug(3) << "[Case " << m.size() + << "] Added new case for key \"" + << key << "\".\n"; } // // Increment counts in the existing map entry @@ -1538,6 +1550,9 @@ void aggr_psum_lines(LineDataFile &f, STATAnalysisJob &job, aggr.nbrcnt_info = cur_nbrcnt; aggr.hdr.clear(); m[key] = aggr; + mlog << Debug(3) << "[Case " << m.size() + << "] Added new case for key \"" + << key << "\".\n"; } // // Increment sums in the existing map entry @@ -1693,6 +1708,9 @@ void aggr_grad_lines(LineDataFile &f, STATAnalysisJob &job, aggr.grad_info = cur; aggr.hdr.clear(); m[key] = aggr; + mlog << Debug(3) << "[Case " << m.size() + << "] Added new case for key \"" + << key << "\".\n"; } // // Increment counts in the existing map entry @@ -1801,6 +1819,9 @@ void aggr_wind_lines(LineDataFile &f, STATAnalysisJob &job, aggr.vl1l2_info = cur; aggr.hdr.clear(); m[key] = aggr; + mlog << Debug(3) << "[Case " << m.size() + << "] Added new case for key \"" + << key << "\".\n"; } // // Increment sums in the existing map entry @@ -1926,6 +1947,9 @@ void aggr_mpr_wind_lines(LineDataFile &f, STATAnalysisJob &job, // aggr.hdr.clear(); m[key] = aggr; + mlog << Debug(3) << "[Case " << m.size() + << "] Added new case for key \"" + << key << "\".\n"; } // // Otherwise, add data to existing map entry @@ -2204,6 +2228,10 @@ void aggr_mpr_lines(LineDataFile &f, STATAnalysisJob &job, aggr.hdr.clear(); m[key] = aggr; + + mlog << Debug(3) << "[Case " << m.size() + << "] Added new case for key \"" + << key << "\".\n"; } // // Increment sums in the existing map entry @@ -2304,6 +2332,9 @@ void aggr_isc_lines(LineDataFile &ldf, STATAnalysisJob &job, aggr.oen_na = aggr.baser_na = aggr.fbias_na = (NumArray *) 0; aggr.hdr.clear(); m[key] = aggr; + mlog << Debug(3) << "[Case " << m.size() + << "] Added new case for key \"" + << key << "\".\n"; } // @@ -2549,6 +2580,9 @@ void aggr_ecnt_lines(LineDataFile &f, STATAnalysisJob &job, if(m.count(key) == 0) { aggr.clear(); m[key] = aggr; + mlog << Debug(3) << "[Case " << m.size() + << "] Added new case for key \"" + << key << "\".\n"; } // @@ -2684,6 +2718,9 @@ void aggr_rps_lines(LineDataFile &f, STATAnalysisJob &job, aggr.rps_info = cur; aggr.hdr.clear(); m[key] = aggr; + mlog << Debug(3) << "[Case " << m.size() + << "] Added new case for key \"" + << key << "\".\n"; } // // Increment counts in the existing map entry @@ -2773,6 +2810,9 @@ void aggr_rhist_lines(LineDataFile &f, STATAnalysisJob &job, aggr.clear(); for(i=0; i Date: Wed, 18 Aug 2021 09:47:28 -0600 Subject: [PATCH 123/200] Per #1879, porting the same changes over to the develop branch. (#1881) --- met/src/libcode/vx_data2d_grib/var_info_grib.cc | 17 ++++++++--------- .../ensemble_stat/ensemble_stat_conf_info.cc | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/met/src/libcode/vx_data2d_grib/var_info_grib.cc b/met/src/libcode/vx_data2d_grib/var_info_grib.cc index de4d685846..a75b699674 100644 --- a/met/src/libcode/vx_data2d_grib/var_info_grib.cc +++ b/met/src/libcode/vx_data2d_grib/var_info_grib.cc @@ -212,12 +212,7 @@ void VarInfoGrib::add_grib_code (Dictionary &dict) } int field_center = dict.lookup_int (conf_key_GRIB1_center, false); int field_subcenter = dict.lookup_int (conf_key_GRIB1_subcenter, false); - Grib1TableEntry tab; - - // if not specified, fill others with default values - if(field_ptv == bad_data_int) field_ptv = default_grib1_ptv; - if(field_center == bad_data_int) field_center = default_grib1_center; - if(field_subcenter == bad_data_int) field_subcenter = default_grib1_subcenter; + Grib1TableEntry tab; // if the name is specified, use it if( !field_name.empty() ){ @@ -229,9 +224,13 @@ void VarInfoGrib::add_grib_code (Dictionary &dict) if( !GribTable.lookup_grib1(field_name.c_str(), default_grib1_ptv, field_code, default_grib1_center, default_grib1_subcenter, tab, tab_match) ) { mlog << Error << "\nVarInfoGrib::add_grib_code() -> " - << "unrecognized GRIB1 field abbreviation '" - << field_name << "' for table version " << field_ptv - << "\n\n"; + << "unrecognized GRIB1 field abbreviation '" << field_name + << "' for table version (" << field_ptv + << "), center (" << field_center + << "), and subcenter (" << field_subcenter + << ") or default table version (" << default_grib1_ptv + << "), center (" << default_grib1_center + << "), and subcenter (" << default_grib1_subcenter << ").\n\n"; exit(1); } } diff --git a/met/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc b/met/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc index c3d1235197..9dcf7154d3 100644 --- a/met/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc +++ b/met/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc @@ -691,7 +691,7 @@ void EnsembleStatVxOpt::process_config(GrdFileType ftype, Dictionary &fdict, vx_pd.obs_info->set_dict(odict); // Set the GRIB code for point observations - if(!use_var_id) vx_pd.obs_info->add_grib_code(odict); + if(point_vx && !use_var_id) vx_pd.obs_info->add_grib_code(odict); // Dump the contents of the current VarInfo if(mlog.verbosity_level() >= 5) { From 10e7f5ee06f1814d565c935670fd89bcc73d5d6c Mon Sep 17 00:00:00 2001 From: johnhg Date: Wed, 18 Aug 2021 11:54:39 -0600 Subject: [PATCH 124/200] Feature 1673 gbeta (#1857) * Per #1673, add a distance_map.beta_value entry to all the Grid-Stat config files. * Per #1673, enhance Grid-Stat to parse the new beta_value option and set its value in the library code. * Per #1673, set the user-defined beta_value when processing the distance map scores. * Per #1673, add 4 new DMAP columns write them. Just writing bad data values right now, still need to actually compute them! Also need to update Stat-Analysis to update the parsing/aggregation of these new values. * Per #1673, enable beta_value to be set to a default bad data value. * Per #1673 and @ericgilleland instruction (https://github.com/dtcenter/MET/issues/1673#issuecomment-876907466), strip asymmetric G-Beta (AGBETA) from the output. * Per #1673, fix typo that was causing the code not to compile. * Per #1673, update MET User's Guide about G/GBETA. * Per #1673, report BETA_VALUE = TOTAL / 2 in the output instead of NA, as directed by Eric. * Per #1673, remove descriptions of Grid-Stat-specific config options for nbrhd, fourier, gradient, and distance_map from the overview section since they belong in the Grid-Stat chapter. Also add direct links for them in the Grid-Stat chapter. * Per #1673, do not reset the beta_value in DMAP::clear(). * Per #1673, log the DMAP options only after the beta_value has been determined. * Per #1673, correct the default beta_value setting as N*N / 2.0. * Per #1673, trying to format G-beta well. * Per #1673, trying to format G-beta well. * Per #1673, beta is formatted as \beta and not \Beta in latex. * Per #1673, beta is formatted as \beta and not \Beta in latex. * Per #1673, switch to defining beta_value as a function of the input grid size. * Per #1673, push initial appendix C updates for GBETA. * Per #1673, working on G and GBETA equations. * Per #1673, working on G and GBETA equations. * Per 1673, update GBETA details in appendix C. * Per #1673, add Eric's info about selecting beta. * Per #1673, update reference for Gilleland-2019 to Gilleland_PartI-2020 and Gilleland_PartII-2020. * Per 1673, fix typo. * Per #1673, making changes requested by Eric. * Per #1673, making changes requested by Eric. * Per #1673, update references based on Eric's feedback. * Update appendixD.rst (#1869) Updated this appendix. * Update appendixD.rst * Per #1673, making the formatting of Gilleland-2020 part I and II references consistent. * Per #1673, update Grid-Stat docs to clarify that GBETA is only computed on the FULL verification domain and not any masking regions. * Per #1673, add DataPlane::n_good_data() function to return a count valid data values. * Per #1673, update vx_statistics library code to only set gbeta/beta_value to bad data for sub-domains. * Per #1673, update grid_stat to mask out bad data between the fcst/obs fields before computing distance maps. This will change existing unit test results! Also store the count of valid data values in the full verification domain. * Per #1673, since GBETA is only reported when VX_MASK = FULL, updating GridStatConfig_all to include the FULL masking region to make this example more meaningful. Co-authored-by: ericgilleland <34106925+ericgilleland@users.noreply.github.com> --- met/data/config/GridStatConfig_default | 1 + .../table_files/met_header_columns_V10.1.txt | 2 +- met/docs/Users_Guide/appendixC.rst | 25 +++- met/docs/Users_Guide/appendixD.rst | 5 +- met/docs/Users_Guide/config_options.rst | 132 +----------------- .../Users_Guide/figure/grid-stat_fig6.png | Bin 0 -> 153718 bytes met/docs/Users_Guide/grid-stat.rst | 68 +++++++-- met/docs/Users_Guide/refs.rst | 39 +++++- met/scripts/config/GridStatConfig_APCP_12 | 2 + met/scripts/config/GridStatConfig_APCP_24 | 2 + met/scripts/config/GridStatConfig_POP_12 | 2 + met/scripts/config/GridStatConfig_all | 4 +- met/src/basic/vx_config/config_constants.h | 1 + met/src/basic/vx_util/data_plane.cc | 16 +++ met/src/basic/vx_util/data_plane.h | 1 + met/src/basic/vx_util/stat_column_defs.h | 3 +- met/src/libcode/vx_stat_out/stat_columns.cc | 12 +- met/src/libcode/vx_statistics/met_stats.cc | 98 ++++++++++--- met/src/libcode/vx_statistics/met_stats.h | 17 ++- met/src/tools/core/grid_stat/grid_stat.cc | 17 ++- .../core/grid_stat/grid_stat_conf_info.cc | 14 ++ .../core/grid_stat/grid_stat_conf_info.h | 3 +- test/config/GridStatConfig_APCP_regrid | 1 + test/config/GridStatConfig_GRIB_lvl_typ_val | 1 + test/config/GridStatConfig_GRIB_set_attr | 1 + test/config/GridStatConfig_GTG_latlon | 1 + test/config/GridStatConfig_GTG_lc | 1 + test/config/GridStatConfig_apply_mask | 1 + test/config/GridStatConfig_climo_WMO | 1 + test/config/GridStatConfig_climo_prob | 1 + test/config/GridStatConfig_fourier | 1 + test/config/GridStatConfig_grid_weight | 1 + test/config/GridStatConfig_interp_shape | 1 + test/config/GridStatConfig_mpr_thresh | 1 + test/config/GridStatConfig_no_leap | 1 + test/config/GridStatConfig_prob_as_scalar | 1 + test/config/GridStatConfig_python | 1 + test/config/GridStatConfig_python_mixed | 1 + test/config/GridStatConfig_rtma | 1 + test/config/GridStatConfig_rtma_perc_thresh | 1 + test/config/GridStatConfig_st4 | 1 + test/config/GridStatConfig_st4_censor | 1 + test/config/ref_config/GridStatConfig_03h | 1 + test/config/ref_config/GridStatConfig_24h | 1 + test/hdr/met_10_1.hdr | 2 +- 45 files changed, 310 insertions(+), 178 deletions(-) create mode 100644 met/docs/Users_Guide/figure/grid-stat_fig6.png diff --git a/met/data/config/GridStatConfig_default b/met/data/config/GridStatConfig_default index e79a3e42b1..89dc90e156 100644 --- a/met/data/config/GridStatConfig_default +++ b/met/data/config/GridStatConfig_default @@ -202,6 +202,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/met/data/table_files/met_header_columns_V10.1.txt b/met/data/table_files/met_header_columns_V10.1.txt index d538d74c92..87b5eba258 100644 --- a/met/data/table_files/met_header_columns_V10.1.txt +++ b/met/data/table_files/met_header_columns_V10.1.txt @@ -10,7 +10,7 @@ V10.1 : STAT : NBRCNT : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID V10.1 : STAT : NBRCTC : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FY_OY FY_ON FN_OY FN_ON V10.1 : STAT : NBRCTS : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL BASER BASER_NCL BASER_NCU BASER_BCL BASER_BCU FMEAN FMEAN_NCL FMEAN_NCU FMEAN_BCL FMEAN_BCU ACC ACC_NCL ACC_NCU ACC_BCL ACC_BCU FBIAS FBIAS_BCL FBIAS_BCU PODY PODY_NCL PODY_NCU PODY_BCL PODY_BCU PODN PODN_NCL PODN_NCU PODN_BCL PODN_BCU POFD POFD_NCL POFD_NCU POFD_BCL POFD_BCU FAR FAR_NCL FAR_NCU FAR_BCL FAR_BCU CSI CSI_NCL CSI_NCU CSI_BCL CSI_BCU GSS GSS_BCL GSS_BCU HK HK_NCL HK_NCU HK_BCL HK_BCU HSS HSS_BCL HSS_BCU ODDS ODDS_NCL ODDS_NCU ODDS_BCL ODDS_BCU LODDS LODDS_NCL LODDS_NCU LODDS_BCL LODDS_BCU ORSS ORSS_NCL ORSS_NCU ORSS_BCL ORSS_BCU EDS EDS_NCL EDS_NCU EDS_BCL EDS_BCU SEDS SEDS_NCL SEDS_NCU SEDS_BCL SEDS_BCU EDI EDI_NCL EDI_NCU EDI_BCL EDI_BCU SEDI SEDI_NCL SEDI_NCU SEDI_BCL SEDI_BCU BAGSS BAGSS_BCL BAGSS_BCU V10.1 : STAT : GRAD : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FGBAR OGBAR MGBAR EGBAR S1 S1_OG FGOG_RATIO DX DY -V10.1 : STAT : DMAP : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FY OY FBIAS BADDELEY HAUSDORFF MED_FO MED_OF MED_MIN MED_MAX MED_MEAN FOM_FO FOM_OF FOM_MIN FOM_MAX FOM_MEAN ZHU_FO ZHU_OF ZHU_MIN ZHU_MAX ZHU_MEAN +V10.1 : STAT : DMAP : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FY OY FBIAS BADDELEY HAUSDORFF MED_FO MED_OF MED_MIN MED_MAX MED_MEAN FOM_FO FOM_OF FOM_MIN FOM_MAX FOM_MEAN ZHU_FO ZHU_OF ZHU_MIN ZHU_MAX ZHU_MEAN G GBETA BETA_VALUE V10.1 : STAT : ORANK : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL INDEX OBS_SID OBS_LAT OBS_LON OBS_LVL OBS_ELV OBS PIT RANK N_ENS_VLD (N_ENS) ENS_[0-9]* OBS_QC ENS_MEAN CLIMO_MEAN SPREAD ENS_MEAN_OERR SPREAD_OERR SPREAD_PLUS_OERR CLIMO_STDEV V10.1 : STAT : PCT : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL (N_THRESH) THRESH_[0-9]* OY_[0-9]* ON_[0-9]* V10.1 : STAT : PJC : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL (N_THRESH) THRESH_[0-9]* OY_TP_[0-9]* ON_TP_[0-9]* CALIBRATION_[0-9]* REFINEMENT_[0-9]* LIKELIHOOD_[0-9]* BASER_[0-9]* diff --git a/met/docs/Users_Guide/appendixC.rst b/met/docs/Users_Guide/appendixC.rst index 10eb14f5d8..d6523fb1c2 100644 --- a/met/docs/Users_Guide/appendixC.rst +++ b/met/docs/Users_Guide/appendixC.rst @@ -1134,7 +1134,7 @@ A mathematical metric, :math:`m(A,B)\geq 0`, must have the following three prope The first establishes that a perfect score is zero and that the only way to obtain a perfect score is if the two sets are identical according to the metric. The second requirement ensures that the order by which the two sets are evaluated will not change the result. The third property ensures that if *C* is closer to *A* than *B* is to *A*, then :math:`m(A,C) < m(A,B)`. -It has been argued in :ref:`Gilleland (2019) ` that the second property of symmetry is not necessarily an important quality to have for a summary measure for verification purposes because lack of symmetry allows for information about false alarms and misses. +It has been argued in :ref:`Gilleland (2017) ` that the second property of symmetry is not necessarily an important quality to have for a summary measure for verification purposes because lack of symmetry allows for information about false alarms and misses. The results of the distance map verification approaches that are included in the Grid-Stat tool are summarized using a variety of measures. These measures include Baddeley's :math:`\Delta` Metric, the Hausdorff Distance, the Mean-error Distance, Pratt's Figure of Merit, and Zhu's Measure. Their equations are listed below. @@ -1205,6 +1205,29 @@ where MED *(A,B)* is as in the Mean-error distance, *N* is the total number of g The range for ZHU is 0 to infinity, with a score of 0 indicating a perfect forecast. +.. _App_C-gbeta: + +:math:`G` and :math:`G_\beta` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Called "G" and "GBETA" in the DMAP output :numref:`table_GS_format_info_DMAP` + +See :numref:`grid-stat_gbeta` for a description. + +Let :math:`y = {y_1}{y_2}` where :math:`y_1 = n_A + n_B - 2n_{AB}`, and :math:`y_2 = MED(A,B) \cdot n_B + MED(B,A) \cdot n_A`, with the mean-error distance (:math:`MED`) as described above, and where :math:`n_{A}`, :math:`n_{B}`, and :math:`n_{AB}` are the number of events within event areas *A*, *B*, and the intersection of *A* and *B*, respectively. + +The :math:`G` performance measure is given by + +.. math:: G(A,B) = y^{1/3} + +and the :math:`G_\beta` performance measure is given by + +.. math:: G_\beta(A,B) = max\{1-\frac{y}{\beta}, 0\} + +where :math:`\beta > 0` is a user-chosen parameter with a default value of :math:`n^2 / 2.0` with :math:`n` equal to the number of points in the domain. The square-root of :math:`G` will give units of grid points, where :math:`y^{1/3}` gives units of grid points squared. + +The range for :math:`G_\beta` is 0 to 1, with a score of 1 indicating a perfect forecast. + Calculating Percentiles _______________________ diff --git a/met/docs/Users_Guide/appendixD.rst b/met/docs/Users_Guide/appendixD.rst index a90c71b620..66c578e91a 100644 --- a/met/docs/Users_Guide/appendixD.rst +++ b/met/docs/Users_Guide/appendixD.rst @@ -77,8 +77,9 @@ All other verification scores with CIs in MET must be obtained through bootstrap 5. Calculate CIs for the parameters directly from the sample (see text below for more details) -Typically, a simple random sample is taken for step 2, and that is how it is done in MET. As an example of what happens in this step, suppose our sample is :math:`X_1,X_2,X_3,X_4`. Then, one possible replicate might be :math:`X_2,X_2,X_2,X_4`. Usually one samples :math:`m = n` points in this step, but there are cases where one should use :math:`m < n`. For example, when the underlying distribution is heavy-tailed, one should use a smaller size m than n (e.g., the closest integer value to the square root of the original sample size). +Typically, a simple random sample is taken for step 2, and that is how it is done in MET. As an example of what happens in this step, suppose our sample is :math:`X_1,X_2,X_3,X_4`. Then, one possible replicate might be :math:`X_2,X_2,X_2,X_4`. Usually one samples :math:`m = n` points in this step, but there are cases where one should use :math:`m < n`. For example, when the underlying distribution is heavy-tailed, one should use a smaller size m than n (e.g., the closest integer value to the square root of the original sample size). See :ref:`Gilleland (2020, part II) ` for considerably more information about the issues with estimators that follow a heavy tailed distribution and the closely related issue of bootstrapping extreme-valued estimators, such as the maximum, in the atmospheric science domain. There are numerous ways to construct CIs from the sample obtained in step 4. MET allows for two of these procedures: the percentile and the BCa. The percentile is the most commonly known method, and the simplest to understand. It is merely the :math:`\alpha / 2` and :math:`1 - \alpha / 2` percentiles from the sample of statistics. Unfortunately, however, it has been shown that this interval is too optimistic in practice (i.e., it doesn't have accurate coverage). One solution is to use the BCa method, which is very accurate, but it is also computationally intensive. This method adjusts for bias and non-constant variance, and yields the percentile interval in the event that the sample is unbiased with constant variance. -If there is dependency in the sample, then it is prudent to account for this dependency in some way. One method that does not make a lot of assumptions is circular block bootstrapping. This is not currently implemented in MET, but will be available in a future release. At that time, the method will be explained more fully here, but until then consult :ref:`Gilleland (2010) ` for more details. +If there is dependency in the sample, then it is prudent to account for this dependency in some way. :ref:`Gilleland (2010) ` describes the bootstrap procedure, along with the above-mentioned parametric methods, in more detail specifically for the verification application. If there is dependency in the sample, then it is prudent to account for this dependency in some way (see :ref:`Gilleland (2020, part I) ` part I for an in-depth discussion of bootstrapping in the competing forecast verification domain). One method that is particularly appropriate for serially dependent data is the circular block resampling procedure for step 2. + diff --git a/met/docs/Users_Guide/config_options.rst b/met/docs/Users_Guide/config_options.rst index a490ea1e27..5c3149b03f 100644 --- a/met/docs/Users_Guide/config_options.rst +++ b/met/docs/Users_Guide/config_options.rst @@ -413,7 +413,7 @@ e.g. model = "GFS"; model = "WRF"; -.._desc: +.. _desc: :ref:`desc ` @@ -1615,136 +1615,6 @@ This dictionary may include the following entries: ]; } -.. _nbrhd: - -:ref:`nbrhd ` - -The "nbrhd" entry is a dictionary that is very similar to the "interp" -entry. It specifies information for computing neighborhood statistics in -Grid-Stat. This dictionary may include the following entries: - -* The "field" entry specifies to which field(s) the computation of - fractional coverage should be applied. Grid-Stat processes each - combination of categorical threshold and neighborhood width to - derive the fractional coverage fields from which neighborhood - statistics are calculated. Users who have computed fractional - coverage fields outside of MET can use this option to disable - these computations. Instead, the raw input values will be - used directly to compute neighborhood statistics: - - * "BOTH" to compute fractional coverage for both the forecast - and the observation fields (default). - - * "FCST" to only process the forecast field. - - * "OBS" to only process the observation field. - - * "NONE" to process neither field. - -* The "vld_thresh" entry is described above. - -* The "shape" entry defines the shape of the neighborhood. - Valid values are "SQUARE" or "CIRCLE" - -* The "width" entry is as described above, and must be odd. - -* The "cov_thresh" entry is an array of thresholds to be used when - computing categorical statistics for the neighborhood fractional - coverage field. - -.. code-block:: none - - nbrhd = { - field = BOTH; - vld_thresh = 1.0; - shape = SQUARE; - width = [ 1 ]; - cov_thresh = [ >=0.5 ]; - } - -.. _fourier: - -:ref:`fourier ` - -The "fourier" entry is a dictionary which specifies the application of the -Fourier decomposition method. It consists of two arrays of the same length -which define the beginning and ending wave numbers to be included. If the -arrays have length zero, no Fourier decomposition is applied. For each array -entry, the requested Fourier decomposition is applied to the forecast and -observation fields. The beginning and ending wave numbers are indicated in -the MET ASCII output files by the INTERP_MTHD column (e.g. WV1_0-3 for waves -0 to 3 or WV1_10 for only wave 10). This 1-dimensional Fourier decomposition -is computed along the Y-dimension only (i.e. the columns of data). It is only -defined when each grid point contains valid data. If either input field -contains missing data, no Fourier decomposition is computed. - -The available wave numbers start at 0 (the mean across each row of data) -and end at (Nx+1)/2 (the finest level of detail), where Nx is the X-dimension -of the verification grid: - -* The "wave_1d_beg" entry is an array of integers specifying the first - wave number to be included. - -* The "wave_1d_end" entry is an array of integers specifying the last - wave number to be included. - -.. code-block:: none - - fourier = { - wave_1d_beg = [ 0, 4, 10 ]; - wave_1d_end = [ 3, 9, 20 ]; - } - -.. _gradient: - -:ref:`gradient ` - -The "gradient" entry is a dictionary which specifies the number and size of -gradients to be computed. The "dx" and "dy" entries specify the size of the -gradients in grid units in the X and Y dimensions, respectively. dx and dy -are arrays of integers (positive or negative) which must have the same -length, and the GRAD output line type will be computed separately for each -entry. When computing gradients, the value at the (x, y) grid point is -replaced by the value at the (x+dx, y+dy) grid point minus the value at -(x, y). - -This configuration option may be set separately in each "obs.field" entry. - -.. code-block:: none - - gradient = { - dx = [ 1 ]; - dy = [ 1 ]; - } - -.. _distance_map: - -:ref:`distance_map ` - -The "distance_map" entry is a dictionary containing options related to the -distance map statistics in the DMAP output line type. The "baddeley_p" entry -is an integer specifying the exponent used in the Lp-norm when computing the -Baddeley Delta metric. The "baddeley_max_dist" entry is a floating point -number specifying the maximum allowable distance for each distance map. Any -distances larger than this number will be reset to this constant. A value of -NA indicates that no maximum distance value should be used. The "fom_alpha" -entry is a floating point number specifying the scaling constant to be used -when computing Pratt's Figure of Merit. The "zhu_weight" specifies a value -between 0 and 1 to define the importance of the RMSE of the binary fields -(i.e. amount of overlap) versus the mean-error distance (MED). The default -value of 0.5 gives equal weighting. - -This configuration option may be set separately in each "obs.field" entry. - -.. code-block:: none - - distance_map = { - baddeley_p = 2; - baddeley_max_dist = NA; - fom_alpha = 0.1; - zhu_weight = 0.5; - } - .. _land_mask: :ref:`land_mask ` diff --git a/met/docs/Users_Guide/figure/grid-stat_fig6.png b/met/docs/Users_Guide/figure/grid-stat_fig6.png new file mode 100644 index 0000000000000000000000000000000000000000..e0916152f709d4a28005cff941aa855c0429a191 GIT binary patch literal 153718 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 y)1HZ(p%5C;( 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%0D*^h)WI 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. For each combination of input field and categorical threshold requested in the configuration file, Grid-Stat applies that threshold to define events in the forecast and observation fields and computes distance maps for those binary fields. Statistics for all requested masking regions are derived from those distance maps. Note that the distance maps are computed only once over the full verification domain, not separately for each masking region. Events occurring outside of a masking region can affect the distance map values inside that masking region and, therefore, can also affect the distance maps statistics for that region. +The statistics derived from these distance maps are described in :numref:`Appendix C, Section %s `. To make fair comparisons, any grid point containing bad data in either the forecast or observation field is set to bad data in both fields. For each combination of input field and categorical threshold requested in the configuration file, Grid-Stat applies that threshold to define events in the forecast and observation fields and computes distance maps for those binary fields. Statistics for all requested masking regions are derived from those distance maps. Note that the distance maps are computed only once over the full verification domain, not separately for each masking region. Events occurring outside of a masking region can affect the distance map values inside that masking region and, therefore, can also affect the distance maps statistics for that region. + +.. _grid-stat_gbeta: + +:math:`\beta` and :math:`G_\beta` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See :numref:`App_C-gbeta` for the :math:`G` and :math:`G_\beta` equations. + +:math:`G_\beta` provides a summary measure of forecast quality for each user-defined threshold chosen. It falls into a range from zero to one where one is a perfect forecast and zero is considered to be a very poor forecast as determined by the user through the value of :math:`\beta`. Values of :math:`G_\beta` closer to one represent better forecasts and worse forecasts as it decreases toward zero. Although a particular value cannot be universally compared against any forecast, when applied with the same choice of :math:`\beta` for the same variable and on the same domain, it is highly effective at ranking such forecasts. + +:math:`G_\beta` is sensitive to the choice of :math:`\beta`, which depends on the (i) specific domain, (ii) variable, and (iii) user’s needs. Smaller values make :math:`G_\beta` more stringent and larger values make it more lenient. :numref:`grid-stat_fig6` shows an example of applying :math:`G_\beta` over a range of :math:`\beta` values to a precipitation verification set where the binary fields are created by applying a threshold of :math:`2.1 mmh^{-1}`. Color choice and human bias can make it difficult to determine the quality of the forecast for a human observer looking at the raw images in the top row of the figure (:ref:`Ahijevych et al., 2009 `). The bottom left panel of the figure displays the differences in their binary fields, which highlights that the forecast captured the overall shapes of the observed rain areas but suffers from a spatial displacement error (perhaps really a timing error). + +Whether or not the forecast from :numref:`grid-stat_fig6` is “good” or not depends on the specific user. Is it sufficient that the forecast came as close as it did to the observation field? If the answer is yes for the user, then a higher choice of :math:`\beta`, such as :math:`N/2`, with :math:`N` equal to the number of points in the domain, will correctly inform this user that it is a “good” forecast as it will lead to a :math:`G_\beta` value near one. If the user requires the forecast to be much better aligned spatially with the observation field, then a lower choice, perhaps :math:`\beta = N`, will correctly inform that the forecast suffers from spatial displacement errors that are too large for this user to be pleased. If the goal is to rank a series of ensemble forecasts, for example, then a choice of :math:`\beta` that falls in the steep part of the curve shown in the lower right panel of the figure should be preferred, say somewhere between :math:`\beta = N` and :math:`\beta = N^2/2`. Such a choice will ensure that each member is differentiated by the measure. + +.. _grid-stat_fig6: + +.. figure:: figure/grid-stat_fig6.png + + Top left is an example of an accumulated precipitation (mm/h) forecast with the corresponding observed field on the top right. Bottom left shows the difference in binary fields, where the binary fields are created by setting all values in the original fields that fall above :math:`2.1 mmh^{-1}` to one and the rest to zero. Bottom right shows the results for :math:`G_\beta` calculated on the binary fields using the threshold of :math:`2.1 mmh^{-1}` over a range of choices for :math:`\beta`. + +In some cases, a user may be interested in a much higher threshold than :math:`2.1 mmh^{-1}` of the above example. :ref:`Gilleland, 2021 (Fig. 4) `, for example, shows this same forecast using a threshold of :math:`40 mmh^{-1}`. Only a small area in Mississippi has such extreme rain predicted at this valid time; yet none was observed. Small spatial areas of extreme rain in the observed field, however, did occur in a location far away from Mississippi that was not predicted. Generally, for this type of verification, the Hausdorff metric is a good choice of measure. However, a small choice of :math:`\beta` will provide similar results as the Hausdorff distance (:ref:`Gilleland, 2021 `). The user should think about the average size of storm areas and multiply this value by the displacement distance they are comfortable with in order to get a good initial choice for :math:`\beta`, and may have to increase or decrease its value by trial-and-error using one or two example cases from their verification set. + +Since :math:`G_\beta` is so sensitive to the choice of :math:`\beta`, which is defined relative to the number of points in the verification domain, :math:`G_\beta` is only computed for the full verification domain. :math:`G_\beta` is reported as a bad data value for any masking region subsets of the full verification domain. Practical information _____________________ @@ -234,6 +257,10 @@ The configuration options listed above are common to multiple MET tools and are ___________________________ +.. _nbrhd: + +:ref:`nbrhd ` + .. code-block:: none nbrhd = { @@ -244,7 +271,7 @@ ___________________________ cov_thresh = [ >=0.5 ]; } - + The **nbrhd** dictionary contains a list of values to be used in defining the neighborhood to be used when computing neighborhood verification statistics. The neighborhood **shape** is a **SQUARE** or **CIRCLE** centered on the current point, and the **width** value specifies the width of the square or diameter of the circle as an odd integer. The **field** entry is set to **BOTH, FCST, OBS**, or **NONE** to indicate the fields to which the fractional coverage derivation logic should be applied. This should always be set to **BOTH** unless you have already computed the fractional coverage field(s) with numbers between 0 and 1 outside of MET. @@ -255,6 +282,10 @@ The **cov_thresh** entry contains a comma separated list of thresholds to be app ___________________ +.. _fourier: + +:ref:`fourier ` + .. code-block:: none fourier = { @@ -263,25 +294,36 @@ ___________________ } -The **fourier** entry is a dictionary which specifies the application of the Fourier decomposition method. It consists of two arrays of the same length which define the beginning and ending wave numbers to be included. If the arrays have length zero, no Fourier decomposition is applied. For each array entry, the requested Fourier decomposition is applied to the forecast and observation fields. The beginning and ending wave numbers are indicated in the MET ASCII output files by the INTERP_MTHD column (e.g. WV1_0-3 for waves 0 to 3 or WV1_10 for only wave 10). This 1-dimensional Fourier decomposition is computed along the Y-dimension only (i.e. the columns of data). It is applied to the forecast and observation fields as well as the climatological mean field, if specified. It is only defined when each grid point contains valid data. If any input field contains missing data, no Fourier decomposition is computed. The available wave numbers start at 0 (the mean across each row of data) and end at (Nx+1)/2 (the finest level of detail), where Nx is the X-dimension of the verification grid. +The **fourier** entry is a dictionary which specifies the application of the Fourier decomposition method. It consists of two arrays of the same length which define the beginning and ending wave numbers to be included. If the arrays have length zero, no Fourier decomposition is applied. For each array entry, the requested Fourier decomposition is applied to the forecast and observation fields. The beginning and ending wave numbers are indicated in the MET ASCII output files by the INTERP_MTHD column (e.g. WV1_0-3 for waves 0 to 3 or WV1_10 for only wave 10). This 1-dimensional Fourier decomposition is computed along the Y-dimension only (i.e. the columns of data). It is applied to the forecast and observation fields as well as the climatological mean field, if specified. It is only defined when each grid point contains valid data. If any input field contains missing data, no Fourier decomposition is computed. + +The available wave numbers start at 0 (the mean across each row of data) and end at (Nx+1)/2 (the finest level of detail), where Nx is the X-dimension of the verification grid: + +* The **wave_1d_beg** entry is an array of integers specifying the first wave number to be included. -The **wave_1d_beg** entry is an array of integers specifying the first wave number to be included. The **wave_1d_end** entry is an array of integers specifying the last wave number to be included. +* The **wave_1d_end** entry is an array of integers specifying the last wave number to be included. _____________________ +.. _gradient: + +:ref:`gradient ` + .. code-block:: none - grad = { + gradient = { dx = [ 1 ]; dy = [ 1 ]; } - The **gradient** entry is a dictionary which specifies the number and size of gradients to be computed. The **dx** and **dy** entries specify the size of the gradients in grid units in the X and Y dimensions, respectively. **dx** and **dy** are arrays of integers (positive or negative) which must have the same length, and the GRAD output line type will be computed separately for each entry. When computing gradients, the value at the (x, y) grid point is replaced by the value at the (x+dx, y+dy) grid point minus the value at (x, y). This configuration option may be set separately in each **obs.field** entry. ____________________ +.. _distance_map: + +:ref:`distance_map ` + .. code-block:: none distance_map = { @@ -289,9 +331,10 @@ ____________________ baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } -The **distance_map** entry is a dictionary containing options related to the distance map statistics in the **DMAP** output line type. The **baddeley_p** entry is an integer specifying the exponent used in the Lp-norm when computing the Baddeley Delta metric. The **baddeley_max_dist** entry is a floating point number specifying the maximum allowable distance for each distance map. Any distances larger than this number will be reset to this constant. A value of **NA** indicates that no maximum distance value should be used. The **fom_alpha** entry is a floating point number specifying the scaling constant to be used when computing Pratt's Figure of Merit. The **zhu_weight** specifies a value between 0 and 1 to define the importance of the RMSE of the binary fields (i.e. amount of overlap) versus the mean-error distance (MED). The default value of 0.5 gives equal weighting. This configuration option may be set separately in each **obs.field** entry. +The **distance_map** entry is a dictionary containing options related to the distance map statistics in the **DMAP** output line type. The **baddeley_p** entry is an integer specifying the exponent used in the Lp-norm when computing the Baddeley :math:`\Delta` metric. The **baddeley_max_dist** entry is a floating point number specifying the maximum allowable distance for each distance map. Any distances larger than this number will be reset to this constant. A value of **NA** indicates that no maximum distance value should be used. The **fom_alpha** entry is a floating point number specifying the scaling constant to be used when computing Pratt's Figure of Merit. The **zhu_weight** specifies a value between 0 and 1 to define the importance of the RMSE of the binary fields (i.e. amount of overlap) versus the mean-error distance (MED). The default value of 0.5 gives equal weighting. This configuration option may be set separately in each **obs.field** entry. The **beta_value** entry is defined as a function of n, where n is the total number of grid points in the full verification domain containing valid data in both the forecast and observation fields. The resulting beta_value is used to compute the :math:`G_\beta` statistic. The default function, :math:`N^2 / 2`, is recommended in :ref:`Gilleland, 2021 ` but can be modified as needed. _____________________ @@ -755,7 +798,7 @@ The format of the STAT and ASCII output of the Grid-Stat tool are the same as th - Frequency Bias * - 29 - BADDELEY - - Baddeley's Delta Metric + - Baddeley's :math:`\Delta` Metric * - 30 - HAUSDORFF - Hausdorff Distance @@ -804,6 +847,15 @@ The format of the STAT and ASCII output of the Grid-Stat tool are the same as th * - 45 - ZHU_MEAN - Mean of ZHU_FO and ZHU_OF + * - 46 + - G + - :math:`G` distance measure + * - 47 + - GBETA + - :math:`G_\beta` distance measure + * - 48 + - BETA_VALUE + - Beta value used to compute :math:`G_\beta` If requested using the **nc_pairs_flag** dictionary in the configuration file, a NetCDF file containing the matched pair and forecast minus observation difference fields for each combination of variable type/level and masking region applied will be generated. The contents of this file are determined by the contents of the nc_pairs_flag dictionary. The output NetCDF file is named similarly to the other output files: **grid_stat_PREFIX_ HHMMSSL_YYYYMMDD_HHMMSSV_pairs.nc**. Commonly available NetCDF utilities such as ncdump or ncview may be used to view the contents of the output file. diff --git a/met/docs/Users_Guide/refs.rst b/met/docs/Users_Guide/refs.rst index 090c16ce0f..647e3591bf 100644 --- a/met/docs/Users_Guide/refs.rst +++ b/met/docs/Users_Guide/refs.rst @@ -9,6 +9,13 @@ References | Atlantic Basin. *Weather & Forecasting*, 13, 1005-1015. | +.. _Ahijevych-2009: + +| Ahijevych, D., E. Gilleland, B.G. Brown, and E.E. Ebert, 2009. Application of +| spatial verification methods to idealized and NWP-gridded precipitation forecasts. +| Weather Forecast., 24 (6), 1485 - 1497, doi: 10.1175/2009WAF2222298.1. +| + .. _Barker-1991: @@ -115,12 +122,36 @@ References | Gilleland, E., 2010: Confidence intervals for forecast verification. | *NCAR Technical Note* NCAR/TN-479+STR, 71pp. +| + +.. _Gilleland-2017: + +| Gilleland, E., 2017. A new characterization in the spatial verification +| framework for false alarms, misses, and overall patterns. +| Weather Forecast., 32 (1), 187 - 198, doi: 10.1175/WAF-D-16-0134.1. +| + + +.. _Gilleland_PartI-2020: + +| Gilleland, E., 2020. Bootstrap methods for statistical inference. +| Part I: Comparative forecast verification for continuous variables. +| Journal of Atmospheric and Oceanic Technology, 37 (11), 2117 - 2134, +| doi: 10.1175/JTECH-D-20-0069.1. +| + +.. _Gilleland_PartII-2020: + +| Gilleland, E., 2020. Bootstrap methods for statistical inference. +| Part II: Extreme-value analysis. Journal of Atmospheric and Oceanic +| Technology, 37 (11), 2135 - 2144, doi: 10.1175/JTECH-D-20-0070.1. +| -.. _Gilleland-2019: +.. _Gilleland-2021: -| Gilleland, E., 2019: Bootstrap methods for statistical inference. Part II: -| Extreme-value analysis. Submitted to the Journal of Atmospheric and -| Oceanic Technology on 2 December 2019. Re-submitted on 12 May 2020 +| Gilleland, E., 2021. Novel measures for summarizing high-resolution forecast +| performance. Advances in Statistical Climatology, Meteorology and Oceanography, +| 7 (1), 13 - 34, doi: 10.5194/ascmo-7-13-2021. | .. _Gneiting-2004: diff --git a/met/scripts/config/GridStatConfig_APCP_12 b/met/scripts/config/GridStatConfig_APCP_12 index e63c3a3d23..76747e7908 100644 --- a/met/scripts/config/GridStatConfig_APCP_12 +++ b/met/scripts/config/GridStatConfig_APCP_12 @@ -158,6 +158,8 @@ distance_map = { baddeley_p = 2; baddeley_max_dist = NA; fom_alpha = 0.1; + zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/met/scripts/config/GridStatConfig_APCP_24 b/met/scripts/config/GridStatConfig_APCP_24 index 9ad9e8bb53..bca332cdde 100644 --- a/met/scripts/config/GridStatConfig_APCP_24 +++ b/met/scripts/config/GridStatConfig_APCP_24 @@ -168,6 +168,8 @@ distance_map = { baddeley_p = 2; baddeley_max_dist = NA; fom_alpha = 0.1; + zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/met/scripts/config/GridStatConfig_POP_12 b/met/scripts/config/GridStatConfig_POP_12 index 20c48f59a6..2df3bc3914 100644 --- a/met/scripts/config/GridStatConfig_POP_12 +++ b/met/scripts/config/GridStatConfig_POP_12 @@ -168,6 +168,8 @@ distance_map = { baddeley_p = 2; baddeley_max_dist = NA; fom_alpha = 0.1; + zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/met/scripts/config/GridStatConfig_all b/met/scripts/config/GridStatConfig_all index 901ec29565..13b7f601f3 100644 --- a/met/scripts/config/GridStatConfig_all +++ b/met/scripts/config/GridStatConfig_all @@ -118,7 +118,7 @@ climo_mean = { // Verification masking regions // mask = { - grid = [ "DTC165", "DTC166" ]; + grid = [ "FULL", "DTC165", "DTC166" ]; poly = [ "${TEST_OUT_DIR}/gen_vx_mask/CONUS_poly.nc", "MET_BASE/poly/LMV.poly" ]; } @@ -199,6 +199,8 @@ distance_map = { baddeley_p = 2; baddeley_max_dist = NA; fom_alpha = 0.1; + zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/met/src/basic/vx_config/config_constants.h b/met/src/basic/vx_config/config_constants.h index d3b8773e58..34fe74c978 100644 --- a/met/src/basic/vx_config/config_constants.h +++ b/met/src/basic/vx_config/config_constants.h @@ -692,6 +692,7 @@ static const char conf_key_baddeley_p[] = "baddeley_p"; static const char conf_key_baddeley_max_dist[] = "baddeley_max_dist"; static const char conf_key_fom_alpha[] = "fom_alpha"; static const char conf_key_zhu_weight[] = "zhu_weight"; +static const char conf_key_beta_value[] = "beta_value"; // // Wavelet-Stat specific parameter key names diff --git a/met/src/basic/vx_util/data_plane.cc b/met/src/basic/vx_util/data_plane.cc index c855b2a1d5..c49c360918 100644 --- a/met/src/basic/vx_util/data_plane.cc +++ b/met/src/basic/vx_util/data_plane.cc @@ -297,6 +297,22 @@ bool DataPlane::is_all_bad_data() const { /////////////////////////////////////////////////////////////////////////////// +int DataPlane::n_good_data() const { + int j, n; + + // + // Count number of good data values + // + + for(j=0,n=0; j " + << "the beta_value (" << beta_value + << ") must be greater than 0!\n\n"; + exit(1); + } + // Initialize clear(); @@ -2852,28 +2868,29 @@ void DMAPInfo::set(const SingleThresh &fthr, const SingleThresh &othr, non_zero_count = 0; - mlog << Debug(4) << " DMAP.Options: baddeley_p=" << baddeley_p - << ", baddeley_max_dist=" << baddeley_max_dist - << ", fom_alpha=" << fom_alpha - << ", zhu_weight=" << zhu_weight << "\n"; - for (int i=0; i 0) { fy++; med_of_sum += odmap_na[i]; fom_of_sum += 1 / (1 + odmap_na[i] * odmap_na[i] * fom_alpha); } + + // Observation if (othr_na[i] > 0) { oy++; med_fo_sum += fdmap_na[i]; fom_fo_sum += 1 / (1 + fdmap_na[i] * fdmap_na[i] * fom_alpha); } + // Forecast and observation event + if (fthr_na[i] > 0 && othr_na[i] > 0) foy++; + sum_event_diff += (fthr_na[i] - othr_na[i]) * (fthr_na[i] - othr_na[i]); f_distance = (!is_bad_data(baddeley_max_dist) && @@ -2937,26 +2954,67 @@ void DMAPInfo::set(const SingleThresh &fthr, const SingleThresh &othr, zhu_mean = (zhu_fo + zhu_of) / 2; } - mlog << Debug(4) << " DMAP: nf=" << fy << ", no=" << oy << ", total=" << total - << "\tbaddeley=" << baddeley << ", hausdorff=" << hausdorff - << "\n\tmed_fo=" << med_fo << ", med_of=" << med_of - << ", med_min=" << med_min << ", med_max=" << med_max << ", med_mean=" << med_mean - << "\n\tfom_fo=" << fom_fo << ", fom_of=" << fom_of - << ", fom_min=" << fom_min << ", fom_max=" << fom_max << ", fom_mean=" << fom_mean - << "\n\tzhu_fo=" << zhu_fo << ", zhu_of=" << zhu_of - << ", zhu_min=" << zhu_min << ", zhu_max=" << zhu_max << ", zhu_mean=" << zhu_mean + // G and G-Beta + // Reference: + // Gilleland, E.: Novel measures for summarizing high-resolution forecast performance, + // Adv. Stat. Clim. Meteorol. Oceanogr., 7, 13–34, + // https://doi.org/10.5194/ascmo-7-13-2021, 2021. + + // If not set by the user, default maximum distance to the number of pairs + double max_dist = (is_bad_data(baddeley_max_dist) ? + (double) total : baddeley_max_dist); + + double g_med_fo = (oy == 0 ? max_dist : med_fo); + double g_med_of = (fy == 0 ? max_dist : med_of); + int g_y1 = fy + oy - 2 * foy; + double g_y2 = g_med_fo * oy + g_med_of * fy; + double g_y = g_y1 * g_y2; + g = pow(g_y, 1.0 / 3.0); + + // Only compute GBETA over the full verification domain. + // Report bad data for masking regions. + if(total == n_full_points) { + gbeta = max(1.0 - g_y / beta_value, 0.0); + } + else { + gbeta = beta_value = bad_data_double; + } + + // Dump debug distance map info + mlog << Debug(4) << " DMAP.Options: baddeley_p=" << baddeley_p + << ", baddeley_max_dist=" << baddeley_max_dist + << ", fom_alpha=" << fom_alpha + << ", zhu_weight=" << zhu_weight + << ", beta_value=" << beta_value + << ", n_full_points=" << n_full_points << "\n"; + + mlog << Debug(4) << " DMAP: nf=" << fy << ", no=" << oy << ", nfo=" << foy << ", total=" << total + << "\n\tbaddeley=" << baddeley << ", hausdorff=" << hausdorff + << "\n\tmed_fo=" << med_fo << ", med_of=" << med_of + << ", med_min=" << med_min << ", med_max=" << med_max << ", med_mean=" << med_mean + << "\n\tfom_fo=" << fom_fo << ", fom_of=" << fom_of + << ", fom_min=" << fom_min << ", fom_max=" << fom_max << ", fom_mean=" << fom_mean + << "\n\tzhu_fo=" << zhu_fo << ", zhu_of=" << zhu_of + << ", zhu_min=" << zhu_min << ", zhu_max=" << zhu_max << ", zhu_mean=" << zhu_mean + << "\n\ty1=" << g_y1 << ", y2=" << g_y2 << ", y=" << g_y + << "\n\tg=" << g << ", gbeta=" << gbeta + << "\n"; + return; } //////////////////////////////////////////////////////////////////////// void DMAPInfo::set_options(const int _baddeley_p, const double _baddeley_max_dist, - const double _fom_alpha, const double _zhu_weight) { + const double _fom_alpha, const double _zhu_weight, + const double _beta_value, const int _n_full_points) { baddeley_p = _baddeley_p; baddeley_max_dist = _baddeley_max_dist; fom_alpha = _fom_alpha; zhu_weight = _zhu_weight; + beta_value = _beta_value; + n_full_points = _n_full_points; } //////////////////////////////////////////////////////////////////////// diff --git a/met/src/libcode/vx_statistics/met_stats.h b/met/src/libcode/vx_statistics/met_stats.h index 9f29299333..06b6af3fcd 100644 --- a/met/src/libcode/vx_statistics/met_stats.h +++ b/met/src/libcode/vx_statistics/met_stats.h @@ -609,6 +609,8 @@ class DMAPInfo { double baddeley_max_dist; // Maximum distance constant double fom_alpha; // FOM Alpha double zhu_weight; // Zhu Weight + double beta_value; // G-Beta Value + int n_full_points; // Number of FULL domain points public: @@ -622,7 +624,7 @@ class DMAPInfo { SingleThresh othresh; // Counts - int total, fy, oy; + int total, fy, oy, foy; // Distance metrics double baddeley, hausdorff; @@ -636,6 +638,9 @@ class DMAPInfo { // Zhu Metric double zhu_fo, zhu_of, zhu_min, zhu_max, zhu_mean; + // G and G-Beta + double g, gbeta; + // Compute statistics double fbias() const; // fbias = fy / oy @@ -645,12 +650,20 @@ class DMAPInfo { const NumArray &fthr_na, const NumArray &othr_na); void set_options(const int _baddeley_p, const double _baddeley_max_dist, - const double _fom_alpha, const double _zhu_weight); + const double _fom_alpha, const double _zhu_weight, + const double _beta_value, const int _n_full_points); + + // Get functions + double get_beta_value() const; void clear(); void reset_options(); }; +//////////////////////////////////////////////////////////////////////// + +inline double DMAPInfo::get_beta_value() const { return(beta_value); } + //////////////////////////////////////////////////////////////////////// // // Utility functions for parsing data from configuration files diff --git a/met/src/tools/core/grid_stat/grid_stat.cc b/met/src/tools/core/grid_stat/grid_stat.cc index f0daf3f6a9..242a3de5e3 100644 --- a/met/src/tools/core/grid_stat/grid_stat.cc +++ b/met/src/tools/core/grid_stat/grid_stat.cc @@ -1210,6 +1210,13 @@ void process_scores() { DataPlane fcst_dp_dmap, obs_dp_dmap; pd.extend(grid.nx()*grid.ny()); + // Mask out missing data between the fields for a fair comparison + DataPlane fcst_dp_mm = fcst_dp; + DataPlane obs_dp_mm = obs_dp; + mask_bad_data(fcst_dp_mm, obs_dp_mm); + mask_bad_data(obs_dp_mm, fcst_dp_mm); + int n_good_data = obs_dp_mm.n_good_data(); + // Loop over the categorical thresholds for(k=0; klookup(conf_key_beta_value)); + if(!beta_value_fx.is_set()) { + mlog << Error << "\nGridStatVxOpt::process_config() -> " + << "The \"" << conf_key_beta_value + << "\" function is not set!\n\n"; + exit(1); + } + // Conf: hss_ec_value hss_ec_value = odict.lookup_double(conf_key_hss_ec_value); diff --git a/met/src/tools/core/grid_stat/grid_stat_conf_info.h b/met/src/tools/core/grid_stat/grid_stat_conf_info.h index ff731985ac..73bc476124 100644 --- a/met/src/tools/core/grid_stat/grid_stat_conf_info.h +++ b/met/src/tools/core/grid_stat/grid_stat_conf_info.h @@ -186,7 +186,8 @@ class GridStatVxOpt { int baddeley_p; // Exponent for lp-norm double baddeley_max_dist; // Maximum distance constant double fom_alpha; // FOM Alpha - double zhu_weight; // Zhu Weight + double zhu_weight; // Zhu Weight + UserFunc_1Arg beta_value_fx; // G-Beta Value Function double hss_ec_value; // MCTS HSS expected correct value bool rank_corr_flag; // Flag for computing rank correlations diff --git a/test/config/GridStatConfig_APCP_regrid b/test/config/GridStatConfig_APCP_regrid index dfcfbf73a7..af00db9f28 100644 --- a/test/config/GridStatConfig_APCP_regrid +++ b/test/config/GridStatConfig_APCP_regrid @@ -150,6 +150,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_GRIB_lvl_typ_val b/test/config/GridStatConfig_GRIB_lvl_typ_val index 1b3a539f57..8ace03905d 100644 --- a/test/config/GridStatConfig_GRIB_lvl_typ_val +++ b/test/config/GridStatConfig_GRIB_lvl_typ_val @@ -247,6 +247,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_GRIB_set_attr b/test/config/GridStatConfig_GRIB_set_attr index dae59b6282..917a0caf66 100644 --- a/test/config/GridStatConfig_GRIB_set_attr +++ b/test/config/GridStatConfig_GRIB_set_attr @@ -179,6 +179,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_GTG_latlon b/test/config/GridStatConfig_GTG_latlon index 0f18b04d2d..36356d9b48 100644 --- a/test/config/GridStatConfig_GTG_latlon +++ b/test/config/GridStatConfig_GTG_latlon @@ -158,6 +158,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_GTG_lc b/test/config/GridStatConfig_GTG_lc index 531a3bb9cf..c32de7a1b7 100644 --- a/test/config/GridStatConfig_GTG_lc +++ b/test/config/GridStatConfig_GTG_lc @@ -158,6 +158,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_apply_mask b/test/config/GridStatConfig_apply_mask index 1c62a9a929..9142054e30 100644 --- a/test/config/GridStatConfig_apply_mask +++ b/test/config/GridStatConfig_apply_mask @@ -159,6 +159,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_climo_WMO b/test/config/GridStatConfig_climo_WMO index 39e64895ce..e23f74a2be 100644 --- a/test/config/GridStatConfig_climo_WMO +++ b/test/config/GridStatConfig_climo_WMO @@ -219,6 +219,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_climo_prob b/test/config/GridStatConfig_climo_prob index b5f4629bf1..a97291af88 100644 --- a/test/config/GridStatConfig_climo_prob +++ b/test/config/GridStatConfig_climo_prob @@ -229,6 +229,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_fourier b/test/config/GridStatConfig_fourier index 6b2ba521f3..ad8c121b23 100644 --- a/test/config/GridStatConfig_fourier +++ b/test/config/GridStatConfig_fourier @@ -185,6 +185,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_grid_weight b/test/config/GridStatConfig_grid_weight index af74b784c7..4cd850faf1 100644 --- a/test/config/GridStatConfig_grid_weight +++ b/test/config/GridStatConfig_grid_weight @@ -170,6 +170,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_interp_shape b/test/config/GridStatConfig_interp_shape index f6a69c5e35..66d1658886 100644 --- a/test/config/GridStatConfig_interp_shape +++ b/test/config/GridStatConfig_interp_shape @@ -152,6 +152,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_mpr_thresh b/test/config/GridStatConfig_mpr_thresh index 4e95022a48..268e24cbc6 100644 --- a/test/config/GridStatConfig_mpr_thresh +++ b/test/config/GridStatConfig_mpr_thresh @@ -217,6 +217,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_no_leap b/test/config/GridStatConfig_no_leap index 3b80dc0330..b33a52c222 100644 --- a/test/config/GridStatConfig_no_leap +++ b/test/config/GridStatConfig_no_leap @@ -159,6 +159,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_prob_as_scalar b/test/config/GridStatConfig_prob_as_scalar index f497641518..8a462ce48a 100644 --- a/test/config/GridStatConfig_prob_as_scalar +++ b/test/config/GridStatConfig_prob_as_scalar @@ -180,6 +180,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_python b/test/config/GridStatConfig_python index 9bb128ac92..3d9059219b 100644 --- a/test/config/GridStatConfig_python +++ b/test/config/GridStatConfig_python @@ -156,6 +156,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_python_mixed b/test/config/GridStatConfig_python_mixed index 38a5f9fa90..9b868a2745 100644 --- a/test/config/GridStatConfig_python_mixed +++ b/test/config/GridStatConfig_python_mixed @@ -164,6 +164,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_rtma b/test/config/GridStatConfig_rtma index b49db75a73..178a1269b1 100644 --- a/test/config/GridStatConfig_rtma +++ b/test/config/GridStatConfig_rtma @@ -160,6 +160,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_rtma_perc_thresh b/test/config/GridStatConfig_rtma_perc_thresh index 55b42b4456..3a739645ad 100644 --- a/test/config/GridStatConfig_rtma_perc_thresh +++ b/test/config/GridStatConfig_rtma_perc_thresh @@ -163,6 +163,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_st4 b/test/config/GridStatConfig_st4 index 00dbf1d8a0..5f210db851 100644 --- a/test/config/GridStatConfig_st4 +++ b/test/config/GridStatConfig_st4 @@ -164,6 +164,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/GridStatConfig_st4_censor b/test/config/GridStatConfig_st4_censor index d0ae97d7d9..1942cfe107 100644 --- a/test/config/GridStatConfig_st4_censor +++ b/test/config/GridStatConfig_st4_censor @@ -173,6 +173,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/ref_config/GridStatConfig_03h b/test/config/ref_config/GridStatConfig_03h index 70f885dd08..dc40220c7b 100644 --- a/test/config/ref_config/GridStatConfig_03h +++ b/test/config/ref_config/GridStatConfig_03h @@ -158,6 +158,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/ref_config/GridStatConfig_24h b/test/config/ref_config/GridStatConfig_24h index a66ffcf276..450b7117aa 100644 --- a/test/config/ref_config/GridStatConfig_24h +++ b/test/config/ref_config/GridStatConfig_24h @@ -158,6 +158,7 @@ distance_map = { baddeley_max_dist = NA; fom_alpha = 0.1; zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/hdr/met_10_1.hdr b/test/hdr/met_10_1.hdr index 245eac4203..ba80ba12b8 100644 --- a/test/hdr/met_10_1.hdr +++ b/test/hdr/met_10_1.hdr @@ -10,7 +10,7 @@ NBRCNT : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_L NBRCTC : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FY_OY FY_ON FN_OY FN_ON NBRCTS : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL BASER BASER_NCL BASER_NCU BASER_BCL BASER_BCU FMEAN FMEAN_NCL FMEAN_NCU FMEAN_BCL FMEAN_BCU ACC ACC_NCL ACC_NCU ACC_BCL ACC_BCU FBIAS FBIAS_BCL FBIAS_BCU PODY PODY_NCL PODY_NCU PODY_BCL PODY_BCU PODN PODN_NCL PODN_NCU PODN_BCL PODN_BCU POFD POFD_NCL POFD_NCU POFD_BCL POFD_BCU FAR FAR_NCL FAR_NCU FAR_BCL FAR_BCU CSI CSI_NCL CSI_NCU CSI_BCL CSI_BCU GSS GSS_BCL GSS_BCU HK HK_NCL HK_NCU HK_BCL HK_BCU HSS HSS_BCL HSS_BCU ODDS ODDS_NCL ODDS_NCU ODDS_BCL ODDS_BCU LODDS LODDS_NCL LODDS_NCU LODDS_BCL LODDS_BCU ORSS ORSS_NCL ORSS_NCU ORSS_BCL ORSS_BCU EDS EDS_NCL EDS_NCU EDS_BCL EDS_BCU SEDS SEDS_NCL SEDS_NCU SEDS_BCL SEDS_BCU EDI EDI_NCL EDI_NCU EDI_BCL EDI_BCU SEDI SEDI_NCL SEDI_NCU SEDI_BCL SEDI_BCU BAGSS BAGSS_BCL BAGSS_BCU GRAD : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FGBAR OGBAR MGBAR EGBAR S1 S1_OG FGOG_RATIO DX DY -DMAP : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FY OY FBIAS BADDELEY HAUSDORFF MED_FO MED_OF MED_MIN MED_MAX MED_MEAN FOM_FO FOM_OF FOM_MIN FOM_MAX FOM_MEAN ZHU_FO ZHU_OF ZHU_MIN ZHU_MAX ZHU_MEAN +DMAP : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FY OY FBIAS BADDELEY HAUSDORFF MED_FO MED_OF MED_MIN MED_MAX MED_MEAN FOM_FO FOM_OF FOM_MIN FOM_MAX FOM_MEAN ZHU_FO ZHU_OF ZHU_MIN ZHU_MAX ZHU_MEAN G GBETA BETA_VALUE ORANK : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL INDEX OBS_SID OBS_LAT OBS_LON OBS_LVL OBS_ELV OBS PIT RANK N_ENS_VLD N_ENS _VAR_ PCT : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL N_THRESH _VAR_ PJC : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL N_THRESH _VAR_ From 730eccdb2d1fe1fc3fe9b754b063b34c01db1047 Mon Sep 17 00:00:00 2001 From: Seth Linden Date: Mon, 23 Aug 2021 11:26:58 -0600 Subject: [PATCH 125/200] Feature 1764 point stat (#1885) * Per #1764 added write_orank_row() to do_hera_ens(). SL * Per issue #1764, added orank stat type for ensemble output. SL * Per issue #1764, added code to setup_txt_files() for ORANK output. SL * Added some comments for debuging. SL * Per #1764, add orank to the list of outputs created by point_stat. * Per #1764, add functions to compute the number of requested HiRA probabilities and ensemble members. Also update n_txt_row() to keep track of the number of ORANK rows to be written. Not totally sure if I'm counting these ORANK output lines correctly though. * Per #1764, update logic in setup_txt_files() to call get_max_n_hira_prob() and get_max_n_hira_ens() functions. * Per #1764, no real changes. Just fixing spacing. * Per issue #1764, cleaned up print (cout) debug statements. SL * Per issue #1764 added 'orank = NONE' to the config files for compatibility with changes to point_stat for calculating ORANK. SL * Per issue #1764 added 'orank = STAT' to config file to produce ORANK output lines in point_stat. SL * Per issue #1764 added content in all relevant sections for ORANK: observation rank statistic. SL * Added 'orank = NONE' to config file for compatibility with changes to point_stant for ORANK. SL * Added 'orank = NONE' to config file for compatibility with changes to point_stant for ORANK. SL * Apply suggestions from code review Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> * Per #1764, no real changes, just fixing indents. * Per #1764, no real changes, just fixing indents. * Per #1764, no real changes, just fixing indents. * Per #1764, putting the docs for VCNT back into its logical order with the other vector line types. The order that they're listed here does not need to match their order in the enumeration in the code. * Per #1764, fixing a vcnt typo I found in the grid-stat chapter... and making them consistent. * Per issue #1764: After the call to write_orank_row, added lines to reset the observation begin and end times. SL * Per #1764, no code changes, just fixing indents. Co-authored-by: Seth Linden Co-authored-by: John Halley Gotway Co-authored-by: John Halley Gotway Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> --- met/data/config/PointStatConfig_default | 1 + met/docs/Users_Guide/grid-stat.rst | 2 +- met/docs/Users_Guide/point-stat.rst | 21 ++++---- met/scripts/config/PointStatConfig | 1 + met/src/tools/core/point_stat/point_stat.cc | 50 ++++++++++++++----- met/src/tools/core/point_stat/point_stat.h | 12 ++--- .../core/point_stat/point_stat_conf_info.cc | 49 +++++++++++++++++- .../core/point_stat/point_stat_conf_info.h | 36 +++++++------ test/config/PointStatConfig_APCP | 1 + test/config/PointStatConfig_APCP_HIRA | 1 + test/config/PointStatConfig_GTG_latlon | 1 + test/config/PointStatConfig_GTG_lc | 1 + test/config/PointStatConfig_INTERP_OPTS | 1 + test/config/PointStatConfig_LAND_TOPO_MASK | 1 + test/config/PointStatConfig_MASK_SID | 1 + test/config/PointStatConfig_PHYS | 1 + test/config/PointStatConfig_PHYS_pint | 1 + test/config/PointStatConfig_WINDS | 1 + test/config/PointStatConfig_aeronet | 1 + test/config/PointStatConfig_airnow | 1 + test/config/PointStatConfig_climo | 1 + test/config/PointStatConfig_climo_WMO | 1 + test/config/PointStatConfig_climo_prob | 1 + test/config/PointStatConfig_dup | 1 + test/config/PointStatConfig_mpr_thresh | 1 + test/config/PointStatConfig_obs_summary | 1 + test/config/PointStatConfig_obs_summary_all | 1 + test/config/PointStatConfig_prob | 1 + test/config/PointStatConfig_python | 1 + test/config/PointStatConfig_qty | 1 + test/config/PointStatConfig_sid_inc_exc | 1 + 31 files changed, 150 insertions(+), 45 deletions(-) diff --git a/met/data/config/PointStatConfig_default b/met/data/config/PointStatConfig_default index 048ff2cb4a..4cdaefaf6e 100644 --- a/met/data/config/PointStatConfig_default +++ b/met/data/config/PointStatConfig_default @@ -280,6 +280,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; // Only for HiRA. + orank = NONE; // Only for HiRA. rps = NONE; // Only for HiRA. eclv = NONE; mpr = NONE; diff --git a/met/docs/Users_Guide/grid-stat.rst b/met/docs/Users_Guide/grid-stat.rst index 264903825f..ef1a465763 100644 --- a/met/docs/Users_Guide/grid-stat.rst +++ b/met/docs/Users_Guide/grid-stat.rst @@ -388,7 +388,7 @@ The **output_flag** array controls the type of output that the Grid-Stat tool ge 10. **VAL1L2** for Vector Anomaly L1L2 Partial Sums when climatological data is supplied -11. **VCNT** for Vector Contingency Table Statistics +11. **VCNT** for Vector Continuous Statistics 12. **PCT** for Contingency Table Counts for Probabilistic forecasts diff --git a/met/docs/Users_Guide/point-stat.rst b/met/docs/Users_Guide/point-stat.rst index 162f86926c..97b93b4b40 100644 --- a/met/docs/Users_Guide/point-stat.rst +++ b/met/docs/Users_Guide/point-stat.rst @@ -121,7 +121,7 @@ The forecast value at P is chosen as the grid point inside the interpolation are HiRA framework ~~~~~~~~~~~~~~ -The Point-Stat tool has been enhanced to include the High Resolution Assessment (HiRA) verification logic (:ref:`Mittermaier, 2014 `). HiRA is analogous to neighborhood verification but for point observations. The HiRA logic interprets the forecast values surrounding each point observation as an ensemble forecast. These ensemble values are processed in two ways. First, the ensemble continuous statistics (ECNT) and the ranked probability score (RPS) line types are computed directly from the ensemble values. Second, for each categorical threshold specified, a fractional coverage value is computed as the ratio of the nearby forecast values that meet the threshold criteria. Point-Stat evaluates those fractional coverage values as if they were a probability forecast. When applying HiRA, users should enable the matched pair (MPR), probabilistic (PCT, PSTD, PJC, or PRC), continuous ensemble statistics (ECNT), or ranked probability score (RPS) line types in the **output_flag** dictionary. The number of probabilistic HiRA output lines is determined by the number of categorical forecast thresholds and HiRA neighborhood widths chosen. +The Point-Stat tool has been enhanced to include the High Resolution Assessment (HiRA) verification logic (:ref:`Mittermaier, 2014 `). HiRA is analogous to neighborhood verification but for point observations. The HiRA logic interprets the forecast values surrounding each point observation as an ensemble forecast. These ensemble values are processed in three ways. First, the ensemble continuous statistics (ECNT), the observation rank statistics (ORANK) and the ranked probability score (RPS) line types are computed directly from the ensemble values. Second, for each categorical threshold specified, a fractional coverage value is computed as the ratio of the nearby forecast values that meet the threshold criteria. Point-Stat evaluates those fractional coverage values as if they were a probability forecast. When applying HiRA, users should enable the matched pair (MPR), probabilistic (PCT, PSTD, PJC, or PRC), continuous ensemble statistics (ECNT), observation rank statistics (ORANK) or ranked probability score (RPS) line types in the **output_flag** dictionary. The number of probabilistic HiRA output lines is determined by the number of categorical forecast thresholds and HiRA neighborhood widths chosen. The HiRA framework provides a unique method for evaluating models in the neighborhood of point observations, allowing for some spatial and temporal uncertainty in the forecast and/or the observations. Additionally, the HiRA framework can be used to compare deterministic forecasts to ensemble forecasts. In MET, the neighborhood is a circle or square centered on the grid point closest to the observation location. An event is defined, then the proportion of points with events in the neighborhood is calculated. This proportion is treated as an ensemble probability, though it is likely to be uncalibrated. @@ -425,6 +425,7 @@ ________________________ pjc = BOTH; prc = BOTH; ecnt = BOTH; // Only for HiRA + orank = BOTH; // Only for HiRA rps = BOTH; // Only for HiRA eclv = BOTH; mpr = BOTH; @@ -450,9 +451,9 @@ The **output_flag** array controls the type of output that the Point-Stat tool g 9. **VL1L2** for Vector L1L2 Partial Sums -10. **VCNT** for Vector Continuous Statistics (Note that bootstrap confidence intervals are not currently calculated for this line type.) +10. **VAL1L2** for Vector Anomaly L1L2 Partial Sums when climatological data is supplied -11. **VAL1L2** for Vector Anomaly L1L2 Partial Sums when climatological data is supplied +11. **VCNT** for Vector Continuous Statistics 12. **PCT** for Contingency Table counts for Probabilistic forecasts @@ -464,13 +465,15 @@ The **output_flag** array controls the type of output that the Point-Stat tool g 16. **ECNT** for Ensemble Continuous Statistics is only computed for the HiRA methodology -17. **RPS** for Ranked Probability Score is only computed for the HiRA methodology +17. **ORANK** for Ensemble Matched Pair Information when point observations are supplied for the HiRA methodology -18. **ECLV** for Economic Cost/Loss Relative Value +18. **RPS** for Ranked Probability Score is only computed for the HiRA methodology -19. **MPR** for Matched Pair data +19. **ECLV** for Economic Cost/Loss Relative Value -Note that the first two line types are easily derived from each other. Users are free to choose which measures are most desired. The output line types are described in more detail in :numref:`point_stat-output`. +20. **MPR** for Matched Pair data + +Note that the FHO and CTC line types are easily derived from each other. Users are free to choose which measures are most desired. The output line types are described in more detail in :numref:`point_stat-output`. Note that writing out matched pair data (MPR lines) for a large number of cases is generally not recommended. The MPR lines create very large output files and are only intended for use on a small set of cases. @@ -489,9 +492,9 @@ point_stat_PREFIX_HHMMSSL_YYYYMMDD_HHMMSSV.stat where PREFIX indicates the user- The output ASCII files are named similarly: -point_stat_PREFIX_HHMMSSL_YYYYMMDD_HHMMSSV_TYPE.txt where TYPE is one of mpr, fho, ctc, cts, cnt, mctc, mcts, pct, pstd, pjc, prc, ecnt, rps, eclv, sl1l2, sal1l2, vl1l2, vcnt or val1l2 to indicate the line type it contains. +point_stat_PREFIX_HHMMSSL_YYYYMMDD_HHMMSSV_TYPE.txt where TYPE is one of mpr, fho, ctc, cts, cnt, mctc, mcts, pct, pstd, pjc, prc, ecnt, orank, rps, eclv, sl1l2, sal1l2, vl1l2, vcnt or val1l2 to indicate the line type it contains. -The first set of header columns are common to all of the output files generated by the Point-Stat tool. Tables describing the contents of the header columns and the contents of the additional columns for each line type are listed in the following tables. The ECNT line type is described in :numref:`table_ES_header_info_es_out_ECNT`. The RPS line type is described in :numref:`table_ES_header_info_es_out_RPS`. +The first set of header columns are common to all of the output files generated by the Point-Stat tool. Tables describing the contents of the header columns and the contents of the additional columns for each line type are listed in the following tables. The ECNT line type is described in :numref:`table_ES_header_info_es_out_ECNT`. The ORANK line type is described in :numref:`table_ES_header_info_es_out_ORANK`. The RPS line type is described in :numref:`table_ES_header_info_es_out_RPS`. .. _table_PS_header_info_point-stat_out: diff --git a/met/scripts/config/PointStatConfig b/met/scripts/config/PointStatConfig index 6df8e67daf..513c956ab6 100644 --- a/met/scripts/config/PointStatConfig +++ b/met/scripts/config/PointStatConfig @@ -199,6 +199,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; // Only for HiRA + orank = NONE; // Only for HiRA rps = NONE; // Only for HiRA eclv = BOTH; mpr = BOTH; diff --git a/met/src/tools/core/point_stat/point_stat.cc b/met/src/tools/core/point_stat/point_stat.cc index 9f49049fdb..36c1a3baf6 100644 --- a/met/src/tools/core/point_stat/point_stat.cc +++ b/met/src/tools/core/point_stat/point_stat.cc @@ -95,6 +95,7 @@ // 045 03/28/21 Halley Gotway Add mpr_column and mpr_thresh // filtering options. // 046 05/28/21 Halley Gotway Add MCTS HSS_EC output. +// 047 08/23/21 Seth Linden Add ORANK line type for HiRA. // //////////////////////////////////////////////////////////////////////// @@ -327,7 +328,9 @@ void setup_first_pass(const DataPlane &dp, const Grid &data_grid) { //////////////////////////////////////////////////////////////////////// void setup_txt_files() { - int i, max_col, max_prob_col, max_mctc_col, n_prob, n_cat, n_eclv; + int i, j; + int max_col, max_prob_col, max_mctc_col, max_orank_col; + int n_prob, n_cat, n_eclv, n_ens; ConcatString base_name; // Create output file names for the stat file and optional text files @@ -340,23 +343,20 @@ void setup_txt_files() { ///////////////////////////////////////////////////////////////////// // Get the maximum number of data columns - n_prob = conf_info.get_max_n_fprob_thresh(); + n_prob = max(conf_info.get_max_n_fprob_thresh(), + conf_info.get_max_n_hira_prob()); n_cat = conf_info.get_max_n_cat_thresh() + 1; n_eclv = conf_info.get_max_n_eclv_points(); + n_ens = conf_info.get_max_n_hira_ens(); - // Check for HiRA output - for(i=0; i max_stat_col ? max_prob_col : max_stat_col ); - max_col = ( max_mctc_col > max_col ? max_mctc_col : max_col ); + max_col = (max_prob_col > max_stat_col ? max_prob_col : max_stat_col); + max_col = (max_mctc_col > max_col ? max_mctc_col : max_col); + max_col = (max_orank_col > max_col ? max_orank_col : max_col); // Add the header columns max_col += n_header_columns + 1; @@ -429,6 +429,10 @@ void setup_txt_files() { max_col = get_n_eclv_columns(n_eclv) + n_header_columns + 1; break; + case(i_orank): + max_col = get_n_orank_columns(n_ens) + n_header_columns + 1; + break; + default: max_col = n_txt_columns[i] + n_header_columns + 1; break; @@ -465,6 +469,10 @@ void setup_txt_files() { write_eclv_header_row(1, n_eclv, txt_at[i], 0, 0); break; + case(i_orank): + write_orank_header_row(1, n_ens, txt_at[i], 0, 0); + break; + default: write_header_row(txt_columns[i], n_txt_columns[i], 1, txt_at[i], 0, 0); @@ -1749,6 +1757,22 @@ void do_hira_ens(int i_vx, const PairDataPoint *pd_ptr) { txt_at[i_ecnt], i_txt_row[i_ecnt]); } // end if ECNT + // Write out the ORANK line + if(conf_info.vx_opt[i_vx].output_flag[i_orank] != STATOutputType_None) { + + // Compute ensemble statistics + hira_pd.compute_pair_vals(rng_ptr); + + write_orank_row(shc, &hira_pd, + conf_info.vx_opt[i_vx].output_flag[i_orank], + stat_at, i_stat_row, + txt_at[i_orank], i_txt_row[i_orank]); + + // Reset the observation valid time + shc.set_obs_valid_beg(conf_info.vx_opt[i_vx].vx_pd.beg_ut); + shc.set_obs_valid_end(conf_info.vx_opt[i_vx].vx_pd.end_ut); + } // end if ORANK + // Write out the RPS line if(conf_info.vx_opt[i_vx].output_flag[i_rps] != STATOutputType_None) { diff --git a/met/src/tools/core/point_stat/point_stat.h b/met/src/tools/core/point_stat/point_stat.h index dc232a52de..9b2b823d2a 100644 --- a/met/src/tools/core/point_stat/point_stat.h +++ b/met/src/tools/core/point_stat/point_stat.h @@ -70,8 +70,8 @@ static const char **txt_columns[n_txt] = { sl1l2_columns, sal1l2_columns, vl1l2_columns, val1l2_columns, pct_columns, pstd_columns, pjc_columns, prc_columns, ecnt_columns, - rps_columns, eclv_columns, mpr_columns, - vcnt_columns + orank_columns, rps_columns, eclv_columns, + mpr_columns, vcnt_columns }; // Length of header columns @@ -81,8 +81,8 @@ static const int n_txt_columns[n_txt] = { n_sl1l2_columns, n_sal1l2_columns, n_vl1l2_columns, n_val1l2_columns, n_pct_columns, n_pstd_columns, n_pjc_columns, n_prc_columns, n_ecnt_columns, - n_rps_columns, n_eclv_columns, n_mpr_columns, - n_vcnt_columns + n_orank_columns, n_rps_columns, n_eclv_columns, + n_mpr_columns, n_vcnt_columns }; // Text file abbreviations @@ -92,8 +92,8 @@ static const char *txt_file_abbr[n_txt] = { "sl1l2", "sal1l2", "vl1l2", "val1l2", "pct", "pstd", "pjc", "prc", "ecnt", - "rps", "eclv", "mpr", - "vcnt" + "orank", "rps", "eclv", + "mpr", "vcnt" }; //////////////////////////////////////////////////////////////////////// diff --git a/met/src/tools/core/point_stat/point_stat_conf_info.cc b/met/src/tools/core/point_stat/point_stat_conf_info.cc index e56352d4ad..dd0d13dee1 100644 --- a/met/src/tools/core/point_stat/point_stat_conf_info.cc +++ b/met/src/tools/core/point_stat/point_stat_conf_info.cc @@ -523,6 +523,26 @@ int PointStatConfInfo::get_max_n_eclv_points() const { //////////////////////////////////////////////////////////////////////// +int PointStatConfInfo::get_max_n_hira_ens() const { + int i, n; + + for(i=0,n=0; i ECLV lines = // Message Types * Masks * Interpolations * Thresholds * @@ -1282,3 +1316,16 @@ int PointStatVxOpt::get_n_oprob_thresh() const { } //////////////////////////////////////////////////////////////////////// + +int PointStatVxOpt::get_n_hira_ens() const { + int n = (hira_info.flag ? hira_info.width.max() : 0); + return(n*n); +} + +//////////////////////////////////////////////////////////////////////// + +int PointStatVxOpt::get_n_hira_prob() const { + return(hira_info.flag ? hira_info.cov_ta.n() : 0); +} + +//////////////////////////////////////////////////////////////////////// diff --git a/met/src/tools/core/point_stat/point_stat_conf_info.h b/met/src/tools/core/point_stat/point_stat_conf_info.h index f9d0d9fe0f..5bc964069d 100644 --- a/met/src/tools/core/point_stat/point_stat_conf_info.h +++ b/met/src/tools/core/point_stat/point_stat_conf_info.h @@ -46,12 +46,13 @@ static const int i_pjc = 12; static const int i_prc = 13; static const int i_ecnt = 14; -static const int i_rps = 15; -static const int i_eclv = 16; -static const int i_mpr = 17; -static const int i_vcnt = 18; +static const int i_orank = 15; +static const int i_rps = 16; +static const int i_eclv = 17; +static const int i_mpr = 18; +static const int i_vcnt = 19; -static const int n_txt = 19; +static const int n_txt = 20; // Text file type static const STATLineType txt_file_type[n_txt] = { @@ -74,10 +75,11 @@ static const STATLineType txt_file_type[n_txt] = { stat_prc, // 13 stat_ecnt, // 14 - stat_rps, // 14 - stat_eclv, // 15 - stat_mpr, // 16 - stat_vcnt, // 17 + stat_orank, // 15 + stat_rps, // 16 + stat_eclv, // 17 + stat_mpr, // 18 + stat_vcnt, // 19 }; @@ -178,19 +180,21 @@ class PointStatVxOpt { int get_n_oprob_thresh() const; int get_n_eclv_points() const; + int get_n_hira_ens() const; + int get_n_hira_prob() const; int get_n_cdf_bin() const; int get_n_ci_alpha() const; }; //////////////////////////////////////////////////////////////////////// -inline int PointStatVxOpt::get_n_msg_typ() const { return(msg_typ.n_elements()); } -inline int PointStatVxOpt::get_n_mask() const { return(mask_name.n_elements()); } -inline int PointStatVxOpt::get_n_interp() const { return(interp_info.n_interp); } +inline int PointStatVxOpt::get_n_msg_typ() const { return(msg_typ.n()); } +inline int PointStatVxOpt::get_n_mask() const { return(mask_name.n()); } +inline int PointStatVxOpt::get_n_interp() const { return(interp_info.n_interp); } -inline int PointStatVxOpt::get_n_eclv_points() const { return(eclv_points.n_elements()); } -inline int PointStatVxOpt::get_n_cdf_bin() const { return(cdf_info.n_bin); } -inline int PointStatVxOpt::get_n_ci_alpha() const { return(ci_alpha.n_elements()); } +inline int PointStatVxOpt::get_n_eclv_points() const { return(eclv_points.n()); } +inline int PointStatVxOpt::get_n_cdf_bin() const { return(cdf_info.n_bin); } +inline int PointStatVxOpt::get_n_ci_alpha() const { return(ci_alpha.n()); } //////////////////////////////////////////////////////////////////////// @@ -266,6 +270,8 @@ class PointStatConfInfo { int get_max_n_fprob_thresh() const; int get_max_n_oprob_thresh() const; int get_max_n_eclv_points() const; + int get_max_n_hira_ens() const; + int get_max_n_hira_prob() const; // Check for any verification of vectors bool get_vflag() const; diff --git a/test/config/PointStatConfig_APCP b/test/config/PointStatConfig_APCP index 003f9f50a0..ea8b55a5b4 100644 --- a/test/config/PointStatConfig_APCP +++ b/test/config/PointStatConfig_APCP @@ -120,6 +120,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = BOTH; mpr = NONE; diff --git a/test/config/PointStatConfig_APCP_HIRA b/test/config/PointStatConfig_APCP_HIRA index eefbcfdda0..412d2d8fe7 100644 --- a/test/config/PointStatConfig_APCP_HIRA +++ b/test/config/PointStatConfig_APCP_HIRA @@ -123,6 +123,7 @@ output_flag = { pjc = STAT; prc = STAT; ecnt = STAT; + orank = STAT; rps = STAT; eclv = STAT; mpr = STAT; diff --git a/test/config/PointStatConfig_GTG_latlon b/test/config/PointStatConfig_GTG_latlon index 7e6e2c53d2..1ac24d927e 100644 --- a/test/config/PointStatConfig_GTG_latlon +++ b/test/config/PointStatConfig_GTG_latlon @@ -142,6 +142,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = BOTH; mpr = BOTH; diff --git a/test/config/PointStatConfig_GTG_lc b/test/config/PointStatConfig_GTG_lc index 4b6df47f87..5efd47662c 100644 --- a/test/config/PointStatConfig_GTG_lc +++ b/test/config/PointStatConfig_GTG_lc @@ -150,6 +150,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = BOTH; mpr = BOTH; diff --git a/test/config/PointStatConfig_INTERP_OPTS b/test/config/PointStatConfig_INTERP_OPTS index 4923dab75b..c255c5b565 100644 --- a/test/config/PointStatConfig_INTERP_OPTS +++ b/test/config/PointStatConfig_INTERP_OPTS @@ -133,6 +133,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = NONE; mpr = STAT; diff --git a/test/config/PointStatConfig_LAND_TOPO_MASK b/test/config/PointStatConfig_LAND_TOPO_MASK index 74d7e28be1..4d1ab530fc 100644 --- a/test/config/PointStatConfig_LAND_TOPO_MASK +++ b/test/config/PointStatConfig_LAND_TOPO_MASK @@ -173,6 +173,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = NONE; mpr = BOTH; diff --git a/test/config/PointStatConfig_MASK_SID b/test/config/PointStatConfig_MASK_SID index 95c30a9d16..e4174e9e9a 100644 --- a/test/config/PointStatConfig_MASK_SID +++ b/test/config/PointStatConfig_MASK_SID @@ -128,6 +128,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = BOTH; mpr = BOTH; diff --git a/test/config/PointStatConfig_PHYS b/test/config/PointStatConfig_PHYS index 4a5640ddcb..7a767a54da 100644 --- a/test/config/PointStatConfig_PHYS +++ b/test/config/PointStatConfig_PHYS @@ -129,6 +129,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = BOTH; mpr = BOTH; diff --git a/test/config/PointStatConfig_PHYS_pint b/test/config/PointStatConfig_PHYS_pint index 9102584bff..4149345038 100644 --- a/test/config/PointStatConfig_PHYS_pint +++ b/test/config/PointStatConfig_PHYS_pint @@ -124,6 +124,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = BOTH; mpr = BOTH; diff --git a/test/config/PointStatConfig_WINDS b/test/config/PointStatConfig_WINDS index 4f17fff75a..2b3ff9988e 100644 --- a/test/config/PointStatConfig_WINDS +++ b/test/config/PointStatConfig_WINDS @@ -145,6 +145,7 @@ output_flag = { prc = NONE; ecnt = NONE; rps = NONE; + orank = NONE; eclv = NONE; mpr = NONE; } diff --git a/test/config/PointStatConfig_aeronet b/test/config/PointStatConfig_aeronet index b36dd7f39c..58579bdf68 100644 --- a/test/config/PointStatConfig_aeronet +++ b/test/config/PointStatConfig_aeronet @@ -193,6 +193,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = NONE; mpr = STAT; diff --git a/test/config/PointStatConfig_airnow b/test/config/PointStatConfig_airnow index cbf3c76c11..7420b10455 100644 --- a/test/config/PointStatConfig_airnow +++ b/test/config/PointStatConfig_airnow @@ -223,6 +223,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = NONE; mpr = STAT; diff --git a/test/config/PointStatConfig_climo b/test/config/PointStatConfig_climo index cd81aa6fbf..cb6eaea84b 100644 --- a/test/config/PointStatConfig_climo +++ b/test/config/PointStatConfig_climo @@ -262,6 +262,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = NONE; mpr = BOTH; diff --git a/test/config/PointStatConfig_climo_WMO b/test/config/PointStatConfig_climo_WMO index fa7499ab84..201e794890 100644 --- a/test/config/PointStatConfig_climo_WMO +++ b/test/config/PointStatConfig_climo_WMO @@ -210,6 +210,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = BOTH; + orank = NONE; rps = BOTH; eclv = NONE; mpr = BOTH; diff --git a/test/config/PointStatConfig_climo_prob b/test/config/PointStatConfig_climo_prob index 18ac41ccdf..2447701f95 100644 --- a/test/config/PointStatConfig_climo_prob +++ b/test/config/PointStatConfig_climo_prob @@ -212,6 +212,7 @@ output_flag = { pjc = BOTH; prc = BOTH; ecnt = NONE; + orank = NONE; rps = NONE; eclv = BOTH; mpr = BOTH; diff --git a/test/config/PointStatConfig_dup b/test/config/PointStatConfig_dup index 4dfe9f5c11..9298bb58ec 100644 --- a/test/config/PointStatConfig_dup +++ b/test/config/PointStatConfig_dup @@ -146,6 +146,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = STAT; mpr = BOTH; diff --git a/test/config/PointStatConfig_mpr_thresh b/test/config/PointStatConfig_mpr_thresh index daf7a11d2f..66bde341ef 100644 --- a/test/config/PointStatConfig_mpr_thresh +++ b/test/config/PointStatConfig_mpr_thresh @@ -204,6 +204,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = NONE; mpr = NONE; diff --git a/test/config/PointStatConfig_obs_summary b/test/config/PointStatConfig_obs_summary index 908f86e44c..b8129521ec 100644 --- a/test/config/PointStatConfig_obs_summary +++ b/test/config/PointStatConfig_obs_summary @@ -135,6 +135,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = STAT; mpr = BOTH; diff --git a/test/config/PointStatConfig_obs_summary_all b/test/config/PointStatConfig_obs_summary_all index 636ed3d001..080ba56dff 100644 --- a/test/config/PointStatConfig_obs_summary_all +++ b/test/config/PointStatConfig_obs_summary_all @@ -204,6 +204,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = STAT; mpr = BOTH; diff --git a/test/config/PointStatConfig_prob b/test/config/PointStatConfig_prob index b1fe365e2b..e2ed42b77f 100644 --- a/test/config/PointStatConfig_prob +++ b/test/config/PointStatConfig_prob @@ -131,6 +131,7 @@ output_flag = { pjc = BOTH; prc = BOTH; ecnt = NONE; + orank = NONE; rps = NONE; eclv = BOTH; mpr = NONE; diff --git a/test/config/PointStatConfig_python b/test/config/PointStatConfig_python index 0c66c8c4f0..752fb7a928 100644 --- a/test/config/PointStatConfig_python +++ b/test/config/PointStatConfig_python @@ -201,6 +201,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = NONE; mpr = STAT; diff --git a/test/config/PointStatConfig_qty b/test/config/PointStatConfig_qty index 98ad597e46..6f7db1b826 100644 --- a/test/config/PointStatConfig_qty +++ b/test/config/PointStatConfig_qty @@ -153,6 +153,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = BOTH; mpr = BOTH; diff --git a/test/config/PointStatConfig_sid_inc_exc b/test/config/PointStatConfig_sid_inc_exc index 62e6e9b43f..9dc3e7fdcf 100644 --- a/test/config/PointStatConfig_sid_inc_exc +++ b/test/config/PointStatConfig_sid_inc_exc @@ -136,6 +136,7 @@ output_flag = { pjc = NONE; prc = NONE; ecnt = NONE; + orank = NONE; rps = NONE; eclv = NONE; mpr = BOTH; From 9e35280a0005757b486e9e5f89fc59207aeb55f2 Mon Sep 17 00:00:00 2001 From: MET Tools Test Account Date: Mon, 23 Aug 2021 11:33:53 -0600 Subject: [PATCH 126/200] Adding Seth to the NB notification list. --- scripts/regression/test_nightly.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/regression/test_nightly.sh b/scripts/regression/test_nightly.sh index f63653d155..992981f702 100755 --- a/scripts/regression/test_nightly.sh +++ b/scripts/regression/test_nightly.sh @@ -21,7 +21,7 @@ #======================================================================= # Constants -EMAIL_LIST="johnhg@ucar.edu hsoh@ucar.edu jpresto@ucar.edu" +EMAIL_LIST="johnhg@ucar.edu hsoh@ucar.edu jpresto@ucar.edu linden@ucar.edu" KEEP_DAYS=5 # Usage statement From 678044f44c2cc28f38a24749973b3ab53429f8f9 Mon Sep 17 00:00:00 2001 From: johnhg Date: Mon, 23 Aug 2021 15:29:47 -0600 Subject: [PATCH 127/200] Bugfix 1886 develop grid_diag (#1888) * Per #1886, port over the bugfixes from main_v10.0 to develop. * Per #1886, make grid_diag error out if to_grid is set to FCST or OBS. --- .../vx_series_data/test_series_data.cc | 2 +- met/src/libcode/vx_series_data/series_pdf.cc | 14 ++++----- met/src/libcode/vx_series_data/series_pdf.h | 14 ++++----- met/src/tools/other/grid_diag/grid_diag.cc | 31 +++++++++++++------ met/src/tools/other/grid_diag/grid_diag.h | 4 +-- 5 files changed, 38 insertions(+), 27 deletions(-) diff --git a/met/internal_tests/libcode/vx_series_data/test_series_data.cc b/met/internal_tests/libcode/vx_series_data/test_series_data.cc index f2396821cd..69b0ec000a 100644 --- a/met/internal_tests/libcode/vx_series_data/test_series_data.cc +++ b/met/internal_tests/libcode/vx_series_data/test_series_data.cc @@ -46,7 +46,7 @@ int main(int argc, char *argv[]) { double delta = (max - min) / nbin; double width = 10; - vector pdf; + vector pdf; init_pdf(nbin, pdf); diff --git a/met/src/libcode/vx_series_data/series_pdf.cc b/met/src/libcode/vx_series_data/series_pdf.cc index 994dc16618..9e89cccb7f 100644 --- a/met/src/libcode/vx_series_data/series_pdf.cc +++ b/met/src/libcode/vx_series_data/series_pdf.cc @@ -22,7 +22,7 @@ void init_pdf( int n, - vector& pdf) { + vector& pdf) { for(int k = 0; k < n; k++) { pdf.push_back(0); @@ -35,7 +35,7 @@ void init_pdf( double min, double max, double delta, - vector& pdf) { + vector& pdf) { int n = (max - min) / delta; for(int k = 0; k < n; k++) { @@ -48,7 +48,7 @@ void init_pdf( void init_joint_pdf( int n_A, int n_B, - vector& pdf) { + vector& pdf) { for(int k = 0; k < n_A * n_B; k++) { pdf.push_back(0); @@ -60,7 +60,7 @@ void init_joint_pdf( void update_pdf( double min, double delta, - vector& pdf, + vector& pdf, const DataPlane& dp, const MaskPlane& mp) { @@ -86,7 +86,7 @@ void update_joint_pdf( double min_B, double delta_A, double delta_B, - vector& pdf, + vector& pdf, const DataPlane& dp_A, const DataPlane& dp_B, const MaskPlane& mp) { @@ -115,7 +115,7 @@ void update_joint_pdf( void print_pdf( double min, double delta, - const vector& pdf) { + const vector& pdf) { for(int k = 0; k < pdf.size(); k++) { double bin_min = min + k * delta; @@ -132,7 +132,7 @@ void write_nc_pdf( const VarInfo& info, double min, double delta, - const vector& pdf) { + const vector& pdf) { vector bin_min; vector bin_max; diff --git a/met/src/libcode/vx_series_data/series_pdf.h b/met/src/libcode/vx_series_data/series_pdf.h index 7a200357d5..de0100c820 100644 --- a/met/src/libcode/vx_series_data/series_pdf.h +++ b/met/src/libcode/vx_series_data/series_pdf.h @@ -30,7 +30,7 @@ using namespace netCDF; void init_pdf( int n, - vector& pdf); + vector& pdf); //////////////////////////////////////////////////////////////////////// @@ -38,21 +38,21 @@ void init_pdf( double min, double max, double delta, - vector& pdf); + vector& pdf); //////////////////////////////////////////////////////////////////////// void init_joint_pdf( int n_A, int n_B, - vector& pdf); + vector& pdf); //////////////////////////////////////////////////////////////////////// void update_pdf( double min, double delta, - vector& pdf, + vector& pdf, const DataPlane&, const MaskPlane&); @@ -65,7 +65,7 @@ void update_joint_pdf( double min_B, double delta_A, double delta_B, - vector& pdf, + vector& pdf, const DataPlane&, const DataPlane&, const MaskPlane&); @@ -75,7 +75,7 @@ void update_joint_pdf( void print_pdf( double min, double delta, - const vector& pdf); + const vector& pdf); //////////////////////////////////////////////////////////////////////// @@ -84,7 +84,7 @@ void write_nc_pdf( const VarInfo& info, double min, double delta, - const vector& pdf); + const vector& pdf); //////////////////////////////////////////////////////////////////////// diff --git a/met/src/tools/other/grid_diag/grid_diag.cc b/met/src/tools/other/grid_diag/grid_diag.cc index c72a81aba3..46929924b4 100644 --- a/met/src/tools/other/grid_diag/grid_diag.cc +++ b/met/src/tools/other/grid_diag/grid_diag.cc @@ -17,6 +17,7 @@ // 000 10/01/19 Fillmore New // 001 07/28/20 Halley Gotway Updates for #1391. // 002 03/04/21 Halley Gotway Bugfix #1694. +// 003 08/20/21 Halley Gotway Bugfix #1886 for integer overflow. // //////////////////////////////////////////////////////////////////////// @@ -217,6 +218,16 @@ void process_command_line(int argc, char **argv) { grid = parse_vx_grid(conf_info.data_info[0]->regrid(), &data_grid, &data_grid); + // The regrid.to_grid option cannot be set to FCST or OBS + if(conf_info.data_info[0]->regrid().field == FieldType_Fcst || + conf_info.data_info[0]->regrid().field == FieldType_Obs) { + mlog << Error << "\nprocess_command_line() -> " + << "the \"regrid.to_grid\" configuration option cannot be set to " + << "FCST or OBS!\nSpecify a named grid, grid specification string, " + << "or the path to a gridded data file instead.\n\n"; + exit(1); + } + // Process masking regions conf_info.process_masks(grid); } @@ -426,7 +437,7 @@ void setup_histograms(void) { << "Initializing " << data_info->magic_str_attr() << " histogram with " << n_bins << " bins from " << min << " to " << max << ".\n"; - histograms[i_var_str] = vector(); + histograms[i_var_str] = vector(); init_pdf(n_bins, histograms[i_var_str]); } // for i_var } @@ -456,7 +467,7 @@ void setup_joint_histograms(void) { << "Initializing " << data_info->magic_str_attr() << "_" << joint_info->magic_str_attr() << " joint histogram with " << n_bins << " x " << n_joint_bins << " bins.\n"; - joint_histograms[ij_var_str] = vector(); + joint_histograms[ij_var_str] = vector(); init_joint_pdf(n_bins, n_joint_bins, joint_histograms[ij_var_str]); @@ -473,9 +484,9 @@ void setup_nc_file(void) { nc_out = open_ncfile(out_file.c_str(), true); if(IS_INVALID_NC_P(nc_out)) { - mlog << Error << "\nsetup_nc_file() -> " - << "trouble opening output NetCDF file " - << out_file << "\n\n"; + mlog << Error << "\nsetup_nc_file() -> " + << "trouble opening output NetCDF file " + << out_file << "\n\n"; exit(1); } @@ -568,7 +579,7 @@ void setup_nc_file(void) { ConcatString hist_name("hist_"); hist_name.add(var_name); NcDim var_dim = data_var_dims[i_var]; - NcVar hist_var = add_var(nc_out, hist_name, ncInt, var_dim, + NcVar hist_var = add_var(nc_out, hist_name, ncInt64, var_dim, deflate_level); hist_vars.push_back(hist_var); @@ -602,7 +613,7 @@ void setup_nc_file(void) { dims.push_back(var_dim); dims.push_back(joint_dim); - NcVar hist_var = add_var(nc_out, hist_name, ncInt, dims, + NcVar hist_var = add_var(nc_out, hist_name, ncInt64, dims, deflate_level); joint_hist_vars.push_back(hist_var); @@ -620,7 +631,7 @@ void write_nc_var_int(const char *var_name, const char *long_name, int n) { // Add the variable - NcVar var = add_var(nc_out, var_name, ncInt); + NcVar var = add_var(nc_out, var_name, ncInt64); add_att(&var, "long_name", long_name); if(!put_nc_data(&var, &n)) { @@ -650,7 +661,7 @@ void write_histograms(void) { VarInfo *data_info = conf_info.data_info[i_var]; NcVar hist_var = hist_vars[i_var]; - int *hist = histograms[i_var_str].data(); + long long *hist = histograms[i_var_str].data(); hist_var.putVar(hist); } @@ -676,7 +687,7 @@ void write_joint_histograms(void) { << "VAR" << i_var << "_" << "VAR" << j_var; - int *hist = joint_histograms[ij_var_str].data(); + long long *hist = joint_histograms[ij_var_str].data(); offsets.clear(); counts.clear(); diff --git a/met/src/tools/other/grid_diag/grid_diag.h b/met/src/tools/other/grid_diag/grid_diag.h index 419d6b8f50..e595ed7e96 100644 --- a/met/src/tools/other/grid_diag/grid_diag.h +++ b/met/src/tools/other/grid_diag/grid_diag.h @@ -110,8 +110,8 @@ vector var_mins; vector var_maxs; // Variable histogram map -map > histograms; -map > joint_histograms; +map > histograms; +map > joint_histograms; map > bin_mins; map > bin_maxs; map > bin_mids; From 4b2e18c771ee3eaedca67a0f0556db80e2d0f133 Mon Sep 17 00:00:00 2001 From: Julie Prestopnik Date: Thu, 26 Aug 2021 13:54:13 -0600 Subject: [PATCH 128/200] Added additional default labels --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/ISSUE_TEMPLATE/enhancement_request.md | 2 +- .github/ISSUE_TEMPLATE/new_feature_request.md | 2 +- .github/ISSUE_TEMPLATE/sub-issue.md | 2 +- .github/ISSUE_TEMPLATE/task.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 2bbe76335b..6c4450e814 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -2,7 +2,7 @@ name: Bug report about: Fix something that's not working title: '' -labels: 'type: bug' +labels: 'alert: NEED ACCOUNT KEY, alert: NEED MORE DEFINITION, alert: NEED PROJECT ASSIGNMENT, type: bug' assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/enhancement_request.md b/.github/ISSUE_TEMPLATE/enhancement_request.md index 0c7f6c1331..3133dec892 100644 --- a/.github/ISSUE_TEMPLATE/enhancement_request.md +++ b/.github/ISSUE_TEMPLATE/enhancement_request.md @@ -2,7 +2,7 @@ name: Enhancement request about: Improve something that it's currently doing title: '' -labels: 'type: enhancement' +labels: 'alert: NEED ACCOUNT KEY, alert: NEED MORE DEFINITION, alert: NEED PROJECT ASSIGNMENT, type: enhancement' assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/new_feature_request.md b/.github/ISSUE_TEMPLATE/new_feature_request.md index c76da8ce50..b37efe8aef 100644 --- a/.github/ISSUE_TEMPLATE/new_feature_request.md +++ b/.github/ISSUE_TEMPLATE/new_feature_request.md @@ -2,7 +2,7 @@ name: New feature request about: Make it do something new title: '' -labels: 'type: new feature' +labels: 'alert: NEED ACCOUNT KEY, alert: NEED MORE DEFINITION, alert: NEED PROJECT ASSIGNMENT, type: new feature' assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/sub-issue.md b/.github/ISSUE_TEMPLATE/sub-issue.md index 3552fa1934..77bf2b2844 100644 --- a/.github/ISSUE_TEMPLATE/sub-issue.md +++ b/.github/ISSUE_TEMPLATE/sub-issue.md @@ -2,7 +2,7 @@ name: Sub-Issue about: Break an issue down into smaller parts title: '' -labels: 'type: sub-issue' +labels: 'alert: NEED ACCOUNT KEY, alert: NEED MORE DEFINITION, alert: NEED PROJECT ASSIGNMENT, type: sub-issue' assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/task.md b/.github/ISSUE_TEMPLATE/task.md index 93e889017d..ce3a6fb09a 100644 --- a/.github/ISSUE_TEMPLATE/task.md +++ b/.github/ISSUE_TEMPLATE/task.md @@ -2,7 +2,7 @@ name: Task about: Describe something that needs to be done title: '' -labels: 'type: task' +labels: 'alert: NEED ACCOUNT KEY, alert: NEED MORE DEFINITION, alert: NEED PROJECT ASSIGNMENT, type: task' assignees: '' --- From 4b32d53271fb8327801b5f6d3ea00b70b8d17bb7 Mon Sep 17 00:00:00 2001 From: johnhg Date: Mon, 30 Aug 2021 09:37:43 -0600 Subject: [PATCH 129/200] Feature 1870 realtime (#1893) * Per #1870. add TCPairs config entries for valid_inc, valid_exc, and write_valid. * Per #1870, removing 2 files I accidentally added. * Per #1870, add code to parse the new tc_pairs config options. * Per #1870, unrelated... just fixing spacing. * Per #1870, update TrackPairInfo/Array classes and tc_pairs application code to use the write_valid option to subset the tracks by requested valid time before writing them. * Per #1870, update the User's Guide with the new config options. Document valid_inc/valid_exc in the common TC config section and add write_valid to the TC-Pairs chapter. * Per #1870, move the subset_write_valid() functionality to the library code and support it for both track and probability arrays. * Per #1870, update unit_tc_pairs.xml with 2 new calls to exercise the new write_valid functionality for both tracks and probabilities. * Per #1870, correct some typos in the docs... PROBRI and probri should be PROBRIRW and probrirw, resp. * Per #1870, switching match_points from TRUE back to FALSE after I acciedentally committed that change. * Per #1870, just fixing indent. Co-authored-by: John Halley Gotway --- met/data/config/TCPairsConfig_default | 9 +- met/docs/Users_Guide/config_options_tc.rst | 37 +++-- met/docs/Users_Guide/tc-pairs.rst | 20 ++- met/docs/Users_Guide/tc-stat.rst | 19 +-- met/src/basic/vx_config/config_constants.h | 1 + .../libcode/vx_tc_util/prob_rirw_pair_info.cc | 17 +++ .../libcode/vx_tc_util/prob_rirw_pair_info.h | 1 + met/src/libcode/vx_tc_util/tc_columns.cc | 4 +- met/src/libcode/vx_tc_util/track_pair_info.cc | 46 +++++- met/src/libcode/vx_tc_util/track_pair_info.h | 1 + met/src/tools/tc_utils/tc_pairs/tc_pairs.cc | 137 ++++++++++-------- .../tc_utils/tc_pairs/tc_pairs_conf_info.cc | 18 +++ .../tc_utils/tc_pairs/tc_pairs_conf_info.h | 3 + test/config/TCPairsConfig_ALAL2010 | 9 +- test/config/TCPairsConfig_BASIN_MAP | 9 +- test/config/TCPairsConfig_INTERP12 | 9 +- test/config/TCPairsConfig_PROBRIRW | 9 +- test/xml/unit_tc_pairs.xml | 49 ++++++- 18 files changed, 297 insertions(+), 101 deletions(-) diff --git a/met/data/config/TCPairsConfig_default b/met/data/config/TCPairsConfig_default index 8c62d1dce3..aa4afb51b6 100644 --- a/met/data/config/TCPairsConfig_default +++ b/met/data/config/TCPairsConfig_default @@ -50,10 +50,17 @@ init_inc = []; init_exc = []; // -// Valid model time window +// Valid model time windows to include or exclude // valid_beg = ""; valid_end = ""; +valid_inc = []; +valid_exc = []; + +// +// Valid times for which output should be written +// +write_valid = []; // // Model initialization hours diff --git a/met/docs/Users_Guide/config_options_tc.rst b/met/docs/Users_Guide/config_options_tc.rst index f3fcc75450..b9542a878d 100644 --- a/met/docs/Users_Guide/config_options_tc.rst +++ b/met/docs/Users_Guide/config_options_tc.rst @@ -92,6 +92,8 @@ or exclude (exc). Tracks whose initial time meets the specified criteria will be used. An empty string indicates that all times should be used. +In TC-Stat, the **-init_beg**, **-init_end**, **init_inc** and **-int_exc** job command options can be used to further refine these selections. + For example: | init_beg = "20100101"; @@ -107,26 +109,34 @@ For example: init_inc = []; init_exc = []; +.. _valid_beg end inc exc_1: -.. _valid_beg, valid_end_1: - -:ref:`valid_beg, valid_end ` - -Specify a model valid time window in YYYYMMDD[_HH[MMSS]] format. -Tracks for which all valid times fall within the time window will be used. -An empty string indicates that all times should be used. + ref:`valid_beg, valid_end, valid_inc, valid_exc ` + +Specify a model valid time window YYYYMMDD[_HH[MMSS]] format or provide a +list of specific valid times to include (inc) or exclude (exc). If a time +window is specified, only tracks for which all points are contained within +the window will be used. If valid times to include or exclude are specified, +tracks will be subset down to the points which meet that criteria. Empty +begin/end time strings and empty include/exclude lists indicate that all +valid times should be used. +In TC-Stat, the **-valid_beg**, **-valid_end**, **valid_inc** and **-valid_exc** job command options can be used to further refine these selections. For example: - + | valid_beg = "20100101"; -| valid_end = "20101231"; -| +| valid_end = "20101231_12"; +| valid_inc = [ "20101231_06" ]; +| valid_exc = [ "20101231_00" ]; +| .. code-block:: none - + valid_beg = ""; valid_end = ""; + valid_inc = []; + valid_exc = []; .. _init_hour_1: @@ -422,7 +432,6 @@ by basin or sub-basin. Note that if your model data and best track do not use the same basin identifier conventions, using an empty list for this parameter will result in missed matches. - .. code-block:: none basin_map = [ @@ -481,9 +490,9 @@ For example: valid_inc = []; valid_exc = []; -.. _ini valid_hour lead req: +.. _init valid_hour lead req: -:ref:`ini_hour, valid_hour, lead, lead_req ` +:ref:`init_hour, valid_hour, lead, lead_req ` Stratify by the initialization and valid hours and lead time. Specify a comma-separated list of initialization hours, diff --git a/met/docs/Users_Guide/tc-pairs.rst b/met/docs/Users_Guide/tc-pairs.rst index f2ce129846..b32cbc15b1 100644 --- a/met/docs/Users_Guide/tc-pairs.rst +++ b/met/docs/Users_Guide/tc-pairs.rst @@ -99,6 +99,8 @@ ____________________ init_exc = []; valid_beg = ""; valid_end = ""; + valid_inc = []; + valid_exc = []; init_hour = []; init_mask = []; lead_req = []; @@ -118,6 +120,14 @@ The **model** variable contains a list of comma-separated models to be used. Eac ____________________ +.. code-block:: none + + write_valid = [ "20101231_06" ]; + +The **write_valid** entry specifies a comma-separated list of valid time strings in YYYYMMDD[_HH[MMSS]] format for which output should be written. An empty list indicates that data for all valid times should be written. This option may be useful when verifying track forecasts in realtime. If evaluating performance for a single valid time, this option can limit the output to that time and skip output for earlier track points. + +____________________ + .. code-block:: none check_dup = FALSE; @@ -315,7 +325,7 @@ TC-Pairs produces output in TCST format. The default output file name can be ove - Valid time masking grid applied * - 13 - LINE_TYPE - - Output line type (TCMPR or PROBRI) + - Output line type (TCMPR or PROBRIRW) .. _TCMPR Line Type: @@ -462,9 +472,9 @@ TC-Pairs produces output in TCST format. The default output file name can be ove - A/BDEPTH - system depth, D-deep, M-medium, S-shallow, X-unknown -.. _PROBRI Line Type: +.. _PROBRIRW Line Type: -.. list-table:: Format information for PROBRIRW (Probability of Rapid Intensification) output line type. +.. list-table:: Format information for PROBRIRW (Probability of Rapid Intensification/Weakening) output line type. :widths: auto :header-rows: 2 @@ -475,8 +485,8 @@ TC-Pairs produces output in TCST format. The default output file name can be ove - Header Column Name - Description * - 13 - - PROBRI - - Probability of Rapid Intensification line type + - PROBRIRW + - Probability of Rapid Intensification/Weakening line type * - 14 - ALAT - Latitude position of edeck model diff --git a/met/docs/Users_Guide/tc-stat.rst b/met/docs/Users_Guide/tc-stat.rst index ee774eee0d..7052e80958 100644 --- a/met/docs/Users_Guide/tc-stat.rst +++ b/met/docs/Users_Guide/tc-stat.rst @@ -139,6 +139,8 @@ _________________________ init_exc = []; valid_beg = ""; valid_end = ""; + valid_inc = []; + valid_exc = []; init_hour = []; lead_req = []; init_mask = []; @@ -161,15 +163,6 @@ The **amodel** and **bmodel** fields stratify by the amodel and bmodel columns b _________________________ -.. code-block:: none - - valid_inc = []; - valid_exc = []; - -The **valid_inc** and **valid_exc** fields stratify by valid times, based on a comma-separated list of specific valid times to include (inc) or exclude (exc). Time strings are defined by YYYYMMDD[_HH[MMSS]]. Using the **-valid_inc** and **-valid_exc** options within the job command lines may further refine these selections. - -_________________________ - .. code-block:: none valid_hour = []; @@ -372,7 +365,7 @@ _________________________ -job summary -line_type TCMPR -column TK_ERR -dump_row ./tc_summary_job.tcst -job rirw -line_type TCMPR -rirw_time 24 -rirw_exact false -rirw_thresh ge20 -job probrirw -line_type PROBRIRW -column_thresh RI_WINDOW ==24 \ - -probri_thresh 30 -probri_prob_thresh ==0.25 + -probrirw_thresh 30 -probrirw_prob_thresh ==0.25 .. _tc_stat-output: @@ -466,12 +459,12 @@ The PROBRIRW job produces probabilistic contingency table counts and statistics • The **-prob_exact bool** option is a boolean defining whether the exact or maximum BEST track intensity change over the time window should be used. If true, the values in the **BDELTA** column are used. If false, the values in the **BDELTA_MAX** column are used. The default is true. -• The **-probri_bdelta_thresh** threshold option defines the BEST track intensity change event threshold. This should typically be set consistent with the probability threshold (**-prob_thresh**) chosen above. The default is greater than or equal to 30 kts. +• The **-probrirw_bdelta_thresh** threshold option defines the BEST track intensity change event threshold. This should typically be set consistent with the probability threshold (**-prob_thresh**) chosen above. The default is greater than or equal to 30 kts. -• The **-probri_prob_thresh threshold_list** option defines the probability thresholds used to create the output Nx2 contingency table. The default is probability bins of width 0.1. These probabilities may be specified as a list (>0.00,>0.25,>0.50,>0.75,>1.00) or using shorthand notation (==0.25) for bins of equal width. +• The **-probrirw_prob_thresh threshold_list** option defines the probability thresholds used to create the output Nx2 contingency table. The default is probability bins of width 0.1. These probabilities may be specified as a list (>0.00,>0.25,>0.50,>0.75,>1.00) or using shorthand notation (==0.25) for bins of equal width. • The **-out_line_type** option defines the output data that should be written. This job can write PCT, PSTD, PJC, and PRC output line types. The default is PCT and PSTD. Please see :numref:`table_PS_format_info_PCT` through :numref:`table_PS_format_info_PRC` for more details. Users may also specify the **-out_alpha** option to define the alpha value for the confidence intervals in the PSTD output line type. Multiple values in the **RI_WINDOW** column cannot be combined in a single PROBRIRW job since the BEST track intensity threshold should change for each. Using the **-by RI_WINDOW** option or **-column_thresh RI_WINDOW ==24** option provide convenient ways avoiding this problem. -Users should note that for the PROBRIRW line type, **PROBRI_PROB** is a derived column name. The -probri_thresh option defines the probabilities of interest (e.g. **-probri_thresh 30**) and the **PROBRI_PROB** column name refers to those probability values, regardless of their column number. For example, the job command options **-probri_thresh 30 -column_thresh PROBRI_PROB >0** select 30 kt probabilities and match probability values greater than 0. +Users should note that for the PROBRIRW line type, **PROBRI_PROB** is a derived column name. The -probrirw_thresh option defines the probabilities of interest (e.g. **-probrirw_thresh 30**) and the **PROBRI_PROB** column name refers to those probability values, regardless of their column number. For example, the job command options **-probrirw_thresh 30 -column_thresh PROBRI_PROB >0** select 30 kt probabilities and match probability values greater than 0. diff --git a/met/src/basic/vx_config/config_constants.h b/met/src/basic/vx_config/config_constants.h index 34fe74c978..81bd59589e 100644 --- a/met/src/basic/vx_config/config_constants.h +++ b/met/src/basic/vx_config/config_constants.h @@ -1012,6 +1012,7 @@ static const char conf_key_valid_end[] = "valid_end"; static const char conf_key_valid_inc[] = "valid_inc"; static const char conf_key_valid_exc[] = "valid_exc"; static const char conf_key_valid_hour[] = "valid_hour"; +static const char conf_key_write_valid[] = "write_valid"; static const char conf_key_lead[] = "lead"; static const char conf_key_lead_req[] = "lead_req"; static const char conf_key_init_mask[] = "init_mask"; diff --git a/met/src/libcode/vx_tc_util/prob_rirw_pair_info.cc b/met/src/libcode/vx_tc_util/prob_rirw_pair_info.cc index 61b69cc125..ce38bdfe97 100644 --- a/met/src/libcode/vx_tc_util/prob_rirw_pair_info.cc +++ b/met/src/libcode/vx_tc_util/prob_rirw_pair_info.cc @@ -453,3 +453,20 @@ bool ProbRIRWPairInfoArray::add(const ProbRIRWInfo &p, const TrackInfo &t) { //////////////////////////////////////////////////////////////////////// +void ProbRIRWPairInfoArray::subset_write_valid(const TimeArray &ta) { + + // Check for no work to do + if(ta.n() == 0) return; + + ProbRIRWPairInfoArray new_pairs; + for(int i=0; i i) { - hdr.set_desc((string)p.line(i)->get_item("DESC", false)); + hdr.set_desc((string)p.line(i)->get_item("DESC", false)); } // Write the header columns @@ -191,7 +191,7 @@ void write_prob_rirw_row(TcHdrColumns &hdr, const ProbRIRWPairInfo &p, // Pass the description from the input line to the output if(p.line().n_items() > 0) { - hdr.set_desc((string)p.line().get_item("DESC", false)); + hdr.set_desc((string)p.line().get_item("DESC", false)); } // Write one line for all the probabilities diff --git a/met/src/libcode/vx_tc_util/track_pair_info.cc b/met/src/libcode/vx_tc_util/track_pair_info.cc index b82d0a5f0d..5a03a9c0fc 100644 --- a/met/src/libcode/vx_tc_util/track_pair_info.cc +++ b/met/src/libcode/vx_tc_util/track_pair_info.cc @@ -309,6 +309,14 @@ void TrackPairInfo::initialize(const TCStatLine &l) { void TrackPairInfo::set_keep(int i, int val) { + // Check range + if(i < 0 || i >= NPoints) { + mlog << Error + << "\nTrackPairInfo::set_keep(int, int) -> " + << "range check error for index value " << i << "\n\n"; + exit(1); + } + Keep.set(i, val); return; @@ -780,13 +788,23 @@ TrackPairInfo TrackPairInfo::keep_subset() const { TrackPairInfo tpi; // Loop over the points - for(i=0; i " @@ -215,25 +215,25 @@ void process_command_line(int argc, char **argv) { } // List the input ADECK track files - for(i=0; i 0) { + if(adeck_source.n() > 0) { process_adecks(bdeck_tracks); } // Process EDECK files - if(edeck_source.n_elements() > 0) { + if(edeck_source.n() > 0) { process_edecks(bdeck_tracks); } @@ -291,7 +291,7 @@ void process_bdecks(TrackInfoArray &bdeck_tracks) { files, files_model_suffix); mlog << Debug(2) - << "Processing " << files.n_elements() << " BDECK file(s).\n"; + << "Processing " << files.n() << " BDECK file(s).\n"; process_track_files(files, files_model_suffix, bdeck_tracks, false, (conf_info.AnlyTrack == TrackType_BDeck || conf_info.AnlyTrack == TrackType_Both)); @@ -314,7 +314,7 @@ void process_adecks(const TrackInfoArray &bdeck_tracks) { files, files_model_suffix); mlog << Debug(2) - << "Processing " << files.n_elements() << " ADECK file(s).\n"; + << "Processing " << files.n() << " ADECK file(s).\n"; process_track_files(files, files_model_suffix, adeck_tracks, true, (conf_info.AnlyTrack == TrackType_ADeck || conf_info.AnlyTrack == TrackType_Both)); @@ -340,7 +340,7 @@ void process_adecks(const TrackInfoArray &bdeck_tracks) { // Derive lag forecasts from the ADECK tracks mlog << Debug(2) - << "Deriving " << conf_info.LagTime.n_elements() + << "Deriving " << conf_info.LagTime.n() << " ADECK lag model(s).\n"; i = derive_lag(adeck_tracks); mlog << Debug(2) @@ -348,8 +348,8 @@ void process_adecks(const TrackInfoArray &bdeck_tracks) { // Derive CLIPER/SHIFOR forecasts from the ADECK/BDECK tracks mlog << Debug(2) - << "Deriving " << conf_info.OperBaseline.n_elements() + - conf_info.BestBaseline.n_elements() + << "Deriving " << conf_info.OperBaseline.n() + + conf_info.BestBaseline.n() << " CLIPER/SHIFOR baseline model(s).\n"; i = derive_baseline(adeck_tracks, bdeck_tracks); mlog << Debug(2) @@ -403,6 +403,14 @@ void process_adecks(const TrackInfoArray &bdeck_tracks) { << pairs.serialize_r() << "\n"; } + // Subset pairs based on requested valid output times + if(conf_info.WriteValid.n() > 0) { + mlog << Debug(3) << "Subsetting output for " + << conf_info.WriteValid.n() + << " requested valid time(s).\n"; + pairs.subset_write_valid(conf_info.WriteValid); + } + // Write out the track pairs write_tracks(pairs); @@ -423,7 +431,7 @@ void process_edecks(const TrackInfoArray &bdeck_tracks) { files, files_model_suffix); mlog << Debug(2) - << "Processing " << files.n_elements() + << "Processing " << files.n() << " EDECK file(s).\n"; process_prob_files(files, files_model_suffix, edeck_probs); @@ -483,6 +491,14 @@ void process_edecks(const TrackInfoArray &bdeck_tracks) { << prob_rirw_pairs.serialize_r() << "\n"; } + // Subset pairs based on requested valid output times + if(conf_info.WriteValid.n() > 0) { + mlog << Debug(3) << "Subsetting output for " + << conf_info.WriteValid.n() + << " requested valid time(s).\n"; + prob_rirw_pairs.subset_write_valid(conf_info.WriteValid); + } + // Write out the ProbRIRW pairs if(prob_rirw_pairs.n_pairs() > 0) write_prob_rirw(prob_rirw_pairs); @@ -498,7 +514,7 @@ void get_atcf_files(const StringArray &source, StringArray cur_source, cur_files; int i, j; - if(source.n_elements() != model_suffix.n_elements()) { + if(source.n() != model_suffix.n()) { mlog << Error << "\nget_atcf_files() -> " << "the source and suffix arrays must be equal length!\n\n"; @@ -510,12 +526,12 @@ void get_atcf_files(const StringArray &source, files_model_suffix.clear(); // Build list of files and corresponding model suffix list - for(i=0; iwarning_time(), m, d, y, h, mm, s); // Check model - if(conf_info.Model.n_elements() > 0 && + if(conf_info.Model.n() > 0 && !conf_info.Model.has(line->technique())) keep = false; // Check storm id - else if(conf_info.StormId.n_elements() > 0 && + else if(conf_info.StormId.n() > 0 && !has_storm_id(conf_info.StormId, line->basin(), line->cyclone_number(), line->warning_time())) keep = false; // Check basin - else if(conf_info.Basin.n_elements() > 0 && + else if(conf_info.Basin.n() > 0 && !conf_info.Basin.has(line->basin())) keep = false; // Check cyclone - else if(conf_info.Cyclone.n_elements() > 0 && + else if(conf_info.Cyclone.n() > 0 && !conf_info.Cyclone.has(line->cyclone_number())) keep = false; @@ -752,17 +768,24 @@ bool is_keeper(const ATCFLineBase * line) { conf_info.InitBeg > line->warning_time()) || (conf_info.InitEnd > 0 && conf_info.InitEnd < line->warning_time()) || - (conf_info.InitInc.n_elements() > 0 && + (conf_info.InitInc.n() > 0 && !conf_info.InitInc.has(line->warning_time())) || - (conf_info.InitExc.n_elements() > 0 && + (conf_info.InitExc.n() > 0 && conf_info.InitExc.has(line->warning_time()))) keep = false; // Initialization hour - else if(conf_info.InitHour.n_elements() > 0 && + else if(conf_info.InitHour.n() > 0 && !conf_info.InitHour.has(hms_to_sec(h, mm, s))) keep = false; + // Valid time include/exclude + else if((conf_info.ValidInc.n() > 0 && + !conf_info.ValidInc.has(line->valid())) || + (conf_info.ValidExc.n() > 0 && + conf_info.ValidExc.has(line->valid()))) + keep = false; + // Return the keep status return(keep); } @@ -781,11 +804,11 @@ void filter_tracks(TrackInfoArray &tracks) { // Loop through the tracks and determine which should be retained // The is_keeper() function has already filtered by model, storm id, - // basin, cyclone, initialization time, and initialization hour. + // basin, cyclone, and timing information. for(i=0; i 0 && + if(conf_info.StormName.n() > 0 && !conf_info.StormName.has(t[i].storm_name())) { mlog << Debug(4) << "Discarding track " << i+1 << " for storm name mismatch: " @@ -812,10 +835,10 @@ void filter_tracks(TrackInfoArray &tracks) { // These are used in determining whether to keep or discard a track; keep a track // if all the required lead times are present. If no required lead times are // specified in the config file, then ignore checking and proceed as usual. - if(conf_info.LeadReq.n_elements() > 0) { + if(conf_info.LeadReq.n() > 0) { // Loop over the required lead times - for(j=0, status=true; jstorm_name()); - // Write the current TrackPairInfo object + // Write the current ProbRIRWPairInfo object write_prob_rirw_row(tchc, p[i], out_at, i_row); } @@ -2159,11 +2182,11 @@ void set_atcf_source(const StringArray & a, ConcatString cs, suffix; // Check for optional suffix sub-argument - for(i=0; i " << "the model suffix must be specified as " @@ -2177,7 +2200,7 @@ void set_atcf_source(const StringArray & a, } // Parse the remaining sources - for(i=0; i - LEAD_REQ + VALID_INC + WRITE_VALID + LEAD_REQ &MET_BIN;/tc_pairs \ @@ -70,6 +72,9 @@ &MET_BIN;/tc_pairs + + WRITE_VALID + \ -edeck &DATA_DIR;/edeck/*2015*.dat \ -bdeck &DATA_DIR;/bdeck/*2015*.dat \ @@ -100,7 +105,9 @@ - LEAD_REQ "96","108" + VALID_INC + WRITE_VALID + LEAD_REQ "96","108" &MET_BIN;/tc_pairs \ @@ -116,4 +123,42 @@ + + + VALID_INC "20100814_12", "20100815_00" + WRITE_VALID "20100815_00" + LEAD_REQ + + &MET_BIN;/tc_pairs + \ + -adeck &DATA_DIR;/adeck/*2010.dat \ + -bdeck &DATA_DIR;/bdeck/*2010.dat \ + -config &CONFIG_DIR;/TCPairsConfig_ALAL2010 \ + -out &OUTPUT_DIR;/tc_pairs/alal2010_WRITE_VALID \ + -log &OUTPUT_DIR;/tc_pairs/tc_pairs_WRITE_VALID.log \ + -v 2 + + + &OUTPUT_DIR;/tc_pairs/alal2010_WRITE_VALID.tcst + + + + + &MET_BIN;/tc_pairs + + WRITE_VALID "20150512" + + \ + -edeck &DATA_DIR;/edeck/*2015*.dat \ + -bdeck &DATA_DIR;/bdeck/*2015*.dat \ + -config &CONFIG_DIR;/TCPairsConfig_PROBRIRW \ + -out &OUTPUT_DIR;/tc_pairs/alal2015_WRITE_VALID \ + -log &OUTPUT_DIR;/tc_pairs/tc_pairs_WRITE_VALID_PROBRIRW.log \ + -v 3 + + + &OUTPUT_DIR;/tc_pairs/alal2015_WRITE_VALID_PROBRIRW.tcst + + + From aeb6c2777bd1cde1ee67f12a2d439a6220aadc25 Mon Sep 17 00:00:00 2001 From: johnhg Date: Mon, 30 Aug 2021 17:30:41 -0600 Subject: [PATCH 130/200] Feature 1788 ssidx (#1892) * Per #1788, add initial definition of the SSIDX line type. * Per #1788, add a STAT-Analysis config file for computing the CBS Score. This is currently just a copy of the GO Index. * Per #1788, add hooks for computing -job cbs_score. * Per #1788, since we're adding a new SSIDX line type, the columns for that line type replace the job_ss_columns and job_go_columns arrays. * Per #1788, rename cbs_score to cbs_index per UK Met Office instruction on 7/22/21. This convention is also consistent with the existing go_index and ss_index jobs. * Per #1788 rename STATAnalysisConfig_CBS_Score to STATAnalysisConfig_CBS_Index * Per #1788, update Makefile to handle name change. * Per #1788, add support for SSIDX stat line type. * Per #1788, define 4 output SSIDX columns. * Per #1788, define an SSIndexInfo struct for stashing/writing SS Index values. * Per #1788, write the SSIDX columns. However we don't need to function to write the whole row since it's only written by Stat-Analysis. * Per #1788, create an AggrSSIndexInfo struct to keep track of unique stat header column input values. * Per #1788, update the stat-analysis job code to make use of the new structs. * Per #1788 fix typo. * Per #1788, remove GO Index defintion from the code comments. That detail belongs elsewhere. * Per #1788, since coding up the GO Index several CNT and CTC columns have been added. Adding them here to let them be included as part of the Skill Score index computations. * Per #1788, update check_hdr_str() to print the name of the problematic header columns. * Per #1788, add a set(one) member function to multiple array classes. This calls clear or erase on the array prior to adding a single element. Add this for StringArray, NumArray, and ThreshArray, and CRCArray. * Per #1788, update the compute_ss_index() function in stat_analysis to make the code more concise by calling the newly adding singular set functions for arrays. * Per #1788, add FCST_MODEL and REF_MODEL output columns to the SSIDX line type. * Per #1788, add a new N_INIT column to the SSIDX line type to report the number of initialization times represented by this skill score. Also define the SSIDXData struct to store the skill score index job output. * Per #1788, update STATAnalysisJob to explicitly set the job type directly rather than parsing a string. * Per #1788, major change here adding skill_score_index_job.h/.cc to handle the computation of the skill score indices. * Per #1788, update stat_analysis source code to make use of the new classes in skill_score_index_job.h/.cc. * Per #1788, write a log message listing the model initialization times over which the skill score index is computed. * Per #1788, tweak log message. * Per #1788, compute n_term as the max lenght of the required arrays. * Per #1788, drop in the ACTUAL definition of the GO index provide by the DTC AF project team. Also simplify the existing arrays down to lenght one if the value remains constant. * Per #1788, correct CBS Index config file. Some parameters had 40 elements while others only had 32. * Per #1788, do not write SSIDX output if there are no valid terms found. * Per #1788, format the values in the skill score index log messages, replacing -9999 with NA. * Per #1788, update the get_stat() member functions. For 0 pairs, return bad data for all statistics other than TOTAL. * Per #1788, working on readability of the warning and error messages. * Per #1788, define the ss_index_name directly in the STATAnalysis config file to make it really easy to modify. * Per #1788, store the ss_index_name configuration option in the StatJob class. Also support a command line -ss_index_name option to override the config file value. * Per #1788, change from name to ss_index_name variable to be a bit more descriptive in the variable names. * Per #1788, since ss_index_name is in the StatJob class we no longer need to pass it around as an argument. * Per #1788, simply the skill score index job handling logic a bit. We only need to update the default job once, not twice.: * Revert "Per #1788, since ss_index_name is in the StatJob class we no longer need to pass it around as an argument." This reverts commit cde0be0950949af7a7d69121cfe0d82b9dd4d2cf. * Revert "Revert "Per #1788, since ss_index_name is in the StatJob class we no longer need to pass it around as an argument."" This reverts commit bbfd838debf9eeffc35f96b77f04a081ef2cd189. * Per #1788, I'd pruned too much code from stat_analysis.cc which caused the processing of config file jobs to fail. Fixing that here. * Per #1788, switch Z0 to L0 to match the sample data for computing CBS Index. * Per #1788, make it so that cbs_index and go_index work from config file. * Per #1788, update the documentation for the skill score index changes. * Per #1788, just move some variable definitions further down since they're only used sometimes. * Per #1788, make job output description into a numbered section. * Per #1788, little tweak. * Per #1788, update the STATAnalysisConfig files to add ss_index_name and hss_ec_value, as needed. * Per #1788, add new unit tests to exercise recent ss_index changes and update the Stat-Analysis documentation. * Update met/docs/Users_Guide/stat-analysis.rst Co-authored-by: jprestop * Update met/docs/Users_Guide/stat-analysis.rst Sorry for the typos! Thanks for catching them. Co-authored-by: jprestop * Update met/docs/Users_Guide/stat-analysis.rst Co-authored-by: jprestop * Per #1788, fix typo in error message. * Per #1788, fix a bug for ss_index... changing 'add' to 'set'. Also set the line_type seperately for each term, if requested. * Per #1788, tweak the ss_index logic slightly to make it more efficient. For each input STATLine, instead of checking all the index terms, stop searching after the first match. This assumes that each input line should be used for only one of the terms... and I think that's a pretty reasonable assumption. * Per #1788, minor tweaks to the STAT-Analysis docs. * Per #1788, add ss_index_vld_thresh option to existing STAT-Analysis config files. * Per #1788, add StatAnalysisJob ss_index_vld_thresh entry and parse it from the STAT-Analysis config file. * Per #1788, update stat_analysis code to check ss_index_vld_thresh setting when computing the skill score index. Also update the Stat-Analysis chapter of the User's Guide. * Per #1788, tweak one test to exercise a non-default ss_index_vld_thresh value. Co-authored-by: jprestop --- met/data/config/Makefile.am | 1 + met/data/config/STATAnalysisConfig_CBS_Index | 138 ++++ met/data/config/STATAnalysisConfig_GO_Index | 84 +- met/data/config/STATAnalysisConfig_default | 8 + .../table_files/met_header_columns_V10.1.txt | 1 + met/docs/Users_Guide/point-stat.rst | 2 +- met/docs/Users_Guide/stat-analysis.rst | 176 ++++- met/docs/Users_Guide/wavelet-stat.rst | 2 +- met/scripts/config/STATAnalysisConfig | 1 + met/src/basic/vx_cal/time_array.cc | 20 + met/src/basic/vx_cal/time_array.h | 6 + met/src/basic/vx_config/config_constants.h | 77 +- met/src/basic/vx_config/config_util.cc | 6 +- met/src/basic/vx_log/string_array.cc | 19 +- met/src/basic/vx_log/string_array.h | 2 + met/src/basic/vx_util/ascii_table.cc | 20 +- met/src/basic/vx_util/ascii_table.h | 2 +- met/src/basic/vx_util/crc_array.h | 20 + met/src/basic/vx_util/num_array.cc | 38 +- met/src/basic/vx_util/num_array.h | 2 + met/src/basic/vx_util/stat_column_defs.h | 25 +- met/src/basic/vx_util/thresh_array.cc | 10 + met/src/basic/vx_util/thresh_array.h | 3 +- met/src/libcode/vx_analysis_util/stat_job.cc | 39 +- met/src/libcode/vx_analysis_util/stat_job.h | 29 +- met/src/libcode/vx_shapedata/engine.cc | 28 +- met/src/libcode/vx_stat_out/stat_columns.cc | 32 + met/src/libcode/vx_stat_out/stat_columns.h | 2 + .../libcode/vx_stat_out/stat_hdr_columns.cc | 24 +- met/src/libcode/vx_statistics/met_stats.cc | 12 + met/src/libcode/vx_statistics/met_stats.h | 25 + met/src/tools/core/stat_analysis/Makefile.am | 6 +- .../core/stat_analysis/aggr_stat_line.cc | 197 ++++- .../tools/core/stat_analysis/aggr_stat_line.h | 11 + .../stat_analysis/skill_score_index_job.cc | 359 +++++++++ .../stat_analysis/skill_score_index_job.h | 111 +++ .../tools/core/stat_analysis/stat_analysis.cc | 95 +-- .../tools/core/stat_analysis/stat_analysis.h | 5 +- .../core/stat_analysis/stat_analysis_job.cc | 726 +++--------------- .../core/stat_analysis/stat_analysis_job.h | 12 +- .../other/mode_time_domain/mtd_config_info.cc | 16 +- test/config/STATAnalysisConfig_APCP_HIRA | 9 + test/config/STATAnalysisConfig_SFC_SS_Index | 112 +++ test/config/STATAnalysisConfig_climo | 9 + test/config/STATAnalysisConfig_filter_times | 9 + test/config/STATAnalysisConfig_grid_stat | 9 + test/config/STATAnalysisConfig_point_stat | 9 + test/config/STATAnalysisConfig_ramps | 9 + test/hdr/met_10_1.hdr | 1 + test/xml/unit_ref_config.xml | 37 + 50 files changed, 1751 insertions(+), 845 deletions(-) create mode 100644 met/data/config/STATAnalysisConfig_CBS_Index create mode 100644 met/src/tools/core/stat_analysis/skill_score_index_job.cc create mode 100644 met/src/tools/core/stat_analysis/skill_score_index_job.h create mode 100644 test/config/STATAnalysisConfig_SFC_SS_Index diff --git a/met/data/config/Makefile.am b/met/data/config/Makefile.am index fe9b468a48..c73bb4cadc 100644 --- a/met/data/config/Makefile.am +++ b/met/data/config/Makefile.am @@ -35,6 +35,7 @@ config_DATA = \ SeriesAnalysisConfig_default \ STATAnalysisConfig_default \ STATAnalysisConfig_GO_Index \ + STATAnalysisConfig_CBS_Index \ TCPairsConfig_default \ TCRMWConfig_default \ RMWAnalysisConfig_default \ diff --git a/met/data/config/STATAnalysisConfig_CBS_Index b/met/data/config/STATAnalysisConfig_CBS_Index new file mode 100644 index 0000000000..989b1de4ea --- /dev/null +++ b/met/data/config/STATAnalysisConfig_CBS_Index @@ -0,0 +1,138 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// STAT-Analysis configuration file used to compute the CBS Index. +// +// WARNING: This file should not be modified. +// +//////////////////////////////////////////////////////////////////////////////// + +// +// Filtering input STAT lines by the contents of each column +// +model = []; + +fcst_lead = [ "24", "48", "72", "96", "120", + "24", "48", "72", "96", "120", + "24", "48", "72", "96", "120", + "24", "48", "72", "96", "120", + "24", "48", "72", "96", "120", + "24", "48", "72", "96", "120", + "24", "48", "72", "96", "120", + "24", "48", "72", "96", "120" + ]; +obs_lead = []; + +fcst_valid_beg = ""; +fcst_valid_end = ""; +fcst_valid_inc = []; +fcst_valid_exc = []; +fcst_valid_hour = []; + +obs_valid_beg = ""; +obs_valid_end = ""; +obs_valid_inc = []; +obs_valid_exc = []; +obs_valid_hour = []; + +fcst_init_beg = ""; +fcst_init_end = ""; +fcst_init_inc = []; +fcst_init_exc = []; +fcst_init_hour = []; + +obs_init_beg = ""; +obs_init_end = ""; +obs_init_inc = []; +obs_init_exc = []; +obs_init_hour = []; + +fcst_var = [ "PRMSL", "PRMSL", "PRMSL", "PRMSL", "PRMSL", + "HGT", "HGT", "HGT", "HGT", "HGT", + "WIND", "WIND", "WIND", "WIND", "WIND", + "WIND", "WIND", "WIND", "WIND", "WIND", + "WIND", "WIND", "WIND", "WIND", "WIND", + "PRMSL", "PRMSL", "PRMSL", "PRMSL", "PRMSL", + "HGT", "HGT", "HGT", "HGT", "HGT", + "WIND", "WIND", "WIND", "WIND", "WIND" + ]; +obs_var = []; + +fcst_lev = [ "L0", "L0", "L0", "L0", "L0", + "P500", "P500", "P500", "P500", "P500", + "P250", "P250", "P250", "P250", "P250", + "P850", "P850", "P850", "P850", "P850", + "P250", "P250", "P250", "P250", "P250", + "L0", "L0", "L0", "L0", "L0", + "P500", "P500", "P500", "P500", "P500", + "P250", "P250", "P250", "P250", "P250" + ]; +obs_lev = []; + +obtype = []; + +vx_mask = [ "NH", "NH", "NH", "NH", "NH", + "NH", "NH", "NH", "NH", "NH", + "NH", "NH", "NH", "NH", "NH", + "TROP", "TROP", "TROP", "TROP", "TROP", + "TROP", "TROP", "TROP", "TROP", "TROP", + "SH", "SH", "SH", "SH", "SH", + "SH", "SH", "SH", "SH", "SH", + "SH", "SH", "SH", "SH", "SH" + ]; + +interp_mthd = []; + +interp_pnts = []; + +fcst_thresh = []; +obs_thresh = []; +cov_thresh = []; + +alpha = []; + +line_type = [ "SL1L2" ]; + +column = [ "RMSE" ]; + +weight = [ 6.4, 6.4, 6.4, 6.4, 6.4, + 2.4, 2.4, 2.4, 2.4, 2.4, + 2.4, 2.4, 2.4, 2.4, 2.4, + 2.0, 2.0, 2.0, 2.0, 2.0, + 1.2, 1.2, 1.2, 1.2, 1.2, + 3.2, 3.2, 3.2, 3.2, 3.2, + 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2, 1.2, 1.2 + ]; + +//////////////////////////////////////////////////////////////////////////////// + +// +// Confidence interval settings +// +out_alpha = 0.05; + +boot = { + interval = PCTILE; + rep_prop = 1.0; + n_rep = 0; + rng = "mt19937"; + seed = ""; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Skill score index options +// +ss_index_name = "CBS_INDEX"; +ss_index_vld_thresh = 1.0; + +//////////////////////////////////////////////////////////////////////////////// + +hss_ec_value = NA; +rank_corr_flag = FALSE; +vif_flag = FALSE; +tmp_dir = "/tmp"; +version = "V10.1.0"; + +//////////////////////////////////////////////////////////////////////////////// diff --git a/met/data/config/STATAnalysisConfig_GO_Index b/met/data/config/STATAnalysisConfig_GO_Index index 2b5ce181f5..a82daa1710 100644 --- a/met/data/config/STATAnalysisConfig_GO_Index +++ b/met/data/config/STATAnalysisConfig_GO_Index @@ -11,18 +11,18 @@ // model = []; -fcst_lead = [ "12", "24", "36", "48", - "12", "24", "36", "48", - "12", "24", "36", "48", - "12", "24", "36", "48", - "12", "24", "36", "48", - "12", "24", "36", "48", - "12", "24", "36", "48", - "12", "24", "36", "48", - "12", "24", "36", "48", - "12", "24", "36", "48", - "12", "24", "36", "48", - "12", "24", "36", "48" +fcst_lead = [ "12", "24", "36", "48", + "12", "24", "36", "48", + "12", "24", "36", "48", + "12", "24", "36", "48", + "12", "24", "36", "48", + "12", "24", "36", "48", + "12", "24", "36", "48", + "12", "24", "36", "48", + "12", "24", "36", "48", + "12", "24", "36", "48", + "12", "24", "36", "48", + "12", "24", "36", "48" ]; obs_lead = []; @@ -94,46 +94,22 @@ cov_thresh = []; alpha = []; -line_type = [ "SL1L2", "SL1L2", "SL1L2", "SL1L2", - "SL1L2", "SL1L2", "SL1L2", "SL1L2", - "SL1L2", "SL1L2", "SL1L2", "SL1L2", - "SL1L2", "SL1L2", "SL1L2", "SL1L2", - "SL1L2", "SL1L2", "SL1L2", "SL1L2", - "SL1L2", "SL1L2", "SL1L2", "SL1L2", - "SL1L2", "SL1L2", "SL1L2", "SL1L2", - "SL1L2", "SL1L2", "SL1L2", "SL1L2", - "SL1L2", "SL1L2", "SL1L2", "SL1L2", - "SL1L2", "SL1L2", "SL1L2", "SL1L2", - "SL1L2", "SL1L2", "SL1L2", "SL1L2", - "SL1L2", "SL1L2", "SL1L2", "SL1L2" - ]; +line_type = [ "SL1L2" ]; -column = [ "RMSE", "RMSE", "RMSE", "RMSE", - "RMSE", "RMSE", "RMSE", "RMSE", - "RMSE", "RMSE", "RMSE", "RMSE", - "RMSE", "RMSE", "RMSE", "RMSE", - "RMSE", "RMSE", "RMSE", "RMSE", - "RMSE", "RMSE", "RMSE", "RMSE", - "RMSE", "RMSE", "RMSE", "RMSE", - "RMSE", "RMSE", "RMSE", "RMSE", - "RMSE", "RMSE", "RMSE", "RMSE", - "RMSE", "RMSE", "RMSE", "RMSE", - "RMSE", "RMSE", "RMSE", "RMSE", - "RMSE", "RMSE", "RMSE", "RMSE" - ]; +column = [ "RMSE" ]; -weight = [ 4.0, 3.0, 2.0, 1.0, - 4.0, 3.0, 2.0, 1.0, - 4.0, 3.0, 2.0, 1.0, - 8.0, 6.0, 4.0, 2.0, - 8.0, 6.0, 4.0, 2.0, - 8.0, 6.0, 4.0, 2.0, - 8.0, 6.0, 4.0, 2.0, - 8.0, 6.0, 4.0, 2.0, - 4.0, 3.0, 2.0, 1.0, - 8.0, 6.0, 4.0, 2.0, - 4.0, 3.0, 2.0, 1.0, - 8.0, 6.0, 4.0, 2.0 +weight = [ 4.0, 3.0, 2.0, 1.0, + 4.0, 3.0, 2.0, 1.0, + 4.0, 3.0, 2.0, 1.0, + 8.0, 6.0, 4.0, 2.0, + 8.0, 6.0, 4.0, 2.0, + 8.0, 6.0, 4.0, 2.0, + 8.0, 6.0, 4.0, 2.0, + 8.0, 6.0, 4.0, 2.0, + 4.0, 3.0, 2.0, 1.0, + 8.0, 6.0, 4.0, 2.0, + 4.0, 3.0, 2.0, 1.0, + 8.0, 6.0, 4.0, 2.0 ]; //////////////////////////////////////////////////////////////////////////////// @@ -153,6 +129,14 @@ boot = { //////////////////////////////////////////////////////////////////////////////// +// +// Skill score index options +// +ss_index_name = "GO_INDEX"; +ss_index_vld_thresh = 1.0; + +//////////////////////////////////////////////////////////////////////////////// + hss_ec_value = NA; rank_corr_flag = FALSE; vif_flag = FALSE; diff --git a/met/data/config/STATAnalysisConfig_default b/met/data/config/STATAnalysisConfig_default index 8ce7bde069..193faf7d3b 100644 --- a/met/data/config/STATAnalysisConfig_default +++ b/met/data/config/STATAnalysisConfig_default @@ -108,6 +108,14 @@ wmo_fisher_stats = [ "CNT:PR_CORR", "CNT:SP_CORR", //////////////////////////////////////////////////////////////////////////////// +// +// Skill score index options +// +ss_index_name = "SS_INDEX"; +ss_index_vld_thresh = 1.0; + +//////////////////////////////////////////////////////////////////////////////// + hss_ec_value = NA; rank_corr_flag = FALSE; vif_flag = FALSE; diff --git a/met/data/table_files/met_header_columns_V10.1.txt b/met/data/table_files/met_header_columns_V10.1.txt index 87b5eba258..c0218275ec 100644 --- a/met/data/table_files/met_header_columns_V10.1.txt +++ b/met/data/table_files/met_header_columns_V10.1.txt @@ -29,6 +29,7 @@ V10.1 : STAT : VAL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID V10.1 : STAT : VL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL UFBAR VFBAR UOBAR VOBAR UVFOBAR UVFFBAR UVOOBAR F_SPEED_BAR O_SPEED_BAR V10.1 : STAT : VCNT : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FBAR FBAR_BCL FBAR_BCU OBAR OBAR_BCL OBAR_BCU FS_RMS FS_RMS_BCL FS_RMS_BCU OS_RMS OS_RMS_BCL OS_RMS_BCU MSVE MSVE_BCL MSVE_BCU RMSVE RMSVE_BCL RMSVE_BCU FSTDEV FSTDEV_BCL FSTDEV_BCU OSTDEV OSTDEV_BCL OSTDEV_BCU FDIR FDIR_BCL FDIR_BCU ODIR ODIR_BCL ODIR_BCU FBAR_SPEED FBAR_SPEED_BCL FBAR_SPEED_BCU OBAR_SPEED OBAR_SPEED_BCL OBAR_SPEED_BCU VDIFF_SPEED VDIFF_SPEED_BCL VDIFF_SPEED_BCU VDIFF_DIR VDIFF_DIR_BCL VDIFF_DIR_BCU SPEED_ERR SPEED_ERR_BCL SPEED_ERR_BCU SPEED_ABSERR SPEED_ABSERR_BCL SPEED_ABSERR_BCU DIR_ERR DIR_ERR_BCL DIR_ERR_BCU DIR_ABSERR DIR_ABSERR_BCL DIR_ABSERR_BCU V10.1 : STAT : GENMPR : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL INDEX STORM_ID AGEN_INIT AGEN_FHR AGEN_LAT AGEN_LON AGEN_DLAND BGEN_LAT BGEN_LON BGEN_DLAND GEN_DIST GEN_TDIFF INIT_TDIFF DEV_CAT OPS_CAT +V10.1 : STAT : SSIDX : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE FCST_MODEL REF_MODEL N_INIT N_TERM N_VLD SS_INDEX V10.1 : MODE : OBJ : VERSION MODEL N_VALID GRID_RES DESC FCST_LEAD FCST_VALID FCST_ACCUM OBS_LEAD OBS_VALID OBS_ACCUM FCST_RAD FCST_THR OBS_RAD OBS_THR FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE OBJECT_ID OBJECT_CAT CENTROID_X CENTROID_Y CENTROID_LAT CENTROID_LON AXIS_ANG LENGTH WIDTH AREA AREA_THRESH CURVATURE CURVATURE_X CURVATURE_Y COMPLEXITY INTENSITY_10 INTENSITY_25 INTENSITY_50 INTENSITY_75 INTENSITY_90 INTENSITY_USER INTENSITY_SUM CENTROID_DIST BOUNDARY_DIST CONVEX_HULL_DIST ANGLE_DIFF ASPECT_DIFF AREA_RATIO INTERSECTION_AREA UNION_AREA SYMMETRIC_DIFF INTERSECTION_OVER_AREA CURVATURE_RATIO COMPLEXITY_RATIO PERCENTILE_INTENSITY_RATIO INTEREST V10.1 : MODE : CTS : VERSION MODEL N_VALID GRID_RES DESC FCST_LEAD FCST_VALID FCST_ACCUM OBS_LEAD OBS_VALID OBS_ACCUM FCST_RAD FCST_THR OBS_RAD OBS_THR FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE FIELD TOTAL FY_OY FY_ON FN_OY FN_ON BASER FMEAN ACC FBIAS PODY PODN POFD FAR CSI GSS HK HSS ODDS diff --git a/met/docs/Users_Guide/point-stat.rst b/met/docs/Users_Guide/point-stat.rst index 97b93b4b40..c37c5b06d7 100644 --- a/met/docs/Users_Guide/point-stat.rst +++ b/met/docs/Users_Guide/point-stat.rst @@ -498,7 +498,7 @@ The first set of header columns are common to all of the output files generated .. _table_PS_header_info_point-stat_out: -.. list-table:: Header information for each file point-stat outputs. +.. list-table:: Common STAT header columns. :widths: auto :header-rows: 2 diff --git a/met/docs/Users_Guide/stat-analysis.rst b/met/docs/Users_Guide/stat-analysis.rst index 2267f7ba03..80c843b9a3 100644 --- a/met/docs/Users_Guide/stat-analysis.rst +++ b/met/docs/Users_Guide/stat-analysis.rst @@ -52,10 +52,49 @@ When aggregating the matched pair line type (MPR) and computing an output contin .. _StA_Skill-Score-Index: -Skill Score Index, including GO Index -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Skill Score Index +~~~~~~~~~~~~~~~~~ + +The Stat-Analysis "ss_index", "go_index", and "cbs_index" jobs calculate skill score indices by weighting scores for meteorological fields at different levels and lead times. Pre-defined configuration files are provided for the GO Index and CBS Index which are special cases of the highly configurable skill score index job. + +In general, a skill score index is computed over several terms and the number and definition of those terms is configurable. It is computed by aggregating the output from earlier runs of the Point-Stat and/or Grid-Stat tools over one or more cases. When configuring a skill score index job, the following requirements apply: + +1. Exactly two models names must be chosen. The first is interpreted as the forecast model and the second is the reference model, against which the performance of the forecast should be measured. Specify this with the "model" configuration file entry or using the "-model" job command option. + +2. The forecast variable name, level, lead time, line type, column, and weight options must be specified. If the value remains constant for all the terms, set it to an array of length one. If the value changes for at least one term, specify an array entry for each term. Specify these with the "fcst_var", "fcst_lev", "lead_time", "line_type", "column", and "weight" configuration file entries, respectively, or use the corresponding job command options. + +3. While these line types are required, additional options may be provided for each term, including the observation type ("obtype"), verification region ("vx_mask"), and interpolation method ("interp_mthd"). Specify each as single value or provide a value for each term. + +4. Only the SL1L2 and CTC input line types are supported, and the input Point-Stat and/or Grid-Stat output must contain these line types. + +5. For the SL1L2 line type, set the "column" entry to the CNT output column that contains the statistic of interest (e.g. RMSE for root-mean-squared-error). Note, only those continuous statistics that are derivable from SL1L2 lines can be used. + +6. For the CTC line type, set the "column" entry to the CTS output column that contains the statistic of intereest (e.g. PODY for probability of detecting yes). Note, consider specifying the "fcst_thresh" for the CTC line type. + +For each term, all matching SL1L2 (or CTC) input lines are aggregated separately for the forecast and reference models. The requested statistic ("column") is derived from the aggregated partial sums or counts. For each term, a skill score is defined as: + +.. math:: ss = 1.0 - \frac{s_{fcst}^2}{s_{ref}^2} + +Where :math:`s_{fcst}` and :math:`s_{ref}` are the aggregated forecast and reference statistics, respectively. Next, a weighted average is computed from the skill scores for each term: + + .. math:: ss_{avg} = \frac{1}{n} \sum_{i=1}^{n} w_i * ss_i + +Where, :math:`w_i` and :math:`ss_i` are the weight and skill score for each term and :math:`n` is the number of terms. Finally, the skill score index is computed as: -The Stat-Analysis "ss_index" and "go_index" jobs calculate the skill score indices by weighting scores for different meteorological fields at different pressure levels and for different lead times. The GO Index is a special case of the Skill Score index for which a specific configuration file is provided. The GO index is a weighted average of the RMSE values for wind speed, dew point temperature, temperature, height, and pressure at several levels in the atmosphere. The variables, levels, and lead times included in the index are shown in :numref:`compute_GO_Index` and are defined by a default Stat-Analysis configuration file. The partial sums (SL1L2 lines in the STAT output) for each of these variables at each level and lead time must have been computed in a previous step. The Stat-Analysis tool then uses the weights in :numref:`compute_GO_Index` to compute values for the GO Index. For a general skill score index, the user can specify the weights and variables to use in the calculations in a Stat-Analysis configuration file and run the ss_index job type. +.. math:: index = \sqrt{\frac{1.0}{1.0-ss_{avg}}} + +A value greater than 1.0 indicates that the forecast model outperforms the reference, while a value less than 1.0 indicates that the reference outperforms the forecast. + +The default skill score index name (SS_INDEX) can be overridden using the "ss_index_name" option in the configuration file. The pre-defined configuration files for the GO Index and CBS Index use "GO_INDEX" and "CBS_INDEX", respectively. + +When running a skill score index job using the "-out_stat" job command option, a .stat output file is written containing the skill score index (SSIDX) output line type. If the "-by" job command option is specified, the skill score index will be computed separately for each unique combination of values found in the column(s) specified. For example, "-by FCST_INIT_BEG,VX_MASK" runs the job separately for each combination of model initialization time and verification region found in the input. Note that increasing the Stat-Analysis verbosity level (-v 3) on the command line prints detailed information about each skill score index term. + +.. _StA_Go-Index: + +GO Index +~~~~~~~~ + +The "go_index" job is a special case of the "ss_index" job, described in :numref:`StA_Skill-Score-Index`. The GO Index is a weighted average of 48 skill scores of RMSE statistics for wind speed, dew point temperature, temperature, height, and pressure at several levels in the atmosphere. The variables, levels, and lead times included in the index are listed in :numref:`compute_GO_Index` and are defined by the default "STATAnalysisConfig_GO_Index" configuration file. The partial sums (SL1L2 lines in the STAT output) for each of these variables at each level and lead time must have been computed in a previous step. The Stat-Analysis tool then uses the weights in :numref:`compute_GO_Index` to compute values for the GO Index. .. _compute_GO_Index: @@ -148,6 +187,50 @@ The Stat-Analysis "ss_index" and "go_index" jobs calculate the skill score indic - 4 - 2 +.. _StA_CBS-Index: + +CBS Index +~~~~~~~~~ + +The "cbs_index" job is a special case of the "ss_index" job, described in :numref:`StA_Skill-Score-Index`. The CBS Index is a weighted average of 40 skill scores of RMSE statistics for mean sea level pressure, height, and wind speed at multiple levels computed over the northern hemisphere, southern hemisphere and the tropics. The variables, levels, lead times, and regions included in the index are listed in :numref:`compute_CBS_Index` and are defined by the default "STATAnalysisConfig_CBS_Index" configuration file. The partial sums (SL1L2 lines in the STAT output) for each of these variables for each level, lead time, and masking region must have been computed in a previous step. The Stat-Analysis tool then uses the weights in :numref:`compute_CBS_Index` to compute values for the CBS Index. + +.. _compute_CBS_Index: + +.. list-table:: Variables, levels, and weights used to compute the CBS Index for 24, 48, 72, 96 and 120 hour lead times. + :widths: auto + :header-rows: 2 + + * - Variable + - Level + - Weights by Region + - + - + * - + - + - North Hem + - Tropics + - South Hem + * - Pressure + - Mean sea level + - 6.4 + - x + - 3.2 + * - Height + - 500 hPa + - 2.4 + - x + - 1.2 + * - Wind speed + - 250 hPa + - 2.4 + - 1.2 + - 1.2 + * - + - 850 hPa + - x + - 2.0 + - x + Ramp Events ~~~~~~~~~~~ @@ -156,7 +239,7 @@ The Stat-Analysis "ramp" job identifies ramp events (large increases or decrease Wind Direction Statistics ~~~~~~~~~~~~~~~~~~~~~~~~~ -The Stat-Analysis "aggregate_stat" job can read vector partial sums and derive wind direction error statistics (WDIR). The vector partial sums (VL1L2 or VAL1L2) or matched pairs (MPR) for the UGRD and VGRD must have been computed in a previous step, i.e. by Point-Stat or Grid-Stat tools. This job computes an average forecast wind direction and an average observed wind direction along with their difference. The output is in degrees. In Point-Stat and Grid-Stat, the UGRD and VGRD can be verified using thresholds on their values or on the calculated wind speed. If thresholds have been applied, the wind direction statistics are calculated for each threshold. +The Stat-Analysis "aggregate_stat" job can read vector partial sums and derive wind direction error statistics (WDIR). The vector partial sums (VL1L2 or VAL1L2) or matched pairs (MPR) for the UGRD and VGRD must have been computed in a previous step, i.e. by Point-Stat or Grid-Stat tools. This job computes an average forecast wind direction and an average observed wind direction along with their difference. The output is in degrees. In Point-Stat and Grid-Stat, the UGRD and VGRD can be verified using thresholds on their values or on the calculated wind speed. If thresholds have been applied, the wind direction statistics are calculated for each threshold. The first step in verifying wind direction is running the Grid-Stat and/or Point-Stat tools to verify each forecast of interest and generate the VL1L2 or MPR line(s). When running these tools, please note: @@ -432,7 +515,16 @@ ___________________ column = []; weight = []; -The column and weight fields are used to define a skill score index. The computation of a single value will be computed from each column and weight value specified. The GO Index is a specific example of a skill score index. +The column and weight entries are used to define a skill score index. They can either be set to a constant value of length one or specify a separate value for each term of the index. + +___________________ + +.. code-block:: none + + ss_index_name = "SS_INDEX"; + ss_index_vld_thresh = 1.0; + +The ss_index_name and ss_index_vld_thresh options are used to define a skill score index. The ss_index_name entry is a string which defines the output name for the current skill score index configuration. The ss_index_vld_thresh entry is a number between 0.0 and 1.0 that defines the required ratio of valid terms. If the ratio of valid skill score index terms to the total is less than than this number, no output is written for that case. The default value of 1.0 indicates that all terms are required. ___________________ @@ -476,7 +568,10 @@ All possible tasks for **job_name** are listed in :numref:`Des_components_STAT_a - Calculates a user-defined Skill Score index as described in section :numref:`StA_Skill-Score-Index`. - \-model forecast :raw-html:`
` \-model reference * - go_index - - Calculates the GO Index as described in section :numref:`StA_Skill-Score-Index`. + - Calculates the GO Index as described in section :numref:`StA_GO-Index`. + - \-model forecast :raw-html:`
` \-model reference + * - cbs_index + - Calculates the CBS Index as described in section :numref:`StA_CBS-Index`. - \-model forecast :raw-html:`
` \-model reference * - ramp - Defines a ramp event on a time-series of forecast and observed values. The amount of change from one time to the next is computed for forecast and observed values. Those changes are thresholded to define events which are used to populate a 2x2 contingency table. @@ -656,7 +751,6 @@ This job produces summary statistics for the column name and line type specified * - 22 - WMO Weighted Mean value - Job: aggregate ^^^^^^^^^^^^^^ @@ -694,15 +788,73 @@ This job is similar to the "**aggregate**" job listed above, however the format * - MPR - FHO, CTC, CTS, MCTC, MCTS, PCT, PSTD, PJC, or PRC (must specify "**-out_fcst_thresh**" and "**-out_obs_thresh**" arguments) -**Job: ss_index** +Job: ss_index, go_index, cbs_index +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The output from this job consists of three lines, the first two of which contain "**JOB_LIST**" and "**COL_NAME**", as described above. The third line contains "**SS_INDEX**" followed by a colon and then the value computed for the user-defined Skill Score Index. +While the inputs for the "ss_index", "go_index", and "cbs_index" jobs may vary, the output is the same. By default, the job output is written to the screen or to a "-out" file, if specified. If the "-out_stat" job command option is specified, a STAT output file is written containing the skill score index (SSIDX) output line type. -**Job: go_index** +The SSIDX line type consists of the common STAT header columns described in :numref:`table_PS_header_info_point-stat_out` followed by the columns described below. In general, when multiple input header strings are encountered, the output is reported as a comma-separated list of the unique values. The "-set_hdr" job command option can be used to override any of the output header strings (e.g. "-set_hdr VX_MASK MANY" sets the output VX_MASK column to "MANY"). Special logic applied to some of the STAT header columns are also described below. -The output from this job consists of three lines, the first two of which contain "**JOB_LIST**" and"**COL_NAME**", as described above. The third line contains "**GO_INDEX**" followed by a colon and then the value computed for the GO Index. +.. _table_SA_format_info_SSIDX: -**Job: ramp** +.. list-table:: Format information for the SSIDX (Skill Score Index) output line type. + :widths: auto + :header-rows: 2 + + * - SSIDX OUTPUT FORMAT + - + - + * - Column Number + - SSIDX Column Name + - Description + * - 4 + - FCST_LEAD + - Maximum input forecast lead time + * - 5 + - FCST_VALID_BEG + - Minimum input forecast valid start time + * - 6 + - FCST_VALID_END + - Maximum input forecast valid end time + * - 7 + - OBS_LEAD + - Maximum input observation lead time + * - 8 + - OBS_VALID_BEG + - Minimum input observation valid start time + * - 9 + - OBS_VALID_END + - Maximum input observation valid end time + * - 10 + - FCST_VAR + - Skill score index name from the "ss_index_name" option + * - 11 + - OBS_VAR + - Skill score index name from the "ss_index_name" option + * - 24 + - SSIDX + - Skill score index line type + * - 25 + - FCST_MODEL + - Forecast model name + * - 26 + - REF_MODEL + - Reference model name + * - 27 + - N_INIT + - Number of unique input model initialization times + * - 28 + - N_TERM + - Number of skill score index terms + * - 29 + - N_VLD + - Number of terms for which a valid skill score was computed + * - 30 + - SS_INDEX + - Skill score index value + +Job: ramp +^^^^^^^^^ The ramp job operates on a time-series of forecast and observed values and is analogous to the RIRW (Rapid Intensification and Weakening) job described in :numref:`tc_stat-output`. The amount of change from one time to the next is computed for forecast and observed values. Those changes are thresholded to define events which are used to populate a 2x2 contingency table. diff --git a/met/docs/Users_Guide/wavelet-stat.rst b/met/docs/Users_Guide/wavelet-stat.rst index e449a513e3..2b9a39291b 100644 --- a/met/docs/Users_Guide/wavelet-stat.rst +++ b/met/docs/Users_Guide/wavelet-stat.rst @@ -323,7 +323,7 @@ The output ASCII files are named similarly: wavelet_stat_PREFIX_HHMMSSL_YYYYMMDD_HHMMSSV_TYPE.txt where TYPE is isc to indicate that this is an intensity-scale line type. -The format of the STAT and ASCII output of the Wavelet-Stat tool is similar to the format of the STAT and ASCII output of the Point-Stat tool. Please refer to the tables in :numref:`point_stat-output` for a description of the common output for STAT files types. The information contained in the STAT and isc files are identical. However, for consistency with the STAT files produced by other tools, the STAT file will only have column headers for the first 21 fields. The isc file contains all headers. The format of the ISC line type is explained in the following table. +The format of the STAT and ASCII output of the Wavelet-Stat tool is similar to the format of the STAT and ASCII output of the Point-Stat tool. Please refer to the tables in :numref:`point_stat-output` for a description of the common output for STAT files types. The information contained in the STAT and isc files are identical. However, for consistency with the STAT files produced by other tools, the STAT file will only have names for the header columns. The isc file contains names for all columns. The format of the ISC line type is explained in the following table. .. _table_WS_header_info_ws_outputs: diff --git a/met/scripts/config/STATAnalysisConfig b/met/scripts/config/STATAnalysisConfig index 6ff87047e5..5f81208f5a 100644 --- a/met/scripts/config/STATAnalysisConfig +++ b/met/scripts/config/STATAnalysisConfig @@ -104,6 +104,7 @@ boot = { //////////////////////////////////////////////////////////////////////////////// +ss_index_name = "SS_INDEX"; hss_ec_value = NA; rank_corr_flag = TRUE; vif_flag = FALSE; diff --git a/met/src/basic/vx_cal/time_array.cc b/met/src/basic/vx_cal/time_array.cc index 4521693ed9..cbbf8aa8eb 100644 --- a/met/src/basic/vx_cal/time_array.cc +++ b/met/src/basic/vx_cal/time_array.cc @@ -567,4 +567,24 @@ return ( 0 ); } +//////////////////////////////////////////////////////////////////////// + + +ConcatString write_css(const TimeArray &ta) + +{ + +ConcatString css; + +for ( int i=0; i " - << "null string!\n\n"; + << "output header column " << to_upper(col_name) << " is empty!\n\n"; return(na_string); } // Check for embedded whitespace - if(check_reg_exp(ws_reg_exp, s_tmp.c_str())) { + if(check_reg_exp(ws_reg_exp, cs_tmp.c_str())) { mlog << Error << "\ncheck_hdr_str() -> " - << "output header column value (\"" << s_tmp - << "\") should contain no embedded whitespace!\n\n"; + << "output header column " << to_upper(col_name) << " value (\"" + << cs_tmp << "\") should contain no embedded whitespace!\n\n"; exit(1); } - return(s_tmp); + return(cs_tmp); } diff --git a/met/src/basic/vx_util/ascii_table.h b/met/src/basic/vx_util/ascii_table.h index 4e0ed53804..e75f64876c 100644 --- a/met/src/basic/vx_util/ascii_table.h +++ b/met/src/basic/vx_util/ascii_table.h @@ -366,7 +366,7 @@ extern void copy_ascii_table_row(const AsciiTable &at_from, const int r_from, As extern void justify_met_at(AsciiTable &at, const int n_hdr_cols); -extern ConcatString check_hdr_str(const ConcatString, +extern ConcatString check_hdr_str(const ConcatString &, const ConcatString &, bool space_to_underscore = false); diff --git a/met/src/basic/vx_util/crc_array.h b/met/src/basic/vx_util/crc_array.h index 4fa5a99e6c..d79886b62c 100644 --- a/met/src/basic/vx_util/crc_array.h +++ b/met/src/basic/vx_util/crc_array.h @@ -130,6 +130,7 @@ class CRC_Array { void add(const CRC_Array &); void add_css_sec(const char *); + void set(const T & val); void set(int ix, const T & val); void sort_increasing(); @@ -394,6 +395,24 @@ return; //////////////////////////////////////////////////////////////////////// +template + +void CRC_Array::set(const T & elem) + +{ + +clear(); + +add(elem); + +return; + +} + + +//////////////////////////////////////////////////////////////////////// + + template void CRC_Array::set(int ix, const T & elem) @@ -410,6 +429,7 @@ void CRC_Array::set(int ix, const T & elem) exit ( 1 ); } + e[ix] = elem; } diff --git a/met/src/basic/vx_util/num_array.cc b/met/src/basic/vx_util/num_array.cc index 9493b14fb2..3a6b10e5a1 100644 --- a/met/src/basic/vx_util/num_array.cc +++ b/met/src/basic/vx_util/num_array.cc @@ -495,14 +495,48 @@ return; //////////////////////////////////////////////////////////////////////// +void NumArray::set(int k) + +{ + +set((double) k); + +return; + +} + + +//////////////////////////////////////////////////////////////////////// + + +void NumArray::set(double d) + +{ + +erase(); + +add(d); + + // + // an array of length one is sorted + // + +Sorted = true; + +return; + +} + + +//////////////////////////////////////////////////////////////////////// + + void NumArray::set(int i, int k) { set(i, (double) k); -Sorted = false; - return; } diff --git a/met/src/basic/vx_util/num_array.h b/met/src/basic/vx_util/num_array.h index 8c24299a42..eaea0f7990 100644 --- a/met/src/basic/vx_util/num_array.h +++ b/met/src/basic/vx_util/num_array.h @@ -79,6 +79,8 @@ class NumArray { void add_css(const char *); void add_css_sec(const char *); + void set(int); + void set(double); void set(int, int); void set(int, double); diff --git a/met/src/basic/vx_util/stat_column_defs.h b/met/src/basic/vx_util/stat_column_defs.h index 84653915fc..b8ddc583bc 100644 --- a/met/src/basic/vx_util/stat_column_defs.h +++ b/met/src/basic/vx_util/stat_column_defs.h @@ -309,6 +309,15 @@ static const char * ssvar_columns [] = { "RMSE" }; +static const char * relp_columns [] = { + "TOTAL", "N_ENS", "RELP_" +}; + +static const char * ssidx_columns [] = { + "FCST_MODEL", "REF_MODEL", "N_INIT", + "N_TERM", "N_VLD", "SS_INDEX" +}; + static const char * genmpr_columns [] = { "TOTAL", "INDEX", "STORM_ID", "AGEN_INIT", "AGEN_FHR", @@ -318,10 +327,6 @@ static const char * genmpr_columns [] = { "DEV_CAT", "OPS_CAT" }; -static const char * relp_columns [] = { - "TOTAL", "N_ENS", "RELP_" -}; - static const char * job_summary_columns [] = { "TOTAL", "MEAN", "MEAN_NCL", "MEAN_NCU", "MEAN_BCL", "MEAN_BCU", @@ -332,14 +337,6 @@ static const char * job_summary_columns [] = { "WMO_TYPE", "WMO_MEAN", "WMO_WEIGHTED_MEAN" }; -static const char * job_go_columns [] = { - "GO_INDEX" -}; - -static const char * job_ss_columns [] = { - "SS_INDEX" -}; - static const char * job_wdir_columns [] = { "TOTAL", "FBAR", "OBAR", "ME", "MAE" @@ -399,8 +396,6 @@ static const int n_dmap_columns = sizeof(dmap_columns)/sizeof(*dmap_colu static const int n_isc_columns = sizeof(isc_columns)/sizeof(*isc_columns); static const int n_job_summary_columns = sizeof(job_summary_columns)/sizeof(*job_summary_columns); -static const int n_job_go_columns = sizeof(job_go_columns)/sizeof(*job_go_columns); -static const int n_job_ss_columns = sizeof(job_ss_columns)/sizeof(*job_ss_columns); static const int n_job_wdir_columns = sizeof(job_wdir_columns)/sizeof(*job_wdir_columns); static const int n_job_ramp_columns = sizeof(job_ramp_columns)/sizeof(*job_ramp_columns); static const int n_job_ramp_mpr_columns = sizeof(job_ramp_mpr_columns)/sizeof(*job_ramp_mpr_columns); @@ -414,6 +409,8 @@ static const int n_orank_columns = sizeof(orank_columns)/sizeof(*orank_co static const int n_ssvar_columns = sizeof(ssvar_columns)/sizeof(*ssvar_columns); static const int n_relp_columns = sizeof(relp_columns)/sizeof(*relp_columns); +static const int n_ssidx_columns = sizeof(ssidx_columns)/sizeof(*ssidx_columns); + static const int n_genmpr_columns = sizeof(genmpr_columns)/sizeof(*genmpr_columns); //////////////////////////////////////////////////////////////////////// diff --git a/met/src/basic/vx_util/thresh_array.cc b/met/src/basic/vx_util/thresh_array.cc index 50358a5d83..faafb0d98e 100644 --- a/met/src/basic/vx_util/thresh_array.cc +++ b/met/src/basic/vx_util/thresh_array.cc @@ -256,6 +256,16 @@ void ThreshArray::add_css(const char *text) { //////////////////////////////////////////////////////////////////////// +void ThreshArray::set(const SingleThresh &st) { + + clear(); + + add(st); + + return; +} +//////////////////////////////////////////////////////////////////////// + void ThreshArray::parse_thresh_str(const char *thresh_str) { char *line = (char *) 0; char *c = (char *) 0; diff --git a/met/src/basic/vx_util/thresh_array.h b/met/src/basic/vx_util/thresh_array.h index d27dc087c9..12fcce1499 100644 --- a/met/src/basic/vx_util/thresh_array.h +++ b/met/src/basic/vx_util/thresh_array.h @@ -57,6 +57,8 @@ class ThreshArray { void add(const ThreshArray &); void add_css(const char *); + void set(const SingleThresh &); + void parse_thresh_str(const char *); int n_elements() const; @@ -103,7 +105,6 @@ extern ThreshArray process_perc_thresh_bins (const ThreshArray &); extern ThreshArray process_rps_cdp_thresh (const ThreshArray &); extern ConcatString write_css (const ThreshArray &); - //////////////////////////////////////////////////////////////////////// #endif /* __THRESH_ARRAY_H__ */ diff --git a/met/src/libcode/vx_analysis_util/stat_job.cc b/met/src/libcode/vx_analysis_util/stat_job.cc index c6cfafddea..70464037c6 100644 --- a/met/src/libcode/vx_analysis_util/stat_job.cc +++ b/met/src/libcode/vx_analysis_util/stat_job.cc @@ -202,6 +202,10 @@ void STATAnalysisJob::clear() { boot_interval = bad_data_int; boot_rep_prop = bad_data_double; n_boot_rep = bad_data_int; + + ss_index_name.clear(); + ss_index_vld_thresh = bad_data_double; + hss_ec_value = bad_data_double; rank_corr_flag = false; vif_flag = false; @@ -345,6 +349,9 @@ void STATAnalysisJob::assign(const STATAnalysisJob & aj) { boot_rep_prop = aj.boot_rep_prop; n_boot_rep = aj.n_boot_rep; + ss_index_name = aj.ss_index_name; + ss_index_vld_thresh = aj.ss_index_vld_thresh; + hss_ec_value = aj.hss_ec_value; rank_corr_flag = aj.rank_corr_flag; vif_flag = aj.vif_flag; @@ -628,6 +635,12 @@ void STATAnalysisJob::dump(ostream & out, int depth) const { out << prefix << "boot_seed = " << boot_seed << "\n"; + out << prefix << "ss_index_name = " + << ss_index_name << "\n"; + + out << prefix << "ss_index_vld_thresh = " + << ss_index_vld_thresh << "\n"; + out << prefix << "hss_ec_value = " << hss_ec_value << "\n"; @@ -1606,6 +1619,14 @@ void STATAnalysisJob::parse_job_command(const char *jobstring) { set_boot_seed(jc_array[i+1].c_str()); i++; } + else if(jc_array[i] == "-ss_index_name") { + ss_index_name = jc_array[i+1].c_str(); + i++; + } + else if(jc_array[i] == "-ss_index_vld_thresh") { + ss_index_vld_thresh = atof(jc_array[i+1].c_str()); + i++; + } else if(jc_array[i] == "-hss_ec_value") { hss_ec_value = atof(jc_array[i+1].c_str()); i++; @@ -1969,6 +1990,7 @@ void STATAnalysisJob::setup_stat_file(int n_row, int n) { case stat_orank: c = n_orank_columns; break; case stat_ssvar: c = n_ssvar_columns; break; case stat_genmpr: c = n_genmpr_columns; break; + case stat_ssidx: c = n_ssidx_columns; break; default: mlog << Error << "\nSTATAnalysisJob::setup_stat_file() -> " << "unexpected stat line type \"" << statlinetype_to_string(cur_lt) @@ -2039,6 +2061,7 @@ void STATAnalysisJob::setup_stat_file(int n_row, int n) { case stat_orank: write_header_row (orank_columns, n_orank_columns, 1, stat_at, 0, 0); break; case stat_ssvar: write_header_row (ssvar_columns, n_ssvar_columns, 1, stat_at, 0, 0); break; case stat_genmpr: write_header_row (genmpr_columns, n_genmpr_columns, 1, stat_at, 0, 0); break; + case stat_ssidx: write_header_row (ssidx_columns, n_ssidx_columns, 1, stat_at, 0, 0); break; // // Write only header columns for unspecified line type @@ -2774,6 +2797,18 @@ ConcatString STATAnalysisJob::get_jobstring() const { } } + // Jobs which compute the skill score index + if(job_type == stat_job_go_index || + job_type == stat_job_cbs_index || + job_type == stat_job_ss_index) { + + // ss_index_name + js << "-ss_index_name " << ss_index_name << " "; + + // ss_index_vld_thresh + js << "-ss_index_vld_thresh " << ss_index_vld_thresh << " "; + } + // Jobs which write MCTC or MCTS output if(!is_bad_data(hss_ec_value) && (out_line_type.has(stat_mctc_str) || @@ -2891,8 +2926,10 @@ STATJobType string_to_statjobtype(const char *str) { else if(strcasecmp(str, statjobtype_str[4]) == 0) t = stat_job_go_index; else if(strcasecmp(str, statjobtype_str[5]) == 0) - t = stat_job_ss_index; + t = stat_job_cbs_index; else if(strcasecmp(str, statjobtype_str[6]) == 0) + t = stat_job_ss_index; + else if(strcasecmp(str, statjobtype_str[7]) == 0) t = stat_job_ramp; else t = no_stat_job_type; diff --git a/met/src/libcode/vx_analysis_util/stat_job.h b/met/src/libcode/vx_analysis_util/stat_job.h index 72254bef5c..bed32cdc1a 100644 --- a/met/src/libcode/vx_analysis_util/stat_job.h +++ b/met/src/libcode/vx_analysis_util/stat_job.h @@ -6,8 +6,6 @@ // ** P.O.Box 3000, Boulder, Colorado, 80307-3000, USA // *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* - - //////////////////////////////////////////////////////////////////////// #ifndef __STAT_JOB_H__ @@ -76,19 +74,21 @@ enum STATJobType { stat_job_go_index = 4, // Compute the GO Index. - stat_job_ss_index = 5, // Compute the Skill Score Index. + stat_job_cbs_index = 5, // Compute the CBS Index. + + stat_job_ss_index = 6, // Compute the Skill Score Index. - stat_job_ramp = 6, // Time-series ramp evaluation. + stat_job_ramp = 7, // Time-series ramp evaluation. - no_stat_job_type = 7 // Default value + no_stat_job_type = 8 // Default value }; -static const int n_statjobtypes = 8; +static const int n_statjobtypes = 9; static const char * const statjobtype_str[n_statjobtypes] = { "filter", "summary", "aggregate", - "aggregate_stat", "go_index", "ss_index", - "ramp", "NA" + "aggregate_stat", "go_index", "cbs_index", + "ss_index", "ramp", "NA" }; extern const char *statjobtype_to_string(const STATJobType); @@ -131,6 +131,7 @@ class STATAnalysisJob { void parse_job_command(const char *); void add_column_thresh(const char *, const char *); + void set_job_type (const STATJobType); int set_job_type (const char *); void set_dump_row (const char *); void set_stat_file(const char *); @@ -323,6 +324,16 @@ class STATAnalysisJob { char *boot_rng; char *boot_seed; + // + // Name of the skill score index being computed + // + ConcatString ss_index_name; + + // + // Required ratio of valid skill score index terms + // + double ss_index_vld_thresh; + // // MCTS HSS Expected Correct rate // @@ -345,6 +356,8 @@ class STATAnalysisJob { //////////////////////////////////////////////////////////////////////// +inline void STATAnalysisJob::set_job_type (const STATJobType t) { job_type = t; return; } + inline void STATAnalysisJob::set_precision (int p) { precision = p; return; } inline int STATAnalysisJob::get_precision () const { return(precision); } diff --git a/met/src/libcode/vx_shapedata/engine.cc b/met/src/libcode/vx_shapedata/engine.cc index ff0b98e393..cbb8974c96 100644 --- a/met/src/libcode/vx_shapedata/engine.cc +++ b/met/src/libcode/vx_shapedata/engine.cc @@ -2773,10 +2773,11 @@ void write_header_columns(ModeFuzzyEngine & eng, const Grid & grid, AsciiTable & // Version at.set_entry(row, c++, - (string)met_version); + (string) met_version); // Model Name - s = check_hdr_str(eng.conf_info.model); + s = check_hdr_str(conf_key_model, + eng.conf_info.model); at.set_entry(row, c++, s.text()); // N_valid @@ -2787,7 +2788,7 @@ void write_header_columns(ModeFuzzyEngine & eng, const Grid & grid, AsciiTable & // Description - s = check_hdr_str(eng.conf_info.desc); + s = check_hdr_str(conf_key_desc, eng.conf_info.desc); at.set_entry(row, c++, s.text()); // Forecast lead time @@ -2831,31 +2832,38 @@ void write_header_columns(ModeFuzzyEngine & eng, const Grid & grid, AsciiTable & eng.conf_info.obs_conv_thresh.get_str()); // Forecast Variable Name - s = check_hdr_str(eng.conf_info.fcst_info->name_attr()); + s = check_hdr_str(conf_key_fcst_var, + eng.conf_info.fcst_info->name_attr()); at.set_entry(row, c++, s.text()); // Forecast Variable Units - s = check_hdr_str(eng.conf_info.fcst_info->units_attr(), true); + s = check_hdr_str(conf_key_fcst_units, + eng.conf_info.fcst_info->units_attr(), true); at.set_entry(row, c++, s.text()); // Forecast Variable Level - s = check_hdr_str(eng.conf_info.fcst_info->level_attr(), true); + s = check_hdr_str(conf_key_fcst_lev, + eng.conf_info.fcst_info->level_attr(), true); at.set_entry(row, c++, s.text()); // Observation Variable Name - s = check_hdr_str(eng.conf_info.obs_info->name_attr()); + s = check_hdr_str(conf_key_obs_var, + eng.conf_info.obs_info->name_attr()); at.set_entry(row, c++, s.text()); // Observation Variable Units - s = check_hdr_str(eng.conf_info.obs_info->units_attr(), true); + s = check_hdr_str(conf_key_obs_units, + eng.conf_info.obs_info->units_attr(), true); at.set_entry(row, c++, s.text()); // Observation Variable Level - s = check_hdr_str(eng.conf_info.obs_info->level_attr(), true); + s = check_hdr_str(conf_key_obs_lev, + eng.conf_info.obs_info->level_attr(), true); at.set_entry(row, c++, s.text()); // Observation type - s = check_hdr_str(eng.conf_info.obtype); + s = check_hdr_str(conf_key_obtype, + eng.conf_info.obtype); at.set_entry(row, c++, s.text()); return; diff --git a/met/src/libcode/vx_stat_out/stat_columns.cc b/met/src/libcode/vx_stat_out/stat_columns.cc index 3f9f8a364d..39707d1e67 100644 --- a/met/src/libcode/vx_stat_out/stat_columns.cc +++ b/met/src/libcode/vx_stat_out/stat_columns.cc @@ -4126,6 +4126,38 @@ void write_relp_cols(const PairDataEnsemble *pd_ptr, //////////////////////////////////////////////////////////////////////// +void write_ssidx_cols(const SSIDXData &ssidx_data, + AsciiTable &at, int r, int c) { + + // + // Skill Score Index + // Dump out the SSIDX line: + // FCST_MODEL, REF_MODEL, N_INIT, + // N_TERM, N_VLD, SS_INDEX + // + at.set_entry(r, c+0, // Forecast model name + ssidx_data.fcst_model); + + at.set_entry(r, c+1, // Reference model name + ssidx_data.ref_model); + + at.set_entry(r, c+2, // Number of initializations + ssidx_data.init_time.n()); + + at.set_entry(r, c+3, // Number of terms + ssidx_data.n_term); + + at.set_entry(r, c+4, // Number of valid terms + ssidx_data.n_vld); + + at.set_entry(r, c+5, // Skill score index value + ssidx_data.ss_index); + + return; +} + +//////////////////////////////////////////////////////////////////////// + void justify_stat_cols(AsciiTable &at) { justify_met_at(at, n_header_columns); diff --git a/met/src/libcode/vx_stat_out/stat_columns.h b/met/src/libcode/vx_stat_out/stat_columns.h index ff974d7c1e..96a3a0c5c4 100644 --- a/met/src/libcode/vx_stat_out/stat_columns.h +++ b/met/src/libcode/vx_stat_out/stat_columns.h @@ -189,6 +189,8 @@ extern void write_ssvar_cols (const PairDataEnsemble *, int, double, AsciiTable &, int, int); extern void write_relp_cols (const PairDataEnsemble *, AsciiTable &, int, int); +extern void write_ssidx_cols (const SSIDXData &, + AsciiTable &, int, int); // Setup column justification for STAT AsciiTable objects extern void justify_stat_cols(AsciiTable &); diff --git a/met/src/libcode/vx_stat_out/stat_hdr_columns.cc b/met/src/libcode/vx_stat_out/stat_hdr_columns.cc index 2ab360b744..23ce8fe8f0 100644 --- a/met/src/libcode/vx_stat_out/stat_hdr_columns.cc +++ b/met/src/libcode/vx_stat_out/stat_hdr_columns.cc @@ -99,14 +99,14 @@ void StatHdrColumns::clear() { //////////////////////////////////////////////////////////////////////// void StatHdrColumns::set_model(const char *s) { - model = check_hdr_str((string)s); + model = check_hdr_str(conf_key_model, (string) s); return; } //////////////////////////////////////////////////////////////////////// void StatHdrColumns::set_desc(const char *s) { - desc = check_hdr_str((string)s); + desc = check_hdr_str(conf_key_desc, (string) s); return; } @@ -161,56 +161,56 @@ void StatHdrColumns::set_obs_valid_end(const unixtime ut) { //////////////////////////////////////////////////////////////////////// void StatHdrColumns::set_fcst_var(const ConcatString s) { - fcst_var = check_hdr_str(s); + fcst_var = check_hdr_str(conf_key_fcst_var, s); return; } //////////////////////////////////////////////////////////////////////// void StatHdrColumns::set_fcst_units(const ConcatString s) { - fcst_units = check_hdr_str(s, true); + fcst_units = check_hdr_str(conf_key_fcst_units, s, true); return; } //////////////////////////////////////////////////////////////////////// void StatHdrColumns::set_fcst_lev(const char *s) { - fcst_lev = check_hdr_str((string)s, true); + fcst_lev = check_hdr_str(conf_key_fcst_lev, (string) s, true); return; } //////////////////////////////////////////////////////////////////////// void StatHdrColumns::set_obs_var(const ConcatString s) { - obs_var = check_hdr_str(s); + obs_var = check_hdr_str(conf_key_obs_var, s); return; } //////////////////////////////////////////////////////////////////////// void StatHdrColumns::set_obs_units(const ConcatString s) { - obs_units = check_hdr_str(s, true); + obs_units = check_hdr_str(conf_key_obs_units, s, true); return; } //////////////////////////////////////////////////////////////////////// void StatHdrColumns::set_obs_lev(const char *s) { - obs_lev = check_hdr_str((string)s, true); + obs_lev = check_hdr_str(conf_key_obs_lev, (string) s, true); return; } //////////////////////////////////////////////////////////////////////// void StatHdrColumns::set_obtype(const char *s) { - obtype = check_hdr_str((string)s); + obtype = check_hdr_str(conf_key_obtype, (string) s); return; } //////////////////////////////////////////////////////////////////////// void StatHdrColumns::set_mask(const char *s) { - mask = check_hdr_str((string)s); + mask = check_hdr_str(conf_key_vx_mask, (string) s); return; } @@ -234,7 +234,7 @@ void StatHdrColumns::set_interp_mthd(ConcatString s, GridTemplateFactory gtf; mthd << '_' << gtf.enum2String(shape).c_str(); } - interp_mthd = check_hdr_str(mthd); + interp_mthd = check_hdr_str(conf_key_interp_mthd, mthd); return; } @@ -269,7 +269,7 @@ void StatHdrColumns::set_interp_pnts(const int n) { //////////////////////////////////////////////////////////////////////// void StatHdrColumns::set_line_type(const char *s) { - line_type = check_hdr_str((string)s); + line_type = check_hdr_str(conf_key_line_type, (string) s); return; } diff --git a/met/src/libcode/vx_statistics/met_stats.cc b/met/src/libcode/vx_statistics/met_stats.cc index a1aa7870bf..17adde559a 100644 --- a/met/src/libcode/vx_statistics/met_stats.cc +++ b/met/src/libcode/vx_statistics/met_stats.cc @@ -431,6 +431,7 @@ void CTSInfo::compute_ci() { double CTSInfo::get_stat(const char *stat_name) { double v = bad_data_double; + // Find the statistic by name if(strcmp(stat_name, "TOTAL") == 0) v = cts.n(); else if(strcmp(stat_name, "BASER") == 0) v = cts.baser(); else if(strcmp(stat_name, "FMEAN") == 0) v = cts.fmean(); @@ -458,6 +459,11 @@ double CTSInfo::get_stat(const char *stat_name) { << "\"!\n\n"; exit(1); } + + // Return bad data for 0 pairs + if(cts.n() == 0 && strcmp(stat_name, "TOTAL") != 0) { + v = bad_data_double; + } return(v); } @@ -1001,6 +1007,7 @@ void CNTInfo::compute_ci() { double CNTInfo::get_stat(const char *stat_name) { double v = bad_data_double; + // Find the statistic by name if(strcmp(stat_name, "TOTAL" ) == 0) v = n; else if(strcmp(stat_name, "FBAR" ) == 0) v = fbar.v; else if(strcmp(stat_name, "FSTDEV" ) == 0) v = fstdev.v; @@ -1040,6 +1047,11 @@ double CNTInfo::get_stat(const char *stat_name) { exit(1); } + // Return bad data for 0 pairs + if(n == 0 && strcmp(stat_name, "TOTAL") != 0) { + v = bad_data_double; + } + return(v); } diff --git a/met/src/libcode/vx_statistics/met_stats.h b/met/src/libcode/vx_statistics/met_stats.h index 06b6af3fcd..1c2cfc353b 100644 --- a/met/src/libcode/vx_statistics/met_stats.h +++ b/met/src/libcode/vx_statistics/met_stats.h @@ -664,6 +664,31 @@ class DMAPInfo { inline double DMAPInfo::get_beta_value() const { return(beta_value); } +//////////////////////////////////////////////////////////////////////// +// +// Structure to store the Skill Score Index output +// +//////////////////////////////////////////////////////////////////////// + +struct SSIDXData { + + // Skill score index name + ConcatString ss_index_name; + + // Forecast and reference model names + ConcatString fcst_model; + ConcatString ref_model; + + // List of unique initialization times + TimeArray init_time; + + // Number of terms and number valid + int n_term, n_vld; + + // Skill score index value + double ss_index; +}; + //////////////////////////////////////////////////////////////////////// // // Utility functions for parsing data from configuration files diff --git a/met/src/tools/core/stat_analysis/Makefile.am b/met/src/tools/core/stat_analysis/Makefile.am index 60ca332858..00e6a2488d 100644 --- a/met/src/tools/core/stat_analysis/Makefile.am +++ b/met/src/tools/core/stat_analysis/Makefile.am @@ -14,7 +14,8 @@ bin_PROGRAMS = stat_analysis stat_analysis_SOURCES = stat_analysis.cc \ aggr_stat_line.cc \ parse_stat_line.cc \ - stat_analysis_job.cc + stat_analysis_job.cc \ + skill_score_index_job.cc stat_analysis_CPPFLAGS = ${MET_CPPFLAGS} stat_analysis_LDFLAGS = ${MET_LDFLAGS} stat_analysis_LDADD = -lvx_stat_out \ @@ -47,4 +48,5 @@ stat_analysis_LDADD = -lvx_stat_out \ EXTRA_DIST = stat_analysis.h \ parse_stat_line.h \ aggr_stat_line.h \ - stat_analysis_job.h + stat_analysis_job.h \ + skill_score_index_job.h diff --git a/met/src/tools/core/stat_analysis/aggr_stat_line.cc b/met/src/tools/core/stat_analysis/aggr_stat_line.cc index a26a3df46b..3e66de254e 100644 --- a/met/src/tools/core/stat_analysis/aggr_stat_line.cc +++ b/met/src/tools/core/stat_analysis/aggr_stat_line.cc @@ -466,7 +466,7 @@ StatHdrColumns StatHdrInfo::get_shc(const ConcatString &cur_case, // INTERP_PNTS css = write_css(interp_pnts); - if(interp_pnts.n() > 1) { + if(interp_pnts.n() == 0 || interp_pnts.n() > 1) { mlog << Warning << "For case \"" << cur_case << "\", found " << interp_pnts.n() @@ -502,7 +502,7 @@ StatHdrColumns StatHdrInfo::get_shc(const ConcatString &cur_case, // ALPHA css = write_css(alpha); - if(alpha.n() > 1) { + if(alpha.n() == 0 || alpha.n() > 1) { mlog << Warning << "For case \"" << cur_case << "\", found " << alpha.n() @@ -1558,7 +1558,6 @@ void aggr_psum_lines(LineDataFile &f, STATAnalysisJob &job, // Increment sums in the existing map entry // else { - m[key].sl1l2_info += cur_sl1l2; m[key].vl1l2_info += cur_vl1l2; m[key].nbrcnt_info += cur_nbrcnt; @@ -3397,6 +3396,198 @@ void aggr_time_series_lines(LineDataFile &f, STATAnalysisJob &job, //////////////////////////////////////////////////////////////////////// +void aggr_ss_index(LineDataFile &f, STATAnalysisJob &job, + map &m, + int &n_in, int &n_out) { + STATLine line; + AggrSSIndexInfo cur; + ConcatString key; + int i, n_term; + + // + // Store the index name and valid data threshold + // + cur.job_info.ss_index_name = job.ss_index_name; + cur.job_info.ss_index_vld_thresh = job.ss_index_vld_thresh; + + // + // Check that the -model option has been supplied exactly 2 times. + // The first is the forecast model and the second is the reference. + // + if(job.model.n() != 2) { + mlog << Error << "\naggr_ss_index() -> " + << "this job may only be called when the \"-model\" option " + << "has been used exactly twice to specify the forecast " + << "model followed by the reference model.\n\n"; + throw(1); + } + else { + cur.job_info.fcst_model = job.model[0]; + cur.job_info.ref_model = job.model[1]; + } + + mlog << Debug(3) + << "Computing " << cur.job_info.ss_index_name << " for forecast model (" + << cur.job_info.fcst_model << ") versus reference model (" + << cur.job_info.ref_model << ").\n"; + + // + // Compute the number of terms as the maximum array length + // + n_term = max( 0, job.fcst_var.n()); + n_term = max(n_term, job.fcst_lev.n()); + n_term = max(n_term, job.fcst_lead.n()); + n_term = max(n_term, job.line_type.n()); + n_term = max(n_term, job.column.n()); + n_term = max(n_term, job.weight.n()); + + // + // Must be at least one term + // + if(n_term < 1) { + mlog << Error << "\naggr_ss_var() -> " + << "you must define the skill score index to be computed " + << "using the \"-fcst_var\", \"-fcst_lev\", \"-fcst_lead\", " + << "\"-line_type\", \"-column\", and \"-weight\" options.\n\n"; + throw(1); + } + + // + // Sanity check the array lengths + // + if((job.fcst_lev.n() != n_term && job.fcst_lev.n() != 1) || + (job.fcst_lead.n() != n_term && job.fcst_lead.n() != 1) || + (job.line_type.n() != n_term && job.line_type.n() != 1) || + (job.column.n() != n_term && job.column.n() != 1) || + (job.weight.n() != n_term && job.weight.n() != 1)) { + mlog << Error << "\naggr_ss_var() -> " + << "each skill score index parameter must have the same length (" + << n_term << ") or have length 1!\n" + << "Check the \"-fcst_var\", \"-fcst_lev\", \"-fcst_lead\", " + << "\"-line_type\", \"-column\", and \"-weight\" options.\n\n"; + throw(1); + } + + // + // Create a job for each term + // + for(i=0; i " + << "a skill score index can only be computed using " + << "statistics derived from SL1L2 or CTC line types." + << "\n\n"; + throw(1); + } + } + + // + // Set filtering options + // + fcst_term.model.set(cur.job_info.fcst_model); + if(job.fcst_lead.n() == n_term) fcst_term.fcst_lead.set(job.fcst_lead[i]); + if(job.obs_lead.n() == n_term) fcst_term.obs_lead.set(job.obs_lead[i]); + if(job.fcst_init_hour.n() == n_term) fcst_term.fcst_init_hour.set(job.fcst_init_hour[i]); + if(job.obs_init_hour.n() == n_term) fcst_term.obs_init_hour.set(job.obs_init_hour[i]); + if(job.fcst_var.n() == n_term) fcst_term.fcst_var.set(job.fcst_var[i]); + if(job.obs_var.n() == n_term) fcst_term.obs_var.set(job.obs_var[i]); + if(job.fcst_lev.n() == n_term) fcst_term.fcst_lev.set(job.fcst_lev[i]); + if(job.obs_lev.n() == n_term) fcst_term.obs_lev.set(job.obs_lev[i]); + if(job.obtype.n() == n_term) fcst_term.obtype.set(job.obtype[i]); + if(job.vx_mask.n() == n_term) fcst_term.vx_mask.set(job.vx_mask[i]); + if(job.interp_mthd.n() == n_term) fcst_term.interp_mthd.set(job.interp_mthd[i]); + if(job.interp_pnts.n() == n_term) fcst_term.interp_pnts.set(job.interp_pnts[i]); + if(job.fcst_thresh.n() == n_term) fcst_term.fcst_thresh.set(job.fcst_thresh[i]); + if(job.obs_thresh.n() == n_term) fcst_term.obs_thresh.set(job.obs_thresh[i]); + if(job.line_type.n() == n_term) fcst_term.line_type.set(job.line_type[i]); + if(job.column.n() == n_term) fcst_term.column.set(job.column[i]); + if(job.weight.n() == n_term) fcst_term.weight.set(job.weight[i]); + + // + // Set the reference model job identical to the forecast model + // job but with a different model name. + // + ref_term = fcst_term; + ref_term.model.set(cur.job_info.ref_model); + + // + // Store the forecast and reference jobs for this term + // + cur.job_info.add_term(fcst_term, ref_term); + + } // end for i + + // + // Process the STAT lines + // + while(f >> line) { + + if(line.is_header()) continue; + + n_in++; + + if(cur.job_info.is_keeper(line)) { + + // + // Build the map key for the current line + // + key = job.get_case_info(line); + + // + // Add a new map entry, if necessary + // + if(m.count(key) == 0) { + m[key] = cur; + mlog << Debug(3) << "[Case " << m.size() + << "] Added new case for key \"" + << key << "\".\n"; + } + + // + // Add the current line to the map entry + // + m[key].job_info.add(line); + + // + // Keep track of the unique header column entries + // + m[key].hdr.add(line); + + // + // Write line to dump file + // + job.dump_stat_line(line); + + n_out++; + } + } // end while + + return; +} + +//////////////////////////////////////////////////////////////////////// + void mpr_to_ctc(STATAnalysisJob &job, const AggrMPRInfo &info, int i_thresh, CTSInfo &cts_info) { int i; diff --git a/met/src/tools/core/stat_analysis/aggr_stat_line.h b/met/src/tools/core/stat_analysis/aggr_stat_line.h index 166dde307e..9cf72aeb2f 100644 --- a/met/src/tools/core/stat_analysis/aggr_stat_line.h +++ b/met/src/tools/core/stat_analysis/aggr_stat_line.h @@ -53,6 +53,7 @@ using namespace std; #include "vx_statistics.h" #include "vx_stat_out.h" #include "ens_stats.h" +#include "skill_score_index_job.h" //////////////////////////////////////////////////////////////////////// @@ -160,6 +161,11 @@ struct AggrRPSInfo { RPSInfo rps_info; }; +struct AggrSSIndexInfo { + StatHdrInfo hdr; + SSIndexJobInfo job_info; +}; + // Define struct used to perform comparisons for SSVAR bins struct ssvar_bin_cmp { bool operator()(const ConcatString & cs1, const ConcatString & cs2) const { @@ -287,6 +293,11 @@ extern void aggr_time_series_lines( map &, int &, int &); +extern void aggr_ss_index( + LineDataFile &, STATAnalysisJob &, + map &, + int &, int &); + //////////////////////////////////////////////////////////////////////// extern void mpr_to_ctc( diff --git a/met/src/tools/core/stat_analysis/skill_score_index_job.cc b/met/src/tools/core/stat_analysis/skill_score_index_job.cc new file mode 100644 index 0000000000..7cfac5a250 --- /dev/null +++ b/met/src/tools/core/stat_analysis/skill_score_index_job.cc @@ -0,0 +1,359 @@ +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +// ** Copyright UCAR (c) 1992 - 2021 +// ** 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 +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* + +//////////////////////////////////////////////////////////////////////// +// +// Filename: skill_score_index_job.cc +// +// Description: +// +// Mod# Date Name Description +// ---- ---- ---- ----------- +// 000 08/25/21 Halley Gotway New +// +//////////////////////////////////////////////////////////////////////// + +using namespace std; + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "skill_score_index_job.h" +#include "parse_stat_line.h" + +//////////////////////////////////////////////////////////////////////// +// +// Code for class SSIndexJobInfo +// +//////////////////////////////////////////////////////////////////////// + +SSIndexJobInfo::SSIndexJobInfo() { + init_from_scratch(); +} + +//////////////////////////////////////////////////////////////////////// + +SSIndexJobInfo::~SSIndexJobInfo() { + clear(); +} + +//////////////////////////////////////////////////////////////////////// + +SSIndexJobInfo::SSIndexJobInfo(const SSIndexJobInfo &c) { + + init_from_scratch(); + + assign(c); +} + +//////////////////////////////////////////////////////////////////////// + +SSIndexJobInfo & SSIndexJobInfo::operator=(const SSIndexJobInfo &c) { + + if(this == &c) return(*this); + + assign(c); + + return(*this); +} + +//////////////////////////////////////////////////////////////////////// + +void SSIndexJobInfo::init_from_scratch() { + + clear(); + + return; +} + +//////////////////////////////////////////////////////////////////////// + +void SSIndexJobInfo::clear() { + + // Initialize + ss_index_name.clear(); + ss_index_vld_thresh = 0.0; + fcst_model.clear(); + ref_model.clear(); + n_term = 0; + n_fcst_lines.clear(); + n_ref_lines.clear(); + job_lt.clear(); + fcst_job.clear(); + ref_job.clear(); + fcst_sl1l2.clear(); + ref_sl1l2.clear(); + fcst_cts.clear(); + ref_cts.clear(); + + return; +} + +//////////////////////////////////////////////////////////////////////// + +void SSIndexJobInfo::assign(const SSIndexJobInfo &c) { + + ss_index_name = c.ss_index_name; + ss_index_vld_thresh = c.ss_index_vld_thresh; + fcst_model = c.fcst_model; + ref_model = c.ref_model; + n_term = c.n_term; + n_fcst_lines = c.n_fcst_lines; + n_ref_lines = c.n_ref_lines; + job_lt = c.job_lt; + fcst_job = c.fcst_job; + ref_job = c.ref_job; + fcst_sl1l2 = c.fcst_sl1l2; + ref_sl1l2 = c.ref_sl1l2; + fcst_cts = c.fcst_cts; + ref_cts = c.ref_cts; + + return; +} + +//////////////////////////////////////////////////////////////////////// + +void SSIndexJobInfo::add_term(const STATAnalysisJob &fcst_term, + const STATAnalysisJob &ref_term) { + + // Increment the counter + n_term++; + + // Add the jobs + fcst_job.push_back(fcst_term); + ref_job.push_back(ref_term); + + // Add the input line type for each job + job_lt.push_back(string_to_statlinetype(fcst_term.line_type[0].c_str())); + + // Add partial sums + SL1L2Info sl1l2_info; + fcst_sl1l2.push_back(sl1l2_info); + ref_sl1l2.push_back(sl1l2_info); + + // Add contingency tables + CTSInfo cts_info; + fcst_cts.push_back(cts_info); + ref_cts.push_back(cts_info); + + // Add line counters + n_fcst_lines.add(0); + n_ref_lines.add(0); + + return; +} + +//////////////////////////////////////////////////////////////////////// + +bool SSIndexJobInfo::is_keeper(const STATLine &line) { + bool keep = false; + + // Check each forecast and reference job + for(int i=0; i " + << "unxpected line type of " << statlinetype_to_string(job_lt[i]) + << "!\n\n"; + exit(1); + } + + // Check for conditions when a skill score cannot be computed + if(nint(n_fcst_lines[i]) == 0 || nint(n_ref_lines[i]) == 0 || + is_bad_data(fcst_stat) || is_bad_data(ref_stat) || + is_eq(ref_stat, 0.0)) { + ss = bad_data_double; + } + // Compute the skill score and keep a running sum of the skill + // scores and weights + else { + ss = 1.0 - (fcst_stat*fcst_stat)/(ref_stat*ref_stat); + ss_sum += ss*fcst_job[i].weight[0]; + weight_sum += fcst_job[i].weight[0]; + } + + // Format log message strings + ConcatString term_cs, fcst_cs, ref_cs, ss_cs; + term_cs << fcst_job[i].fcst_var[0] << "/" + << fcst_job[i].fcst_lev[0] << " at " + << sec_to_hhmmss(fcst_job[i].fcst_lead[0]) << " lead"; + if(is_bad_data(fcst_stat)) fcst_cs << na_str; + else fcst_cs << fcst_stat; + if(is_bad_data(ref_stat)) ref_cs << na_str; + else ref_cs << ref_stat; + if(is_bad_data(ss)) ss_cs << na_str; + else ss_cs << ss; + + // Print debug info for each term + mlog << Debug(3) << ss_index_name << " Term " << i+1 + << ": " << term_cs << ", " + << n_fcst_lines[i] << " fcst " + << fcst_job[i].line_type[0] << "->" + << fcst_job[i].column[0] << " = " << fcst_cs << ", " + << n_ref_lines[i] << " ref " + << fcst_job[i].line_type[0] << "->" + << fcst_job[i].column[0] << " = " << ref_cs + << ", skill = " << ss_cs + << ", weight = " << fcst_job[i].weight[0] << "\n"; + + // Check if the number of aggregated lines differ + if(nint(n_fcst_lines[i]) != nint(n_ref_lines[i])) { + mlog << Warning << "\nSSIndexJobInfo::compute_ss_index() -> " + << "the number of aggregated forecast and reference lines " + << "differ (" << n_fcst_lines[i] << " != " << n_ref_lines[i] + << ") for term " << i+1 << " (" << term_cs << ").\n\n"; + } + + if(is_bad_data(ss)) { + mlog << Warning << "\nSSIndexJobInfo::compute_ss_index() -> " + << "can't compute the skill score for term " << i+1 + << " (" << term_cs << ").\n\n"; + } + else { + n_vld++; + } + + } // end for i + + // Check the required ratio of valid terms + if(((double) n_vld / n_term) < ss_index_vld_thresh) { + mlog << Warning << "\nSSIndexJobInfo::compute_ss_index() -> " + << "skipping " << ss_index_name + << " since the ratio of valid terms " << n_vld << "/" + << n_term << " < " << ss_index_vld_thresh << "!\n\n"; + data.n_vld = 0; + return(data); + } + + // Compute the weighted average of the skill scores + if(is_eq(weight_sum, 0.0)) ss_avg = bad_data_double; + else ss_avg = ss_sum/weight_sum; + + // Store the output data + data.ss_index_name = ss_index_name; + data.fcst_model = fcst_model; + data.ref_model = ref_model; + data.init_time = init_time; + data.n_term = n_term; + data.n_vld = n_vld; + if(is_bad_data(ss_avg) || is_eq(ss_avg, 1.0)) { + data.ss_index = bad_data_double; + } + else { + data.ss_index = sqrt(1.0/(1.0 - ss_avg)); + } + + mlog << Debug(3) + << ss_index_name << " Weighted Average = " << ss_avg << "\n" + << ss_index_name << " Skill Score Value = " << data.ss_index << "\n"; + + return(data); +} + +//////////////////////////////////////////////////////////////////////// diff --git a/met/src/tools/core/stat_analysis/skill_score_index_job.h b/met/src/tools/core/stat_analysis/skill_score_index_job.h new file mode 100644 index 0000000000..60d2350171 --- /dev/null +++ b/met/src/tools/core/stat_analysis/skill_score_index_job.h @@ -0,0 +1,111 @@ +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +// ** Copyright UCAR (c) 1992 - 2021 +// ** 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 +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* + +//////////////////////////////////////////////////////////////////////// +// +// Filename: skill_score_index_job.h +// +// Description: +// +// Mod# Date Name Description +// ---- ---- ---- ----------- +// 000 07/28/21 Halley Gotway New +// +//////////////////////////////////////////////////////////////////////// + +#ifndef __SKILL_SCORE_INDEX_JOB_H__ +#define __SKILL_SCORE_INDEX_JOB_H__ + +//////////////////////////////////////////////////////////////////////// + +using namespace std; + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "met_stats.h" +#include "stat_job.h" +#include "vx_config.h" +#include "vx_util.h" + +//////////////////////////////////////////////////////////////////////// +// +// Class used to compute the Skill Score Index Job +// +//////////////////////////////////////////////////////////////////////// + +class SSIndexJobInfo { + + private: + void init_from_scratch(); + void assign(const SSIndexJobInfo &); + + public: + + SSIndexJobInfo(); + ~SSIndexJobInfo(); + SSIndexJobInfo(const SSIndexJobInfo &); + SSIndexJobInfo & operator=(const SSIndexJobInfo &); + + // Index name + ConcatString ss_index_name; + + // Valid data threshold + double ss_index_vld_thresh; + + // Forecast and reference model names + ConcatString fcst_model, ref_model; + + // Array of unique initialization times + TimeArray init_time; + + // Number of terms + int n_term; + + // Array of input lines counts for each term + NumArray n_fcst_lines, n_ref_lines; + + // Input line type for each term + vector job_lt; + + // Vectors of jobs for each term + vector fcst_job; + vector ref_job; + + // Vectors of partial sums and contingency tables for each term + vector fcst_sl1l2; + vector ref_sl1l2; + vector fcst_cts; + vector ref_cts; + + // Add jobs for each term + void add_term(const STATAnalysisJob &, + const STATAnalysisJob &); + + // Process STAT lines + bool is_keeper(const STATLine &); + bool add(STATLine &); + + // Compute the skill score index value + SSIDXData compute_ss_index(); + + void clear(); +}; + +//////////////////////////////////////////////////////////////////////// + +#endif // __SKILL_SCORE_INDEX_JOB__ + +//////////////////////////////////////////////////////////////////////// diff --git a/met/src/tools/core/stat_analysis/stat_analysis.cc b/met/src/tools/core/stat_analysis/stat_analysis.cc index 8c1df6d2d6..de7a7bf076 100644 --- a/met/src/tools/core/stat_analysis/stat_analysis.cc +++ b/met/src/tools/core/stat_analysis/stat_analysis.cc @@ -41,6 +41,7 @@ // percentile thresholds. // 012 04/25/21 Halley Gotway Replace pickle files for temporary // ascii. +// 013 07/16/21 Halley Gotway MET #1788 Add CBS Index. // //////////////////////////////////////////////////////////////////////// @@ -433,8 +434,6 @@ void set_out_file(const char *path) { void process_search_dirs() { int n, i, j, max_len, n_read, n_keep; - MetConfig go_conf; - STATAnalysisJob go_job; // // Initialize @@ -456,40 +455,45 @@ void process_search_dirs() { } // - // Apply the GO Index filtering criteria for a command line job. + // Apply the GO Index or CBS Index filtering criteria. // - if(default_job.job_type == stat_job_go_index) { + if(default_job.job_type == stat_job_go_index || + default_job.job_type == stat_job_cbs_index) { - mlog << Debug(1) << "GO Index Config File: " - << replace_path(go_index_config_file) << "\n"; + MetConfig ss_index_conf; + STATAnalysisJob ss_index_job; + + ConcatString config_file = + (default_job.job_type == stat_job_go_index ? + replace_path(go_index_config_file) : + replace_path(cbs_index_config_file)); + + mlog << Debug(1) << "Skill Score Index Config File: " + << config_file << "\n"; // - // Read config file constants followed by the config file which - // defines the GO Index. + // Read the config files for the constants and the skill score index. // - go_conf.read(replace_path(config_const_filename).c_str()); - go_conf.read(replace_path(go_index_config_file).c_str()); + ss_index_conf.read(replace_path(config_const_filename).c_str()); + ss_index_conf.read(config_file.c_str()); // - // Parse the contents of the GO Index config file into the - // search job. + // Parse the Skill Score Index config file into the search job. // - set_job_from_config(go_conf, go_job); + ss_index_job.set_job_type(default_job.job_type); + set_job_from_config(ss_index_conf, ss_index_job); // - // Amend the default job with GO Index filtering criteria. + // Amend the default job with Skill Score Index filtering criteria. // - default_job.parse_job_command(go_job.get_jobstring().c_str()); - - } // end if go_index + default_job.parse_job_command(ss_index_job.get_jobstring().c_str()); + } // // Open up the temp file for storing the intermediate STAT line data // - open_temps(); - // // Go through each input file // @@ -633,9 +637,8 @@ return; //////////////////////////////////////////////////////////////////////// void process_job(const char * jobstring, int n_job) { - STATAnalysisJob job, go_job; + STATAnalysisJob job; ConcatString full_jobstring; - MetConfig go_conf; mlog << Debug(4) << "process_job(jobstring): " << jobstring << "\n"; @@ -659,45 +662,47 @@ void process_job(const char * jobstring, int n_job) { } // - // Special processing for the GO Index job. + // Special processing for the GO Index and CBS Index jobs. // - if(job.job_type == stat_job_go_index) { + if(job.job_type == stat_job_go_index || + job.job_type == stat_job_cbs_index) { + + MetConfig ss_index_conf; + STATAnalysisJob ss_index_job; - mlog << Debug(1) << "GO Index Config File: " - << replace_path(go_index_config_file) << "\n"; + ConcatString config_file = + (job.job_type == stat_job_go_index ? + replace_path(go_index_config_file) : + replace_path(cbs_index_config_file)); // - // Read config file constants followed by the config file which - // defines the GO Index. + // Read the config files for the constants and the skill score index. // - go_conf.read(replace_path(config_const_filename).c_str()); - go_conf.read(replace_path(go_index_config_file).c_str()); + ss_index_conf.read(replace_path(config_const_filename).c_str()); + ss_index_conf.read(config_file.c_str()); // - // Parse the contents of the GO Index config file into the - // search job. + // Parse the Skill Score Index config file into the search job. // - set_job_from_config(go_conf, go_job); + ss_index_job.set_job_type(job.job_type); + set_job_from_config(ss_index_conf, ss_index_job); // - // Amend the current job with GO Index filtering criteria + // Amend the current job with Skill Score Index filtering criteria. // mlog << Debug(4) - << "\nAmending Job " << n_job << " with GO Index configuration file: " - << replace_path(go_index_config_file) << "\n"; - job.parse_job_command(go_job.get_jobstring().c_str()); - - } // end if go_index + << "\nAmending Job " << n_job << " with Skill Score Index configuration file: " + << config_file << "\n"; + job.parse_job_command(ss_index_job.get_jobstring().c_str()); + } // - // Amend the current job using any command line options + // Override with any command line options // - if(jobstring != command_line_job_options) { - mlog << Debug(4) - << "\nAmending Job " << n_job << " with command line options: \"" - << command_line_job_options << "\"\n"; - job.parse_job_command(command_line_job_options.c_str()); - } + mlog << Debug(4) + << "\nAmending Job " << n_job << " with command line options: \"" + << command_line_job_options << "\"\n"; + job.parse_job_command(command_line_job_options.c_str()); // // Get the full jobstring diff --git a/met/src/tools/core/stat_analysis/stat_analysis.h b/met/src/tools/core/stat_analysis/stat_analysis.h index c07abfa476..bd70bb19b9 100644 --- a/met/src/tools/core/stat_analysis/stat_analysis.h +++ b/met/src/tools/core/stat_analysis/stat_analysis.h @@ -55,7 +55,10 @@ static const char * default_config_filename = static const char * go_index_config_file = "MET_BASE/config/STATAnalysisConfig_GO_Index"; - + +static const char * cbs_index_config_file = + "MET_BASE/config/STATAnalysisConfig_CBS_Index"; + //////////////////////////////////////////////////////////////////////// // // Variables for Command Line Arguments diff --git a/met/src/tools/core/stat_analysis/stat_analysis_job.cc b/met/src/tools/core/stat_analysis/stat_analysis_job.cc index 451b6d785f..85df53e471 100644 --- a/met/src/tools/core/stat_analysis/stat_analysis_job.cc +++ b/met/src/tools/core/stat_analysis/stat_analysis_job.cc @@ -121,6 +121,18 @@ void set_job_from_config(MetConfig &c, STATAnalysisJob &job) { job.set_boot_rng(boot_info.rng.c_str()); job.set_boot_seed(boot_info.seed.c_str()); + job.ss_index_name = c.lookup_string(conf_key_ss_index_name); + job.ss_index_vld_thresh = c.lookup_double(conf_key_ss_index_vld_thresh); + + // Check that ss_index_vld_thresh is in [0, 1]. + if(job.ss_index_vld_thresh < 0.0 || + job.ss_index_vld_thresh > 1.0) { + mlog << Error << "\nset_job_from_config() -> " + << "\"" << conf_key_ss_index_vld_thresh << "\" (" + << job.ss_index_vld_thresh << ") must be set between 0 and 1.\n\n"; + throw(1); + } + job.hss_ec_value = c.lookup_double(conf_key_hss_ec_value); job.rank_corr_flag = (int) c.lookup_bool(conf_key_rank_corr_flag); job.vif_flag = (int) c.lookup_bool(conf_key_vif_flag); @@ -190,7 +202,10 @@ void do_job(const ConcatString &jobstring, STATAnalysisJob &job, job.job_type != stat_job_summary && job.job_type != stat_job_aggr && job.job_type != stat_job_aggr_stat && - job.job_type != stat_job_ramp) { + job.job_type != stat_job_ramp && + job.job_type != stat_job_go_index && + job.job_type != stat_job_cbs_index && + job.job_type != stat_job_ss_index) { mlog << Warning << "\nThe -by option is ignored for the \"" << statjobtype_to_string(job.job_type) << "\" job type.\n\n"; } @@ -226,9 +241,7 @@ void do_job(const ConcatString &jobstring, STATAnalysisJob &job, break; case(stat_job_go_index): - do_job_go_index(jobstring, f, job, n_in, n_out, sa_out); - break; - + case(stat_job_cbs_index): case(stat_job_ss_index): do_job_ss_index(jobstring, f, job, n_in, n_out, sa_out); break; @@ -369,7 +382,7 @@ void do_job_summary(const ConcatString &jobstring, LineDataFile &f, // Check for no matching STAT lines // if(n_out == 0) { - mlog << Warning << "\ndo_job_aggr() -> " + mlog << Warning << "\ndo_job_summary() -> " << "no matching STAT lines found for job: " << jobstring << "\n\n"; return; @@ -3932,76 +3945,101 @@ void write_job_ramp_cols(const STATAnalysisJob &job, AsciiTable &at, return; } -//////////////////////////////////////////////////////////////////////// -// -// The do_job_go_index() routine is used to compute the GO Index. -// The GO Index is a special case of the Skill Score Index consisting -// of a predefined set of variables, levels, lead times, statistics, -// and weights. -// For lead times of 12, 24, 36, and 48 hours, it contains RMSE for: -// - Wind Speed at the surface(b), 850(a), 400(a), 250(a) mb -// - Dewpoint Temperature at the surface(b), 850(b), 700(b), 400(b) mB -// - Temperature at the surface(b), 400(a) mB -// - Height at 400(a) mB -// - Sea Level Pressure(b) -// Where (a) means weights of 4, 3, 2, 1 for the lead times, and -// (b) means weights of 8, 6, 4, 2 for the lead times. -// The RMSE values are dervied from the partial sums in the SL1L2 lines. -// //////////////////////////////////////////////////////////////////////// -void do_job_go_index(const ConcatString &jobstring, LineDataFile &f, - STATAnalysisJob &job, int &n_in, int &n_out, - ofstream *sa_out) { - double go_index; - AsciiTable out_at; +void write_job_ss_index(STATAnalysisJob &job, + map &m, + AsciiTable &at) { + map::iterator it; + int n_row, n_col, r, c; + StatHdrColumns shc; + SSIDXData ssidx_data; // - // Compute the GO Index as a special case of the Skill Score Index + // Setup the output table // - go_index = compute_ss_index(jobstring, f, job, n_in, n_out); + n_row = 1 + m.size(); + n_col = 1 + job.by_column.n() + n_ssidx_columns; // - // Check for no matching STAT lines + // Prepare the output // - if(n_out == 0) { - mlog << Warning << "\ndo_job_go_index() -> " - << "no matching STAT lines found for job: " << jobstring - << "\n\n"; - return; + if(job.stat_out) { + job.setup_stat_file(n_row, 0); + } + else { + write_job_aggr_hdr(job, n_row, n_col, at); + c = 1 + job.by_column.n(); + write_header_row(ssidx_columns, n_ssidx_columns, 0, at, 0, c); } - // - // Get the column names - // - out_at.set_size(2, 2); - setup_table(out_at, 1, job.get_precision()); - out_at.set_entry(0, 0, "COL_NAME:"); - write_header_row(job_go_columns, n_job_go_columns, 0, out_at, 0, 1); + mlog << Debug(2) << "Computing output for " + << (int) m.size() << " case(s).\n"; // - // Write the data row + // Loop through the map // - out_at.set_entry(1, 0, "GO_INDEX:"); - out_at.set_entry(1, 1, go_index); + for(it = m.begin(), r=1; it != m.end(); it++) { - // - // Write the Ascii Table and the job command line - // - write_jobstring(jobstring, sa_out); - write_table(out_at, sa_out); + // + // Format the output STAT header columns + // + shc = it->second.hdr.get_shc(it->first, job.by_column, + job.hdr_name, job.hdr_value, stat_ssidx); + + // + // Set FCST/OBS_VAR = skill score index type + // Set FCST/OBS_UNITS = FCST/OBS_LEV = NA + // + shc.set_fcst_var(it->second.job_info.ss_index_name); + shc.set_obs_var(it->second.job_info.ss_index_name); + shc.set_fcst_units(na_str); + shc.set_obs_units(na_str); + shc.set_fcst_lev(na_str); + shc.set_obs_lev(na_str); + + // + // Retrieve the SSIDXData + // + ssidx_data = it->second.job_info.compute_ss_index(); + + // + // Skip empty output + // + if(ssidx_data.n_vld == 0) continue; + + // + // Initialize + // + c = 0; + + // + // SSIDX output line + // + if(job.stat_out) { + write_header_cols(shc, job.stat_at, job.stat_row); + write_ssidx_cols(ssidx_data, job.stat_at, + job.stat_row++, n_header_columns); + } + else { + at.set_entry(r, c++, it->second.job_info.ss_index_name); + write_case_cols(it->first, at, r, c); + write_ssidx_cols(ssidx_data, at, r++, c); + } + } // end for it return; } //////////////////////////////////////////////////////////////////////// // -// The do_job_ss_index() routine is used to compute the generalized -// Skill Score Index. This job can be configured to compute a weighted -// average of skill scores derived from a configurable set of variables, -// levels, lead times, and statistics. The skill score index is -// computed using two models, a forecast model and a reference model. -// For each statistic in the index, a skill score is computed as: +// The do_job_ss_index() routine is used to compute the GO Index, +// CBS Index, or generalized Skill Score Index. This job can be +// configured to compute a weighted average of skill scores derived +// from a configurable set of variables, levels, lead times, and +// statistics. The skill score index is computed using two models, +// a forecast model and a reference model. For each statistic in +// the index, a skill score is computed as: // SS = 1 - (S[model]*S[model])/(S[reference]*S[reference]) // Where S is the statistic. // Next, a weighted average is computed over all the skill scores. @@ -4014,13 +4052,23 @@ void do_job_go_index(const ConcatString &jobstring, LineDataFile &f, void do_job_ss_index(const ConcatString &jobstring, LineDataFile &f, STATAnalysisJob &job, int &n_in, int &n_out, ofstream *sa_out) { - double ss_index; + map ssidx_map; AsciiTable out_at; + // + // Store the output line type + // + job.out_line_type.add(stat_ssidx_str); + // // Compute the Skill Score Index // - ss_index = compute_ss_index(jobstring, f, job, n_in, n_out); + aggr_ss_index(f, job, ssidx_map, n_in, n_out); + + // + // Write the output + // + write_job_ss_index(job, ssidx_map, out_at); // // Check for no matching STAT lines @@ -4033,24 +4081,11 @@ void do_job_ss_index(const ConcatString &jobstring, LineDataFile &f, } // - // Get the column names - // - out_at.set_size(2, 2); - setup_table(out_at, 1, job.get_precision()); - out_at.set_entry(0, 0, "COL_NAME:"); - write_header_row(job_ss_columns, n_job_ss_columns, 0, out_at, 0, 1); - - // - // Write the data row - // - out_at.set_entry(1, 0, "SS_INDEX:"); - out_at.set_entry(1, 1, ss_index); - - // - // Write the Ascii Table and the job command line + // Write the ASCII Table and the job command line + // If -out_stat was specified, do not write output // write_jobstring(jobstring, sa_out); - write_table(out_at, sa_out); + if(!job.stat_out) write_table(out_at, sa_out); return; } @@ -4243,551 +4278,6 @@ void write_line(const ConcatString &str, ofstream *sa_out) { //////////////////////////////////////////////////////////////////////// -double compute_ss_index(const ConcatString &jobstring, LineDataFile &f, - STATAnalysisJob &job, int &n_in, int &n_out) { - STATLine line; - SL1L2Info si; - TTContingencyTable ct; - CNTInfo fcst_cnt, ref_cnt; - bool keep; - int i, n_terms; - double fcst_stat, ref_stat, ss, ss_sum, weight_sum; - double ss_avg, ss_index; - - // - // Check that the -model option has been supplied exactly 2 times. - // The first is the forecast model and the second is the reference. - // - if(job.model.n() != 2) { - mlog << Error << "\ncompute_ss_index() -> " - << "this job may only be called when the \"-model\" option " - << "has been used exactly twice to specify the forecast " - << "model followed by the reference model: " - << jobstring << "\n\n"; - throw(1); - } - - // - // Use the length of the fcst_var array to infer the number of terms. - // - if((n_terms = job.fcst_var.n()) < 1) { - mlog << Error << "\ncompute_ss_index() -> " - << "you must define the Skill Score Index to be computed " - << "using the \"-fcst_var\", \"-fcst_lev\", \"-fcst_lead\", " - << "\"-line_type\", \"-column\", and \"-weight\" options: " - << jobstring << "\n\n"; - throw(1); - } - - // - // Check that the required elements are of the same length. - // - if(n_terms != job.fcst_lev.n() || - n_terms != job.fcst_lead.n() || - n_terms != job.line_type.n() || - n_terms != job.column.n() || - n_terms != job.weight.n()) { - mlog << Error << "\ncompute_ss_index() -> " - << "all filtering parameters for defining the Skill Score " - << "Index must be of the same length. Check \"-fcst_var\", " - << "\"-fcst_lev\", \"-fcst_lead\", \"-line_type\", " - << "\"-column\", and \"-weight\" options: " - << jobstring << "\n\n"; - throw(1); - } - - // - // Define arrays of jobs for each term in the Skill Score Index. - // Separate arrays for the forecast and reference models. - // - STATAnalysisJob *fcst_job = (STATAnalysisJob *) 0, *ref_job = (STATAnalysisJob *) 0; - fcst_job = new STATAnalysisJob [n_terms]; - ref_job = new STATAnalysisJob [n_terms]; - - // - // Define arrays of objects to store the partial sums or contingency - // table counts for each term in the Skill Score Index. - // - SL1L2Info *fcst_si = (SL1L2Info *) 0, *ref_si = (SL1L2Info *) 0; - CTSInfo *fcst_cts = (CTSInfo *) 0, *ref_cts = (CTSInfo *) 0; - fcst_si = new SL1L2Info [n_terms]; - ref_si = new SL1L2Info [n_terms]; - fcst_cts = new CTSInfo [n_terms]; - ref_cts = new CTSInfo [n_terms]; - - - // - // Define array of line types to be aggregated for each term in the - // Skill Score Index. - // - STATLineType *job_lt = (STATLineType *) 0; - job_lt = new STATLineType [n_terms]; - - // - // Arrays to keep track of the number of stat lines per term - // - NumArray n_fcst_lines, n_ref_lines; - - mlog << Debug(3) << "Forecast Model = " << job.model[0] << "\n" - << "Reference Model = " << job.model[1] << "\n"; - - // - // Set up the job for each term in the index. - // - for(i=0; i " - << "a Skill Score Index can only be computed using " - << "statistics derived from SL1L2 or CTC line types." - << "\n\n"; - throw(1); - } - } - - // - // column - // - if(job.column.n() == n_terms) { - fcst_job[i].column.clear(); - fcst_job[i].column.add(job.column[i]); - } - - // - // weight - // - if(job.weight.n() == n_terms) { - fcst_job[i].weight.clear(); - fcst_job[i].weight.add(job.weight[i]); - } - - // - // Set the reference model job identical to the forecast model - // job but with a different model name. - // - ref_job[i] = fcst_job[i]; - ref_job[i].model.set(0, job.model[1]); - - } // end for i - - // - // Process the STAT lines - // - n_in = n_out = 0; - while(f >> line) { - - if(line.is_header()) continue; - - n_in++; - - // - // Loop through the jobs to see if this line should be kept - // - keep = 0; - for(i=0; i " - << "the number of aggregated forecast and reference lines " - << "differ (" << n_fcst_lines[i] << " != " << n_ref_lines[i] - << ") for term " << i+1 << ".\n\n"; - } - - if(is_bad_data(ss)) { - mlog << Warning << "\ncompute_ss_index() -> " - << "can't compute skill score for term " << i+1 << ".\n\n"; - } - - } // end for i - - // - // Compute the weighted average of the skill scores. - // - if(is_eq(weight_sum, 0.0)) ss_avg = bad_data_double; - else ss_avg = ss_sum/weight_sum; - - // - // Compute the Skill Score Index value. - // - if(is_bad_data(ss_avg) || - is_eq(ss_avg, 1.0)) ss_index = bad_data_double; - else ss_index = sqrt(1.0/(1.0 - ss_avg)); - - mlog << Debug(3) << "Skill Score Index Weighted Average = " << ss_avg << "\n" - << "Skill Score Index Value = " << ss_index << "\n"; - - // - // Clean up allocated memory. - // - if(fcst_job) { delete [] fcst_job; fcst_job = (STATAnalysisJob *) 0; } - if(ref_job) { delete [] ref_job; ref_job = (STATAnalysisJob *) 0; } - if(fcst_si) { delete [] fcst_si; fcst_si = (SL1L2Info *) 0; } - if(ref_si) { delete [] ref_si; ref_si = (SL1L2Info *) 0; } - if(fcst_cts) { delete [] fcst_cts; fcst_cts = (CTSInfo *) 0; } - if(ref_cts) { delete [] ref_cts; ref_cts = (CTSInfo *) 0; } - if(job_lt) { delete [] job_lt; job_lt = (STATLineType *) 0; } - - return(ss_index); -} - -//////////////////////////////////////////////////////////////////////// - void write_case_cols(const ConcatString &cs, AsciiTable &at, int &r, int &c) { StringArray sa = cs.split(":"); diff --git a/met/src/tools/core/stat_analysis/stat_analysis_job.h b/met/src/tools/core/stat_analysis/stat_analysis_job.h index e03c74330d..5f67470758 100644 --- a/met/src/tools/core/stat_analysis/stat_analysis_job.h +++ b/met/src/tools/core/stat_analysis/stat_analysis_job.h @@ -68,9 +68,6 @@ extern void do_job_aggr_stat(const ConcatString &, LineDataFile &, STATAnalysisJob &, int &, int &, ofstream *, const ConcatString &, gsl_rng *); -extern void do_job_go_index(const ConcatString &, LineDataFile &, - STATAnalysisJob &, int &, int &, ofstream *); - extern void do_job_ss_index(const ConcatString &, LineDataFile &, STATAnalysisJob &, int &, int &, ofstream *); @@ -143,6 +140,9 @@ extern void write_job_ramp(STATAnalysisJob &, extern void write_job_ramp_cols(const STATAnalysisJob &, AsciiTable &, int &, int &); +extern void write_job_ss_index(STATAnalysisJob &, + AggrSSIndexInfo &, AsciiTable &); + //////////////////////////////////////////////////////////////////////// extern void setup_table (AsciiTable &, int, int); @@ -152,11 +152,11 @@ extern void write_line (const ConcatString &, ofstream *); //////////////////////////////////////////////////////////////////////// -extern double compute_ss_index(const ConcatString &, LineDataFile &, - STATAnalysisJob &, int &, int &); +extern void compute_ss_index(LineDataFile &, STATAnalysisJob &, + AggrSSIndexInfo &, int &, int &); extern void write_case_cols(const ConcatString &, AsciiTable &, - int &, int &); + int &, int &); //////////////////////////////////////////////////////////////////////// diff --git a/met/src/tools/other/mode_time_domain/mtd_config_info.cc b/met/src/tools/other/mode_time_domain/mtd_config_info.cc index 8f700c0b85..baa789d11c 100644 --- a/met/src/tools/other/mode_time_domain/mtd_config_info.cc +++ b/met/src/tools/other/mode_time_domain/mtd_config_info.cc @@ -697,13 +697,13 @@ table.set_entry(row, c++, (string)met_version); // model -s = check_hdr_str(model); +s = check_hdr_str(conf_key_model, model); table.set_entry(row, c++, s.text()); // description -s = check_hdr_str(desc); +s = check_hdr_str(conf_key_desc, desc); table.set_entry(row, c++, s.text()); @@ -765,37 +765,37 @@ table.set_entry(row, c++, s.text()); // fcst var -s = check_hdr_str(fcst_info->name_attr()); +s = check_hdr_str(conf_key_fcst_var, fcst_info->name_attr()); table.set_entry(row, c++, s.text()); // fcst units -s = check_hdr_str(fcst_info->units_attr(), true); +s = check_hdr_str(conf_key_fcst_units, fcst_info->units_attr(), true); table.set_entry(row, c++, s.text()); // fcst level -s = check_hdr_str(fcst_info->level_attr(), true); +s = check_hdr_str(conf_key_fcst_lev, fcst_info->level_attr(), true); table.set_entry(row, c++, s.text()); // obs var -s = check_hdr_str(obs_info->name_attr()); +s = check_hdr_str(conf_key_obs_var, obs_info->name_attr()); table.set_entry(row, c++, s.text()); // obs units -s = check_hdr_str(obs_info->units_attr(), true); +s = check_hdr_str(conf_key_obs_units, obs_info->units_attr(), true); table.set_entry(row, c++, s.text()); // obs level -s = check_hdr_str(obs_info->level_attr(), true); +s = check_hdr_str(conf_key_obs_lev, obs_info->level_attr(), true); table.set_entry(row, c++, s.text()); diff --git a/test/config/STATAnalysisConfig_APCP_HIRA b/test/config/STATAnalysisConfig_APCP_HIRA index 22faf3ae7a..e76c4a8ffc 100644 --- a/test/config/STATAnalysisConfig_APCP_HIRA +++ b/test/config/STATAnalysisConfig_APCP_HIRA @@ -98,6 +98,15 @@ boot = { //////////////////////////////////////////////////////////////////////////////// +// +// Skill score index options +// +ss_index_name = "SS_INDEX"; +ss_index_vld_thresh = 1.0; + +//////////////////////////////////////////////////////////////////////////////// + +hss_ec_value = NA; rank_corr_flag = TRUE; vif_flag = FALSE; tmp_dir = "/tmp"; diff --git a/test/config/STATAnalysisConfig_SFC_SS_Index b/test/config/STATAnalysisConfig_SFC_SS_Index new file mode 100644 index 0000000000..ca08d2565c --- /dev/null +++ b/test/config/STATAnalysisConfig_SFC_SS_Index @@ -0,0 +1,112 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// STAT-Analysis configuration file used to compute a Custom Skill Score Index. +// +//////////////////////////////////////////////////////////////////////////////// + +// +// Filtering input STAT lines by the contents of each column +// +model = [ "AFWAv3.4_Noahv3.3", "AFWAv3.4_Noahv2.7.1" ]; + +fcst_lead = [ "12", "24", "36", "48", + "12", "24", "36", "48", + "12", "24", "36", "48", + "12", "24", "36", "48" + ]; +obs_lead = []; + +fcst_valid_beg = ""; +fcst_valid_end = ""; +fcst_valid_inc = []; +fcst_valid_exc = []; +fcst_valid_hour = []; + +obs_valid_beg = ""; +obs_valid_end = ""; +obs_valid_inc = []; +obs_valid_exc = []; +obs_valid_hour = []; + +fcst_init_beg = ""; +fcst_init_end = ""; +fcst_init_inc = []; +fcst_init_exc = []; +fcst_init_hour = []; + +obs_init_beg = ""; +obs_init_end = ""; +obs_init_inc = []; +obs_init_exc = []; +obs_init_hour = []; + +fcst_var = [ "WIND", "WIND", "WIND", "WIND", + "DPT", "DPT", "DPT", "DPT", + "TMP", "TMP", "TMP", "TMP", + "PRMSL", "PRMSL", "PRMSL", "PRMSL" + ]; +obs_var = []; + +fcst_lev = [ "Z10", "Z10", "Z10", "Z10", + "Z2", "Z2", "Z2", "Z2", + "Z2", "Z2", "Z2", "Z2", + "Z0", "Z0", "Z0", "Z0" + ]; +obs_lev = []; + +obtype = []; + +vx_mask = []; + +interp_mthd = []; + +interp_pnts = []; + +fcst_thresh = []; +obs_thresh = []; +cov_thresh = []; + +alpha = []; + +line_type = [ "SL1L2" ]; + +column = [ "RMSE" ]; + +weight = [ 4.0, 3.0, 2.0, 1.0, + 4.0, 3.0, 2.0, 1.0, + 4.0, 3.0, 2.0, 1.0, + 4.0, 3.0, 2.0, 1.0 + ]; + +//////////////////////////////////////////////////////////////////////////////// + +// +// Confidence interval settings +// +out_alpha = 0.05; + +boot = { + interval = PCTILE; + rep_prop = 1.0; + n_rep = 0; + rng = "mt19937"; + seed = ""; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Skill score index options +// +ss_index_name = "SS_INDEX"; +ss_index_vld_thresh = 1.0; + +//////////////////////////////////////////////////////////////////////////////// + +hss_ec_value = NA; +rank_corr_flag = FALSE; +vif_flag = FALSE; +tmp_dir = "/tmp"; +version = "V10.1.0"; + +//////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/STATAnalysisConfig_climo b/test/config/STATAnalysisConfig_climo index d316900db6..608bd3b255 100644 --- a/test/config/STATAnalysisConfig_climo +++ b/test/config/STATAnalysisConfig_climo @@ -104,6 +104,15 @@ wmo_fisher_stats = [ "CNT:PR_CORR", "CNT:SP_CORR", //////////////////////////////////////////////////////////////////////////////// +// +// Skill score index options +// +ss_index_name = "SS_INDEX"; +ss_index_vld_thresh = 1.0; + +//////////////////////////////////////////////////////////////////////////////// + +hss_ec_value = NA; rank_corr_flag = FALSE; vif_flag = FALSE; tmp_dir = "/tmp"; diff --git a/test/config/STATAnalysisConfig_filter_times b/test/config/STATAnalysisConfig_filter_times index 8a9d7afcb4..6af000732f 100644 --- a/test/config/STATAnalysisConfig_filter_times +++ b/test/config/STATAnalysisConfig_filter_times @@ -101,6 +101,15 @@ boot = { //////////////////////////////////////////////////////////////////////////////// +// +// Skill score index options +// +ss_index_name = "SS_INDEX"; +ss_index_vld_thresh = 1.0; + +//////////////////////////////////////////////////////////////////////////////// + +hss_ec_value = NA; rank_corr_flag = TRUE; vif_flag = FALSE; tmp_dir = "/tmp"; diff --git a/test/config/STATAnalysisConfig_grid_stat b/test/config/STATAnalysisConfig_grid_stat index 1453703dfc..3365bf5f24 100644 --- a/test/config/STATAnalysisConfig_grid_stat +++ b/test/config/STATAnalysisConfig_grid_stat @@ -94,6 +94,15 @@ boot = { //////////////////////////////////////////////////////////////////////////////// +// +// Skill score index options +// +ss_index_name = "SS_INDEX"; +ss_index_vld_thresh = 1.0; + +//////////////////////////////////////////////////////////////////////////////// + +hss_ec_value = NA; rank_corr_flag = TRUE; vif_flag = FALSE; tmp_dir = "/tmp"; diff --git a/test/config/STATAnalysisConfig_point_stat b/test/config/STATAnalysisConfig_point_stat index d102f40825..82a68fbaf6 100644 --- a/test/config/STATAnalysisConfig_point_stat +++ b/test/config/STATAnalysisConfig_point_stat @@ -123,6 +123,15 @@ boot = { //////////////////////////////////////////////////////////////////////////////// +// +// Skill score index options +// +ss_index_name = "SS_INDEX"; +ss_index_vld_thresh = 1.0; + +//////////////////////////////////////////////////////////////////////////////// + +hss_ec_value = NA; rank_corr_flag = TRUE; vif_flag = FALSE; tmp_dir = "/tmp"; diff --git a/test/config/STATAnalysisConfig_ramps b/test/config/STATAnalysisConfig_ramps index 5a5d06e424..aca6de0045 100644 --- a/test/config/STATAnalysisConfig_ramps +++ b/test/config/STATAnalysisConfig_ramps @@ -93,6 +93,15 @@ boot = { //////////////////////////////////////////////////////////////////////////////// +// +// Skill score index options +// +ss_index_name = "SS_INDEX"; +ss_index_vld_thresh = 1.0; + +//////////////////////////////////////////////////////////////////////////////// + +hss_ec_value = NA; rank_corr_flag = TRUE; vif_flag = FALSE; tmp_dir = "/tmp"; diff --git a/test/hdr/met_10_1.hdr b/test/hdr/met_10_1.hdr index ba80ba12b8..641ac25813 100644 --- a/test/hdr/met_10_1.hdr +++ b/test/hdr/met_10_1.hdr @@ -29,6 +29,7 @@ VL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_L VAL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL UFABAR VFABAR UOABAR VOABAR UVFOABAR UVFFABAR UVOOABAR VCNT : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FBAR FBAR_BCL FBAR_BCU OBAR OBAR_BCL OBAR_BCU FS_RMS FS_RMS_BCL FS_RMS_BCU OS_RMS OS_RMS_BCL OS_RMS_BCU MSVE MSVE_BCL MSVE_BCU RMSVE RMSVE_BCL RMSVE_BCU FSTDEV FSTDEV_BCL FSTDEV_BCU OSTDEV OSTDEV_BCL OSTDEV_BCU FDIR FDIR_BCL FDIR_BCU ODIR ODIR_BCL ODIR_BCU FBAR_SPEED FBAR_SPEED_BCL FBAR_SPEED_BCU OBAR_SPEED OBAR_SPEED_BCL OBAR_SPEED_BCU VDIFF_SPEED VDIFF_SPEED_BCL VDIFF_SPEED_BCU VDIFF_DIR VDIFF_DIR_BCL VDIFF_DIR_BCU SPEED_ERR SPEED_ERR_BCL SPEED_ERR_BCU SPEED_ABSERR SPEED_ABSERR_BCL SPEED_ABSERR_BCU DIR_ERR DIR_ERR_BCL DIR_ERR_BCU DIR_ABSERR DIR_ABSERR_BCL DIR_ABSERR_BCU GENMPR : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL INDEX STORM_ID AGEN_INIT AGEN_FHR AGEN_LAT AGEN_LON AGEN_DLAND BGEN_LAT BGEN_LON BGEN_DLAND GEN_DIST GEN_TDIFF INIT_TDIFF DEV_CAT OPS_CAT +SSIDX : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE FCST_MODEL REF_MODEL N_INIT N_TERM N_VLD SS_INDEX MODE_SOA : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE N_VALID GRID_RES OBJECT_ID OBJECT_CAT CENTROID_X CENTROID_Y CENTROID_LAT CENTROID_LON AXIS_ANG LENGTH WIDTH AREA AREA_THRESH CURVATURE CURVATURE_X CURVATURE_Y COMPLEXITY INTENSITY_10 INTENSITY_25 INTENSITY_50 INTENSITY_75 INTENSITY_90 INTENSITY_50 INTENSITY_SUM MODE_POA : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE N_VALID GRID_RES OBJECT_ID OBJECT_CAT CENTROID_DIST BOUNDARY_DIST CONVEX_HULL_DIST ANGLE_DIFF ASPECT_DIFF AREA_RATIO INTERSECTION_AREA UNION_AREA SYMMETRIC_DIFF INTERSECTION_OVER_AREA CURVATURE_RATIO COMPLEXITY_RATIO PERCENTILE_INTENSITY_RATIO INTEREST MODE_CTS : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE N_VALID GRID_RES FIELD TOTAL FY_OY FY_ON FN_OY FN_ON BASER FMEAN ACC FBIAS PODY PODN POFD FAR CSI GSS HK HSS ODDS diff --git a/test/xml/unit_ref_config.xml b/test/xml/unit_ref_config.xml index 4e7e26113b..648da522a9 100644 --- a/test/xml/unit_ref_config.xml +++ b/test/xml/unit_ref_config.xml @@ -953,4 +953,41 @@
+ + + + + + &MET_BIN;/stat_analysis + \ + -lookin &OUTPUT_DIR;/ref_config/point_stat/AFWAv3.4_Noahv3.3/ \ + -lookin &OUTPUT_DIR;/ref_config/point_stat/AFWAv3.4_Noahv2.7.1/ \ + -job go_index \ + -by FCST_INIT_BEG,VX_MASK,OBTYPE -set_hdr DESC Noahv3.3_vs_v2.7.1 \ + -model AFWAv3.4_Noahv3.3,AFWAv3.4_Noahv2.7.1 -ss_index_vld_thresh 0.5 \ + -out_stat &OUTPUT_DIR;/ref_config/stat_analysis/go_index_by_option.stat + + + &OUTPUT_DIR;/ref_config/stat_analysis/go_index_by_option.stat + + + + + + + + + &MET_BIN;/stat_analysis + \ + -lookin &OUTPUT_DIR;/ref_config/point_stat/AFWAv3.4_Noahv3.3/ \ + -lookin &OUTPUT_DIR;/ref_config/point_stat/AFWAv3.4_Noahv2.7.1/ \ + -job ss_index -config &CONFIG_DIR;/STATAnalysisConfig_SFC_SS_Index \ + -by FCST_INIT_BEG,VX_MASK,OBTYPE \ + -out_stat &OUTPUT_DIR;/ref_config/stat_analysis/sfc_ss_index_by_option.stat + + + &OUTPUT_DIR;/ref_config/stat_analysis/sfc_ss_index_by_option.stat + + + From d7ca364cc5ded30375073d587669db3c99cd0bb3 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Mon, 30 Aug 2021 22:28:50 -0600 Subject: [PATCH 131/200] #1855 Initialize AllocInc --- met/src/basic/vx_log/concat_string.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/met/src/basic/vx_log/concat_string.cc b/met/src/basic/vx_log/concat_string.cc index d325f0ad8c..d35497884c 100644 --- a/met/src/basic/vx_log/concat_string.cc +++ b/met/src/basic/vx_log/concat_string.cc @@ -236,6 +236,7 @@ void ConcatString::assign(const ConcatString & c) memcpy(FloatFormat, c.FloatFormat, sizeof(FloatFormat)); Precision = c.Precision; + AllocInc = c.AllocInc; } From 0d322f2b203b0558d95ba9e188c7907ea561ad8d Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Mon, 30 Aug 2021 22:30:04 -0600 Subject: [PATCH 132/200] 855 call snprintf instead of sprintf --- met/src/tools/other/point2grid/point2grid.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/met/src/tools/other/point2grid/point2grid.cc b/met/src/tools/other/point2grid/point2grid.cc index fe96df2d11..9dd321221d 100644 --- a/met/src/tools/other/point2grid/point2grid.cc +++ b/met/src/tools/other/point2grid/point2grid.cc @@ -714,14 +714,15 @@ void process_point_file(NcFile *nc_in, MetConfig &config, VarInfo *vinfo, } } else { - char grib_code[128]; + const int TMP_BUF_LEN = 128; + char grib_code[TMP_BUF_LEN + 1]; var_idx_or_gc = atoi(vname.c_str()); - sprintf(grib_code, "%d", var_idx_or_gc); + snprintf(grib_code, TMP_BUF_LEN, "%d", var_idx_or_gc); if (vname != grib_code) { ConcatString var_id = conf_info.get_var_id(vname); if( var_id.nonempty() ) { var_idx_or_gc = atoi(var_id.c_str()); - sprintf(grib_code, "%d", var_idx_or_gc); + snprintf(grib_code, TMP_BUF_LEN, "%d", var_idx_or_gc); } else { exit_by_field_name_error = true; From c099f60b74d1461db5922c7bcf014672e1b43e73 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Mon, 30 Aug 2021 23:00:51 -0600 Subject: [PATCH 133/200] Avoid the same for loops (SobarQube warns this) --- .../tools/other/mode_time_domain/mm_engine.cc | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/met/src/tools/other/mode_time_domain/mm_engine.cc b/met/src/tools/other/mode_time_domain/mm_engine.cc index 6daf8b7e96..be20d78f2d 100644 --- a/met/src/tools/other/mode_time_domain/mm_engine.cc +++ b/met/src/tools/other/mode_time_domain/mm_engine.cc @@ -190,7 +190,7 @@ void MM_Engine::do_match_merge() { -int j, k, n; +int j, k; int f_i, o_i; @@ -234,8 +234,8 @@ for (j=0; j<(graph.n_fcst()); ++j) { const EquivalenceClass * eq = 0; - N_Composites = 0; +IntArray index_list; for (j=0; j<(part.n_elements()); ++j) { @@ -243,21 +243,22 @@ for (j=0; j<(part.n_elements()); ++j) { if ( eq->n_elements() <= 1 ) continue; + index_list.add(j); + ++N_Composites; } // for j -if ( N_Composites > 0 ) comp_to_eq = new int [N_Composites]; +if ( N_Composites > 0 ) { -n = 0; + if ( comp_to_eq ) delete [] comp_to_eq; + comp_to_eq = new int [index_list.n()]; -for (j=0; j<(part.n_elements()); ++j) { + for (j=0; jn_elements() <= 1 ) continue; - - comp_to_eq[n++] = j; + comp_to_eq[j] = index_list[j]; + + } } From 868ab7d2639a505d348920faff06a43b256d02e3 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Mon, 30 Aug 2021 23:12:24 -0600 Subject: [PATCH 134/200] #1855 Checking the minimum rows (3) for formatting. Initialize left & right array --- met/src/basic/vx_util/ascii_table.cc | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/met/src/basic/vx_util/ascii_table.cc b/met/src/basic/vx_util/ascii_table.cc index 910e5165d9..3f35edb749 100644 --- a/met/src/basic/vx_util/ascii_table.cc +++ b/met/src/basic/vx_util/ascii_table.cc @@ -1319,6 +1319,13 @@ if ( Nrows < 0 || Nrows >= INT_MAX ) { exit ( 1 ); } + // + // Line up the decimals in the data starting in row 2. + // For two or fewer rows, there is no work to do. + // + +if ( Nrows <= 2 ) return; + int left[Nrows]; int right[Nrows]; @@ -1327,23 +1334,24 @@ int max_left, max_right; const char fill_char = ' '; const int r_start = 1; // skip the header row + +for (r=0; r max_left ) max_left = left[r]; if ( right [r] > max_right ) max_right = right[r]; From 30ce2e5873eb83b1d17427df96b7a39c95c462f6 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Mon, 30 Aug 2021 23:15:52 -0600 Subject: [PATCH 135/200] #1855 Removed the unreachable return statement --- met/src/basic/vx_util/command_line.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/met/src/basic/vx_util/command_line.cc b/met/src/basic/vx_util/command_line.cc index 01a90bcb40..0b5d48fbd4 100644 --- a/met/src/basic/vx_util/command_line.cc +++ b/met/src/basic/vx_util/command_line.cc @@ -730,7 +730,7 @@ for (j=0; j Date: Mon, 30 Aug 2021 23:20:11 -0600 Subject: [PATCH 136/200] #1855 Avoide out of index for v_miss --- met/src/libcode/vx_data2d_grib2/data2d_grib2.cc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc b/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc index 799b7cfb80..5cb7cbf6d3 100644 --- a/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc +++ b/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc @@ -1290,7 +1290,8 @@ bool MetGrib2DataFile::read_grib2_record_data_plane(Grib2Record *rec, // attempt to read the record gribfield *gfld; g2int numfields; - float v, v_miss[2]; + const int max_miss = 2; + float v, v_miss[max_miss]; int n_miss, i; if( -1 == read_grib2_record(rec->ByteOffset, 1, rec->FieldNum, gfld, numfields) ){ @@ -1321,6 +1322,12 @@ bool MetGrib2DataFile::read_grib2_record_data_plane(Grib2Record *rec, // get the missing data value(s), if specified g2_miss(gfld, v_miss, &n_miss); + int miss_count = n_miss; + if(miss_count > max_miss) { + miss_count = max_miss; + mlog << Warning << "\nMetGrib2DataFile::data_plane() -> " + << "Ignored " << (n_miss-max_miss) << " v_miss.\n\n"; + } // copy the data into the data plane buffer for(int x=0; x < n_x; x++){ @@ -1351,7 +1358,7 @@ bool MetGrib2DataFile::read_grib2_record_data_plane(Grib2Record *rec, (float)gfld->fld[idx_data] : bad_data_float); // check missing data values, if specified - for(i=0; i < n_miss; i++) { + for(i=0; i < miss_count; i++) { if(is_eq(v, v_miss[i])) { v = bad_data_float; break; } } @@ -1378,7 +1385,7 @@ bool MetGrib2DataFile::read_grib2_record_data_plane(Grib2Record *rec, << " lead time: " << sec_to_hhmmss(rec->LeadTime) << "\n" << " init time: " << unix_to_yyyymmdd_hhmmss(rec->InitTime) << "\n" << " bitmap flag: " << gfld->ibmap << "\n"; - for(i=0; i < n_miss; i++) { + for(i=0; i < miss_count; i++) { mlog << Debug(4) << " missing val(" << i+1 << "): " << v_miss[i] << "\n"; } From ae6a6c20b1877bd2fadfbc4dc6c6dfc46ee73999 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Mon, 30 Aug 2021 23:33:31 -0600 Subject: [PATCH 137/200] #1855 Keep buf_size for for-loop (avoid changing it in for loop). The buffer size for strncpy is decided by the targetbuffer size or the input length, not the existing data at the target buffer. The size of existing data at the target buffer is used to erase the previous data --- met/src/libcode/vx_nc_obs/nc_obs_util.cc | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/met/src/libcode/vx_nc_obs/nc_obs_util.cc b/met/src/libcode/vx_nc_obs/nc_obs_util.cc index 805461b078..f545ea0690 100644 --- a/met/src/libcode/vx_nc_obs/nc_obs_util.cc +++ b/met/src/libcode/vx_nc_obs/nc_obs_util.cc @@ -997,10 +997,10 @@ void NetcdfObsVars::read_pb_hdr_data(NcHeaderData &hdr_data) { int *hdr_irpt_typ_block = new int[buf_size]; int *hdr_inst_typ_block = new int[buf_size]; for(int i_start=0; i_start NC_BUFFER_SIZE_32K) buf_size = NC_BUFFER_SIZE_32K; + int buf_size2 = pb_hdr_count - i_start; + if (buf_size2 > NC_BUFFER_SIZE_32K) buf_size2 = NC_BUFFER_SIZE_32K; offsets[0] = i_start; - lengths[0] = buf_size; + lengths[0] = buf_size2; if (has_hdr_prpt_typ_var) { // Get the corresponding header PB message type (string) @@ -1032,7 +1032,7 @@ void NetcdfObsVars::read_pb_hdr_data(NcHeaderData &hdr_data) { } } - for (int hIndex = 0; hIndex < buf_size; hIndex++) { + for (int hIndex = 0; hIndex < buf_size2; hIndex++) { hdr_data.prpt_typ_array.add(hdr_prpt_typ_block[hIndex]); hdr_data.irpt_typ_array.add(hdr_irpt_typ_block[hIndex]); hdr_data.inst_typ_array.add(hdr_inst_typ_block[hIndex]); @@ -1389,17 +1389,16 @@ int write_nc_string_array (NcVar *ncVar, StringArray &strArray, const int str_le int buf_index = 0; int processed_count = 0; for (int index=0; index str_len) len_n = str_len; + strncpy(data_buf[buf_index], string_data.c_str(), len_n); + for (int idx=len_n; idx= buf_size) { From e94048be9ce390b9d40ee2c9c4f81a4b2f4c87fd Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Mon, 30 Aug 2021 23:37:29 -0600 Subject: [PATCH 138/200] #1855 Make sure the variuble c has enough data to avoid out of index error --- met/src/libcode/vx_ps/vx_ps.cc | 64 ++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/met/src/libcode/vx_ps/vx_ps.cc b/met/src/libcode/vx_ps/vx_ps.cc index 668efdbaba..f7d12def88 100644 --- a/met/src/libcode/vx_ps/vx_ps.cc +++ b/met/src/libcode/vx_ps/vx_ps.cc @@ -1781,37 +1781,41 @@ if ( j < 0 ) { AfmCharMetrics & cm = afm.cm[j]; - // - // ligature? - // - -LigatureInfo lig; - -if ( c[1] && afm.has_ligature(c[0], c[1], lig) ) { - - handle_ligature(lig, afm, cur); - - c += 2; - - return; - -} - - // - // is it the start of a kern pair? - // - -KPX kp; - -if ( c[1] && afm.has_kern_pair(c[0], c[1], kp) ) { - - cur->add_char(cm); - - handle_kern_pair(kp, afm, cur); - - ++c; +if (strlen(c) > 1) { - return; + // + // ligature? + // + + LigatureInfo lig; + + if ( c[1] && afm.has_ligature(c[0], c[1], lig) ) { + + handle_ligature(lig, afm, cur); + + c += 2; + + return; + + } + + // + // is it the start of a kern pair? + // + + KPX kp; + + if ( c[1] && afm.has_kern_pair(c[0], c[1], kp) ) { + + cur->add_char(cm); + + handle_kern_pair(kp, afm, cur); + + ++c; + + return; + + } } From fb843daabe6c6803915fb1fc2dfa49b1a6d4eb8a Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Mon, 30 Aug 2021 23:41:02 -0600 Subject: [PATCH 139/200] #1855 nake sure the index is in range (avoid out of index error) --- met/src/libcode/vx_statistics/contable.cc | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/met/src/libcode/vx_statistics/contable.cc b/met/src/libcode/vx_statistics/contable.cc index 22f4caec7a..02f4f177a3 100644 --- a/met/src/libcode/vx_statistics/contable.cc +++ b/met/src/libcode/vx_statistics/contable.cc @@ -354,14 +354,21 @@ for (c=1; c " + << "c_table (" << c_table << ") is greater then w (" << w << ")\n\n"; + } } @@ -1745,7 +1752,8 @@ return ( t ); //////////////////////////////////////////////////////////////////////// - +// r_table < h +// c_table < w int table_rc_to_n(int r_table, int c_table, int w, int h) From 56ec1bfc6a11fcd681144f2a691789d374b0361c Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Mon, 30 Aug 2021 23:43:05 -0600 Subject: [PATCH 140/200] #1855 Make sure no negative offset for s array --- met/src/libcode/vx_tc_util/atcf_line_base.cc | 46 +++++++++++--------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/met/src/libcode/vx_tc_util/atcf_line_base.cc b/met/src/libcode/vx_tc_util/atcf_line_base.cc index c4fca4e38e..42e8d199e3 100644 --- a/met/src/libcode/vx_tc_util/atcf_line_base.cc +++ b/met/src/libcode/vx_tc_util/atcf_line_base.cc @@ -402,16 +402,19 @@ double parse_lat(const char *s) { v = parse_int(s); // Convert tenths of a degree to degrees - switch(s[strlen(s) - 1]) { - case 'N': v *= 0.1; break; - case 'S': v *= -0.1; break; // Degrees south is negative - default: - mlog << Warning - << "\nint parse_lat(const char *) -> " - << "bad latitude ... \"" << s - << "\"\n\n"; - v = bad_data_double; - break; + int buf_len = strlen(s); + if (buf_len > 0) { + switch(s[buf_len - 1]) { + case 'N': v *= 0.1; break; + case 'S': v *= -0.1; break; // Degrees south is negative + default: + mlog << Warning + << "\nint parse_lat(const char *) -> " + << "bad latitude ... \"" << s + << "\"\n\n"; + v = bad_data_double; + break; + } } // Range check @@ -428,16 +431,19 @@ double parse_lon(const char *s) { v = parse_int(s); // Convert tenths of a degree to degrees - switch(s[strlen(s) - 1]) { - case 'E': v *= 0.1; break; - case 'W': v *= -0.1; break; // Degrees west is negative - default: - mlog << Warning - << "\nint parse_lon(const char *) -> " - << "bad longitude ... \"" << s - << "\"\n\n"; - v = bad_data_double; - break; + int buf_len = strlen(s); + if (buf_len > 0) { + switch(s[buf_len - 1]) { + case 'E': v *= 0.1; break; + case 'W': v *= -0.1; break; // Degrees west is negative + default: + mlog << Warning + << "\nint parse_lon(const char *) -> " + << "bad longitude ... \"" << s + << "\"\n\n"; + v = bad_data_double; + break; + } } // Range check From ee6e4c6876b8ae5c3c72be6b5456bdbd17ac9440 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Mon, 30 Aug 2021 23:49:55 -0600 Subject: [PATCH 141/200] #1855 Allocated line before calling getline'. Simplify the code to check the first level only. Check pbl_level before provcessing --- met/src/tools/other/pb2nc/pb2nc.cc | 217 ++++++++++++++--------------- 1 file changed, 108 insertions(+), 109 deletions(-) diff --git a/met/src/tools/other/pb2nc/pb2nc.cc b/met/src/tools/other/pb2nc/pb2nc.cc index a374bfc6f0..d6e64eff51 100644 --- a/met/src/tools/other/pb2nc/pb2nc.cc +++ b/met/src/tools/other/pb2nc/pb2nc.cc @@ -636,7 +636,7 @@ void get_variable_info(const char* tbl_filename) { FILE * fp; char * line = NULL; - size_t len = 0; + size_t len = 1024; ssize_t read; event_names.clear(); @@ -655,6 +655,12 @@ void get_variable_info(const char* tbl_filename) { char var_unit_str[BUFR_UNIT_LEN+1]; bool find_mnemonic = false; + line = (char *)malloc(len * sizeof(char)); + if( line == NULL) { + mlog << Error << "\n" << method_name << " -> " + << "Unable to allocate buffer\n\n"; + exit(1); + } // Processing section 1 int var_count1 = 0; while ((read = getline(&line, &len, fp)) != -1) { @@ -1314,7 +1320,6 @@ void process_pbfile(int i_pb) { // Search through the vertical levels for(lv=0, n_hdr_obs = 0; lv variable \"" << bufr_var_name <<"\" does not exist at BUFR file\n\n"; @@ -2293,28 +2297,17 @@ void process_pbfile_metadata(int i_pb) { readpbint_(&unit, &i_ret, &nlev2, bufr_obs, (char*)var_name.c_str(), &var_name_len, &tmp_nlev_max_req); if (0 >= nlev2) continue; - // Search through the vertical levels - buf_nlev = nlev2; - if (nlev2 > mxr8lv) buf_nlev = mxr8lv; - has_valid_data = false; - int count = 0; - for(lv=0; lv pqtzuv_map_tq, << " from TQ (" << tq_count << ") and UV (" << uv_count << ")\n"; - // Order all observations by pressure from bottom to top - index = pbl_level - 1; - hgt_cnt = spfh_cnt = 0; - for (it=pqtzuv_map_merged.begin(); it!=pqtzuv_map_merged.end(); ++it) { - if (index < 0) { - mlog << Error << "\n" << method_name << "negative index: " << index << "\n\n"; - break; - } - - if (index < MAX_PBL_LEVEL) { - float *pqtzuv = it->second; - pbl_data_pres[index] = pqtzuv[0]; - pbl_data_spfh[index] = pqtzuv[1]; - pbl_data_temp[index] = pqtzuv[2]; - pbl_data_hgt[index] = pqtzuv[3]; - pbl_data_ugrd[index] = pqtzuv[4]; - pbl_data_vgrd[index] = pqtzuv[5]; - if (!is_eq(pbl_data_spfh[index], bad_data_float)) spfh_cnt++; - if (!is_eq(pbl_data_hgt[index], bad_data_float)) hgt_cnt++; - selected_levels.add(nint(it->first)); - } - - index--; + if (pbl_level <= 0) { + mlog << Warning << "\n" << method_name + << "Skip CALPBL because an empty list after combining TQZ and UV\n\n"; } - if (index != -1) { - mlog << Error << "\n" << method_name << "Missing some levels (" << index << ")\n"; - } - - if (pbl_level > MAX_PBL_LEVEL) { - it = pqtzuv_map_tq.begin(); - // Find vertical levels with both data - float highest_pressure = bad_data_float; - for (; it!=pqtzuv_map_tq.end(); ++it) { - if (pqtzuv_map_uv.count(it->first) > 0) { - highest_pressure = it->first; + else { + // Order all observations by pressure from bottom to top + index = pbl_level - 1; + hgt_cnt = spfh_cnt = 0; + for (it=pqtzuv_map_merged.begin(); it!=pqtzuv_map_merged.end(); ++it) { + if (index < 0) { + mlog << Error << "\n" << method_name << "negative index: " << index << "\n\n"; break; } - } - if (!is_eq(highest_pressure, bad_data_float)) { - index = MAX_PBL_LEVEL - 1; - for (; it!=pqtzuv_map_tq.end(); ++it) { - int pres_level = nint(it->first); - if (selected_levels.has(pres_level)) break; - - float *pqtzuv = pqtzuv_map_merged[it->first]; + + if (index < MAX_PBL_LEVEL) { + float *pqtzuv = it->second; pbl_data_pres[index] = pqtzuv[0]; pbl_data_spfh[index] = pqtzuv[1]; pbl_data_temp[index] = pqtzuv[2]; pbl_data_hgt[index] = pqtzuv[3]; pbl_data_ugrd[index] = pqtzuv[4]; pbl_data_vgrd[index] = pqtzuv[5]; - mlog << Debug(5) << method_name << "Force to add " - << pres_level << " into " << index << "\n"; - index--; + if (!is_eq(pbl_data_spfh[index], bad_data_float)) spfh_cnt++; + if (!is_eq(pbl_data_hgt[index], bad_data_float)) hgt_cnt++; + selected_levels.add(nint(it->first)); } + + index--; + } + if (index != -1) { + mlog << Error << "\n" << method_name << "Missing some levels (" << index << ")\n"; + } + + if (pbl_level > MAX_PBL_LEVEL) { + it = pqtzuv_map_tq.begin(); + // Find vertical levels with both data + float highest_pressure = bad_data_float; + for (; it!=pqtzuv_map_tq.end(); ++it) { + if (pqtzuv_map_uv.count(it->first) > 0) { + highest_pressure = it->first; + break; + } + } + if (!is_eq(highest_pressure, bad_data_float)) { + index = MAX_PBL_LEVEL - 1; + for (; it!=pqtzuv_map_tq.end(); ++it) { + int pres_level = nint(it->first); + if (selected_levels.has(pres_level)) break; + + float *pqtzuv = pqtzuv_map_merged[it->first]; + pbl_data_pres[index] = pqtzuv[0]; + pbl_data_spfh[index] = pqtzuv[1]; + pbl_data_temp[index] = pqtzuv[2]; + pbl_data_hgt[index] = pqtzuv[3]; + pbl_data_ugrd[index] = pqtzuv[4]; + pbl_data_vgrd[index] = pqtzuv[5]; + mlog << Debug(5) << method_name << "Force to add " + << pres_level << " into " << index << "\n"; + index--; + } + } + } + else { + // Clear buffer + for (int idx=pbl_level; idx0) && (pbl_level>0)) { + mzbl = pbl_level; + mlog << Debug(PBL_DEBUG_LEVEL) << method_name << "mzbl: " << mzbl + << " missing count: Q: " << (pbl_level - spfh_cnt) + << ", Z: " << (pbl_level - hgt_cnt) << "\n\n"; + if(mlog.verbosity_level() >= PBL_DEBUG_LEVEL) { + log_pbl_input(pbl_level, method_name); + } + + //SUBROUTINE CALPBL(T,Q,P,Z,U,V,MZBL,HPBL,jpbl) + calpbl_(pbl_data_temp, pbl_data_spfh, pbl_data_pres, pbl_data_hgt, + pbl_data_ugrd, pbl_data_vgrd, &mzbl, &hpbl, &jpbl); + if (is_eq(hpbl, bad_data_float)) + mlog << Debug(5) << method_name << " fail to compute PBL. TQ records: " + << tq_count << " UV records: " << uv_count << " merged records: " + << pqtzuv_map_merged.size() << "\n"; } - } - else { - // Clear buffer - for (int idx=pbl_level; idx0) && (pbl_level>0)) { - mzbl = pbl_level; - mlog << Debug(PBL_DEBUG_LEVEL) << method_name << "mzbl: " << mzbl - << " missing count: Q: " << (pbl_level - spfh_cnt) - << ", Z: " << (pbl_level - hgt_cnt) << "\n\n"; - if(mlog.verbosity_level() >= PBL_DEBUG_LEVEL) { - log_pbl_input(pbl_level, method_name); - } - - //SUBROUTINE CALPBL(T,Q,P,Z,U,V,MZBL,HPBL,jpbl) - calpbl_(pbl_data_temp, pbl_data_spfh, pbl_data_pres, pbl_data_hgt, - pbl_data_ugrd, pbl_data_vgrd, &mzbl, &hpbl, &jpbl); - if (is_eq(hpbl, bad_data_float)) - mlog << Debug(5) << method_name << " fail to compute PBL. TQ records: " - << tq_count << " UV records: " << uv_count << " merged records: " - << pqtzuv_map_merged.size() << "\n"; } } return hpbl; From 955a8cac1de245a04c00c8ffcc03a8ed3afae3c5 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Mon, 30 Aug 2021 23:55:12 -0600 Subject: [PATCH 142/200] #1855 Added m_strlen, m_strcpy, m_strcpy2, and m_strncpy --- met/src/basic/vx_util/string_fxns.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/met/src/basic/vx_util/string_fxns.h b/met/src/basic/vx_util/string_fxns.h index 93b3973fd4..b64edbbb86 100644 --- a/met/src/basic/vx_util/string_fxns.h +++ b/met/src/basic/vx_util/string_fxns.h @@ -59,6 +59,14 @@ extern ConcatString str_trim(const ConcatString str); extern int parse_thresh_index(const char *str); +extern int m_strlen(const char *str); + +extern void m_strcpy(char *to_str, const char *from_str, const char *method_name, + const char *extra_msg=(char *)0); +extern char *m_strcpy2(const char *from_str, const char *method_name, + const char *extra_msg=(char *)0); +extern void m_strncpy(char *to_str, const char *from_str, const int buf_len, + const char *method_name, const char *extra_msg=(char *)0); //////////////////////////////////////////////////////////////////////// From 116c4e2e14d7650408e8115a87eadf19c8cb98e2 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Mon, 30 Aug 2021 23:55:24 -0600 Subject: [PATCH 143/200] #1855 Added m_strlen, m_strcpy, m_strcpy2, and m_strncpy> Check if null pointer --- met/src/basic/vx_util/string_fxns.cc | 166 +++++++++++++++++++++------ 1 file changed, 133 insertions(+), 33 deletions(-) diff --git a/met/src/basic/vx_util/string_fxns.cc b/met/src/basic/vx_util/string_fxns.cc index 7b8ea2114a..ff575d3757 100644 --- a/met/src/basic/vx_util/string_fxns.cc +++ b/met/src/basic/vx_util/string_fxns.cc @@ -31,6 +31,8 @@ using namespace std; #include "vx_log.h" +const bool ENHANCE_STR_APIS = false; + //////////////////////////////////////////////////////////////////////// @@ -112,21 +114,20 @@ const char * get_short_name(const char * path) { -if ( !path ) return ( (const char *) 0 ); - -int j; const char * short_name = (const char *) 0; +if ( path ) { + int j; -j = strlen(path) - 1; + j = strlen(path) - 1; -while ( (j >= 0) && (path[j] != '/') ) --j; + while ( (j >= 0) && (path[j] != '/') ) --j; -++j; - -short_name = path + j; + ++j; + short_name = path + j; +} return ( short_name ); @@ -190,39 +191,41 @@ int num_tokens(const char *test_str, const char *separator) int n; char *temp_str = (char *) 0; char *c = (char *) 0; + const char *method_name = "num_tokens() -> "; // // Check for an empty string // - if(strlen(test_str) <= 0) return(0); + if(!test_str) return(0); + + int buf_len = strlen(test_str); + if(buf_len <= 0) return(0); // // Initialize the temp string for use in tokenizing // - temp_str = new char[strlen(test_str) + 1]; + temp_str = m_strcpy2(test_str, method_name); + if (temp_str) { + + // + // Compute the number of tokens in the string + // + //c = strtok(temp_str1.c_str(), separator); + c = strtok(temp_str, separator); + + // + // Check for an empty string + // + if(!c) { delete [] temp_str; temp_str = 0; return(0); } + else n = 1; + + // + // Parse remaining tokens + // + // + while((c = strtok(0, separator)) != NULL) n++; - if(!temp_str) { - mlog << Error << "\nnum_tokens() -> " - << "memory allocation error\n\n"; - exit(1); } - strcpy(temp_str, test_str); - - // - // Compute the number of tokens in the string - // - c = strtok(temp_str, separator); - - // - // Check for an empty string - // - if(!c) { delete [] temp_str; temp_str = 0; return(0); } - else n = 1; - - // - // Parse remaining tokens - // - while((c = strtok(0, separator)) != NULL) n++; if(temp_str) { delete [] temp_str; temp_str = (char *) 0; } @@ -260,6 +263,7 @@ bool has_prefix(const char **prefix_list, int n_prefix, int regex_apply(const char* pat, int num_mat, const char* str, char** &mat) { + const char *method_name = "regex_apply() "; // compile the regex pattern int rc = 0, num_act = 0, num_pmat = ( 0 == num_mat ? 1 : num_mat ); regex_t *re = new regex_t; @@ -267,7 +271,7 @@ int regex_apply(const char* pat, int num_mat, const char* str, char** &mat) if(0 != (rc = regcomp(re, pat, REG_EXTENDED))){ regfree(re); if( re ) { delete re; re = 0; } - mlog << Error << "\napply_regex - regcomp() error: " << rc << "\n\n"; + mlog << Error << "\n" << method_name << "- regcomp() error: " << rc << "\n\n"; exit(1); } @@ -294,7 +298,8 @@ int regex_apply(const char* pat, int num_mat, const char* str, char** &mat) for(int i=0; i < num_act; i++){ int mat_len = pmatch[i].rm_eo - pmatch[i].rm_so; mat[i] = new char[mat_len + 1]; - strcpy(mat[i], str_dat.substr(pmatch[i].rm_so, mat_len).data()); + m_strcpy(mat[i], str_dat.substr(pmatch[i].rm_so, mat_len).data(), + method_name, "mat[i]"); } mat[num_act] = NULL; @@ -392,4 +397,99 @@ int parse_thresh_index(const char *col_name) { return(i); } +//////////////////////////////////////////////////////////////////////// + +int m_strlen(const char *str) { + int str_len = 0; + if (str) str_len = strlen(str); // or use sizeof str; + + return str_len; +} + +//////////////////////////////////////////////////////////////////////// +// to_string is allocated. + +void m_strcpy(char *to_str, const char *from_str, const char *method_name, + const char *extra_msg) { + + if (ENHANCE_STR_APIS) { + int str_len = sizeof to_str; + m_strncpy(to_str, from_str, str_len, method_name, extra_msg); + } + else strcpy(to_str, from_str); + +} + +//////////////////////////////////////////////////////////////////////// +// to_string is not allocated. Allocate to_string and return the to_string after copying + +char *m_strcpy2(const char *from_str, const char *method_name, const char *extra_msg) { + char *to_str = (char *) 0; + if (from_str) { + int str_len = m_strlen(from_str); + + to_str = new char[str_len + 1]; + + if(!to_str) { + mlog << Error << "\n" << method_name + << "memory allocation error (m_strcpy)" + << (extra_msg == 0 ? "" : extra_msg) << "\n\n"; + exit(1); + } + + m_strcpy(to_str, from_str, method_name, extra_msg); + } + else { + mlog << Error << "\n" << method_name + << " Do not copy the string because a from_string is NULL. " + << (extra_msg == 0 ? "" : extra_msg) << "\n\n"; + } + + return to_str; +} + +//////////////////////////////////////////////////////////////////////// + +void m_strncpy(char *to_str, const char *from_str, const int buf_len, + const char *method_name, const char *extra_msg) { + if (!from_str){ + mlog << Warning << "\n" << method_name + << " Do not copy the string because a from_string is NULL. " + << (extra_msg == 0 ? "" : extra_msg) << "\n\n"; + } + else if (!to_str){ + mlog << Warning << "\n" << method_name + << " Do not copy the string because a to_string is NULL. " + << (extra_msg == 0 ? "" : extra_msg) << "\n\n"; + } + else { // (from_str && to_str) + int str_len = m_strlen(from_str); + if (str_len > buf_len) str_len = buf_len; + + memset(to_str, 0, str_len); + if (ENHANCE_STR_APIS) { + string temp_str = from_str; + temp_str.copy(to_str, str_len); + to_str[str_len] = 0; + + // Kludge: The sizeof from_str is 8 when the filenames come from a python script + if (strcmp(from_str, to_str)) { + str_len = strlen(from_str); + if (str_len > buf_len) str_len = buf_len; + temp_str.copy(to_str, str_len); + to_str[str_len] = 0; + } + } + else strncpy(to_str, from_str, str_len); + + if (strcmp(from_str, to_str)) { + mlog << Warning << "\n" << method_name + << " truncated a string " << (extra_msg == 0 ? "" : extra_msg) + << " from \"" << from_str << "\" to \"" << to_str << "\"\n\n"; + } + } + +} + + //////////////////////////////////////////////////////////////////////// From 489923f2f6c4fa695cf3a8c8a9847819f03af477 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Mon, 30 Aug 2021 23:57:26 -0600 Subject: [PATCH 144/200] #1855 Calls m_strcpy intead of strcpy --- met/src/libcode/vx_afm/afm.cc | 8 ++++--- met/src/libcode/vx_data2d_grib/grib_classes.h | 2 +- met/src/libcode/vx_nc_obs/nc_point_obs_out.cc | 13 ++++++++--- met/src/libcode/vx_ps/ps_text.cc | 11 +++++---- met/src/libcode/vx_statistics/met_stats.cc | 23 +++++++++++-------- met/src/tools/core/mode/page_1.cc | 11 +++++---- 6 files changed, 42 insertions(+), 26 deletions(-) diff --git a/met/src/libcode/vx_afm/afm.cc b/met/src/libcode/vx_afm/afm.cc index a36bb6b8e3..d16ab31106 100644 --- a/met/src/libcode/vx_afm/afm.cc +++ b/met/src/libcode/vx_afm/afm.cc @@ -26,6 +26,7 @@ using namespace std; #include "afm_token.h" #include "vx_log.h" +#include "string_fxns.h" //////////////////////////////////////////////////////////////////////// @@ -2283,10 +2284,11 @@ if ( s ) { delete [] s; s = (char *) 0; } if ( !text ) return; -s = new char [1 + strlen(text)]; - -strcpy(s, text); +int buf_len = strlen(text); +s = new char [1 + buf_len]; +const char *method_name = "set_string()"; +m_strcpy(s, text, method_name); return; diff --git a/met/src/libcode/vx_data2d_grib/grib_classes.h b/met/src/libcode/vx_data2d_grib/grib_classes.h index ce8b6687eb..6945fad97b 100644 --- a/met/src/libcode/vx_data2d_grib/grib_classes.h +++ b/met/src/libcode/vx_data2d_grib/grib_classes.h @@ -91,7 +91,7 @@ inline GribError::GribError(int ErrType, int LineNo, const char *FileName, const filename = FileName; - strcpy(message, Message); + m_strcpy(message, Message, "GribError::GribError()", "message"); } diff --git a/met/src/libcode/vx_nc_obs/nc_point_obs_out.cc b/met/src/libcode/vx_nc_obs/nc_point_obs_out.cc index 29e204672f..6d1818e054 100644 --- a/met/src/libcode/vx_nc_obs/nc_point_obs_out.cc +++ b/met/src/libcode/vx_nc_obs/nc_point_obs_out.cc @@ -207,15 +207,22 @@ void MetNcPointObsOut::get_dim_counts(int *obs_cnt, int *hdr_cnt) { void MetNcPointObsOut::init_buffer() { + const char *method_name = "MetNcPointObsOut::init_buffer()"; + const char *not_defined = "NotDefined"; + data_buffer.obs_data_idx = 0; data_buffer.obs_data_offset = 0; data_buffer.hdr_data_idx = 0; data_buffer.hdr_data_offset = 0; data_buffer.pb_hdr_data_offset = 0; - strcpy(data_buffer.prev_hdr_typ_buf, "NotDefined"); - strcpy(data_buffer.prev_hdr_sid_buf, "NotDefined"); - strcpy(data_buffer.prev_hdr_vld_buf, "NotDefined"); + m_strcpy(data_buffer.prev_hdr_typ_buf, not_defined, + method_name, "data_buffer.prev_hdr_typ_buf"); + m_strcpy(data_buffer.prev_hdr_sid_buf, not_defined, + method_name, "data_buffer.prev_hdr_sid_buf"); + m_strcpy(data_buffer.prev_hdr_vld_buf, not_defined, + method_name, "data_buffer.prev_hdr_vld_buf"); + for (int index=0; index #include "vx_log.h" +#include "string_fxns.h" #include "ps_text.h" @@ -288,6 +289,7 @@ if ( n < Nalloc ) return; int k; char * u = (char *) 0; +const char *method_name = "VxpsTextNode::extend"; // // round n up to the next multiple of vx_pstextnode_alloc_inc @@ -321,7 +323,7 @@ Nalloc = n; // copy the old values, if any // -if ( Text ) strncpy(u, Text, Nchars); +if ( Text ) m_strcpy(u, Text, method_name, "Text"); // // toss old, grab new @@ -349,15 +351,14 @@ void VxpsTextNode::set_text(const char * s) { -if ( Text ) { delete [] Text; Text = (char *) 0; } +const char *method_name = "VxpsTextNode::set_text"; +if ( Text ) { delete [] Text; Text = (char *) 0; Nalloc = 0; } Nchars = strlen(s); extend(Nchars + 2); -memset(Text, 0, Nalloc); - -strcpy(Text, s); +if (Text) m_strcpy(Text, s, method_name, "Text"); return; diff --git a/met/src/libcode/vx_statistics/met_stats.cc b/met/src/libcode/vx_statistics/met_stats.cc index a1aa7870bf..8d113d4997 100644 --- a/met/src/libcode/vx_statistics/met_stats.cc +++ b/met/src/libcode/vx_statistics/met_stats.cc @@ -3024,9 +3024,10 @@ void DMAPInfo::set_options(const int _baddeley_p, const double _baddeley_max_dis //////////////////////////////////////////////////////////////////////// int parse_message_type(const char *msg_typ_str, char **&msg_typ_arr) { - char tmp_str[max_str_len]; + char tmp_str[max_str_len + 1]; char *c = (char *) 0; int n, i; + const char *method_name = "parse_message_type() "; // Compute the number of tokens in the string based on " " n = num_tokens(msg_typ_str, " "); @@ -3038,18 +3039,18 @@ int parse_message_type(const char *msg_typ_str, char **&msg_typ_arr) { msg_typ_arr = new char * [n]; // Initialize the temp string for use in tokenizing - strcpy(tmp_str, msg_typ_str); + m_strcpy(tmp_str, msg_typ_str, method_name); // Tokenize the string and store the double values c = strtok(tmp_str, " "); - msg_typ_arr[0] = new char [strlen(c)+1]; - strcpy(msg_typ_arr[0], c); + msg_typ_arr[0] = m_strcpy2(c, method_name, "msg_typ_arr[0]"); + char a_var_name[512+1]; // Parse remaining tokens for(i=1; idata.accum()).c_str()); +m_strcpy(junk, sec_to_hhmmss_colon(eng.fcst_raw->data.accum()).c_str(), + method_name, "fcst_raw->data.accum()"); t1.write_xy1_to_cell(9, 1, dx, dy, 0.0, 0.0, junk); -strcpy(junk, sec_to_hhmmss_colon(eng.obs_raw->data.accum()).c_str()); +m_strcpy(junk, sec_to_hhmmss_colon(eng.obs_raw->data.accum()).c_str(), + method_name, "obs_raw->data.accum()"); t1.write_xy1_to_cell(9, 2, dx, dy, 0.0, 0.0, junk); nextline(); From 8b0a8cfe8d7387a7a2b235ba85cd02c1bf7f3ba2 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Mon, 30 Aug 2021 23:57:49 -0600 Subject: [PATCH 145/200] #1855 Calls m_strcpy2 intead of strcpy --- met/src/basic/vx_util/make_path.cc | 33 ++++++++++--------- met/src/basic/vx_util/thresh_array.cc | 27 +++++++-------- met/src/libcode/vx_analysis_util/stat_job.cc | 25 +++++++------- .../libcode/vx_data2d_grib/grib_classes.cc | 13 ++------ .../libcode/vx_data2d_python/data2d_python.cc | 9 +++-- met/src/libcode/vx_pxm/pbm.cc | 27 +++++---------- met/src/libcode/vx_pxm/pxm_base.cc | 20 +++++------ 7 files changed, 70 insertions(+), 84 deletions(-) diff --git a/met/src/basic/vx_util/make_path.cc b/met/src/basic/vx_util/make_path.cc index 6ccf6df9b4..1ec06ec40d 100644 --- a/met/src/basic/vx_util/make_path.cc +++ b/met/src/basic/vx_util/make_path.cc @@ -26,6 +26,7 @@ using namespace std; #include "make_path.h" #include "vx_log.h" +#include "string_fxns.h" //////////////////////////////////////////////////////////////////////// @@ -46,40 +47,40 @@ if ( path_exists(path) ) return ( 1 ); int j; int status; -char subpath[PATH_MAX]; +const char *method_name = "make_path() "; -memset(subpath, 0, sizeof(subpath)); - // // make subpath // -strcpy(subpath, path); - -j = strlen(subpath) - 1; - -while ( (j >= 0) && (subpath[j] != '/') ) subpath[j--] = (char) 0; +char *subpath = m_strcpy2(path, method_name); -if ( j >= 0 ) subpath[j] = (char) 0; +if (subpath) { + j = strlen(subpath) - 1; -mlog << Debug(1) << "\n\n subpath = \"" << subpath << "\"\n\n"; + while ( (j >= 0) && (subpath[j] != '/') ) subpath[j--] = (char) 0; -if ( strlen(subpath) == 0 ) return ( 0 ); + if ( j >= 0 ) subpath[j] = (char) 0; + mlog << Debug(1) << "\n\n " << method_name << "subpath = \"" << subpath << "\"\n\n"; + if ( strlen(subpath) == 0 ) { + if (subpath) { delete [] subpath; subpath = (char *) 0; } + return ( 0 ); + } -if ( !(path_exists(subpath)) ) { - - make_path(subpath, mode); + if ( !(path_exists(subpath)) ) { + make_path(subpath, mode); + } } - status = mkdir(path, mode); -if ( status < 0 ) return ( 0 ); +if (subpath) { delete [] subpath; subpath = (char *) 0; } +if ( status < 0 ) return ( 0 ); return ( 1 ); diff --git a/met/src/basic/vx_util/thresh_array.cc b/met/src/basic/vx_util/thresh_array.cc index 50358a5d83..0be2387c4c 100644 --- a/met/src/basic/vx_util/thresh_array.cc +++ b/met/src/basic/vx_util/thresh_array.cc @@ -18,6 +18,7 @@ using namespace std; #include "thresh_array.h" #include "vx_math.h" #include "vx_log.h" +#include "string_fxns.h" //////////////////////////////////////////////////////////////////////// @@ -257,23 +258,23 @@ void ThreshArray::add_css(const char *text) { //////////////////////////////////////////////////////////////////////// void ThreshArray::parse_thresh_str(const char *thresh_str) { - char *line = (char *) 0; char *c = (char *) 0; char *lp = (char *) 0; const char delim [] = " "; - const int n = strlen(thresh_str); - - line = new char [n + 1]; - memset(line, 0, n + 1); - strcpy(line, thresh_str); - - lp = line; - - while((c = strtok(lp, delim)) != NULL ) { - - add(c); + const char *method_name = "ThreshArray::parse_thresh_str()"; + + char *line = m_strcpy2(thresh_str, method_name); + if (line) { + + lp = line; + + while((c = strtok(lp, delim)) != NULL ) { + + add(c); + + lp = (char *) 0; + } - lp = (char *) 0; } if(line) { delete [] line; line = (char *) 0; } diff --git a/met/src/libcode/vx_analysis_util/stat_job.cc b/met/src/libcode/vx_analysis_util/stat_job.cc index c6cfafddea..2ebe7206b3 100644 --- a/met/src/libcode/vx_analysis_util/stat_job.cc +++ b/met/src/libcode/vx_analysis_util/stat_job.cc @@ -1060,6 +1060,7 @@ void STATAnalysisJob::parse_job_command(const char *jobstring) { StringArray col_value; ConcatString thresh_cs; int i, n; + const char *method_name = "STATAnalysisJob::parse_job_command()"; // If jobstring is null, simply return; if(jobstring) n = strlen(jobstring); @@ -1071,11 +1072,9 @@ void STATAnalysisJob::parse_job_command(const char *jobstring) { // // Create a temporary copy of the jobstring for use in parsing // - const int line_size = n + 1; - line = new char [line_size]; - memset(line, 0, line_size); - strncpy(line, jobstring, line_size); - line[line_size - 1] = (char) 0; + + line = m_strcpy2(jobstring, method_name); + if (!line) return; lp = line; @@ -1681,9 +1680,9 @@ void STATAnalysisJob::set_dump_row(const char *c) { if(!c) return; - dump_row = new char [strlen(c) + 1]; + const char *method_name = "STATAnalysisJob::set_dump_row()"; - strcpy(dump_row, c); + dump_row = m_strcpy2(c, method_name, "dump_row"); return; } @@ -1696,9 +1695,9 @@ void STATAnalysisJob::set_stat_file(const char *c) { if(!c) return; - stat_file = new char [strlen(c) + 1]; + const char *method_name = "STATAnalysisJob::set_stat_file()"; - strcpy(stat_file, c); + stat_file = m_strcpy2(c, method_name, "stat_file"); return; } @@ -1792,9 +1791,9 @@ void STATAnalysisJob::set_boot_rng(const char *c) { if(!c) return; - boot_rng = new char [strlen(c) + 1]; + const char *method_name = "STATAnalysisJob::set_boot_rng()"; - strcpy(boot_rng, c); + boot_rng = m_strcpy2(c, method_name, "boot_rng"); return; } @@ -1807,9 +1806,9 @@ void STATAnalysisJob::set_boot_seed(const char *c) { if(!c) return; - boot_seed = new char [strlen(c) + 1]; + const char *method_name = "STATAnalysisJob::set_boot_rng()"; - strcpy(boot_seed, c); + boot_seed = m_strcpy2(c, method_name, "boot_seed"); return; } diff --git a/met/src/libcode/vx_data2d_grib/grib_classes.cc b/met/src/libcode/vx_data2d_grib/grib_classes.cc index ff351e2d28..3c61614274 100644 --- a/met/src/libcode/vx_data2d_grib/grib_classes.cc +++ b/met/src/libcode/vx_data2d_grib/grib_classes.cc @@ -685,12 +685,13 @@ bool GribFile::open(const char *filename) { int j; +const char *method_name = "GribFile::open(char *) -> "; close(); if ( !(rep = new GribFileRep) ) { - mlog << Error << "\nGribFile::open(char *) -> memory allocation error\n\n"; + mlog << Error << "\n" << method_name << "memory allocation error\n\n"; exit ( 1 ); @@ -708,15 +709,7 @@ while ( (j >= 0) && (filename[j] != '/') ) --j; ++j; -if ( !(rep->name = new char [1 + strlen(filename + j)]) ) { - - mlog << Error << "\nGribFile::open(const char *) -> memory allocation error 1\n\n"; - - exit ( 1 ); - -} - -strcpy(rep->name, filename + j); +rep->name = m_strcpy2(filename + j, method_name, "rep->name"); rep->issue = rep->lead = 0; diff --git a/met/src/libcode/vx_data2d_python/data2d_python.cc b/met/src/libcode/vx_data2d_python/data2d_python.cc index 3aca4f0119..e246dc8ca2 100644 --- a/met/src/libcode/vx_data2d_python/data2d_python.cc +++ b/met/src/libcode/vx_data2d_python/data2d_python.cc @@ -157,7 +157,7 @@ ConcatString full_path, file_name; int i, file_argc; char **file_argv = (char **) 0; // allocated StringArray sa; - +const char *method_name = "MetPythonDataFile::open() "; // // Store the PythonCommand that is being run @@ -175,9 +175,12 @@ file_argc = sa.n_elements(); if ( file_argc > 0 ) { file_argv = new char * [ file_argc ]; + char a_var_name[512+1]; + for ( i=0; i #include "vx_log.h" +#include "string_fxns.h" #include "pbm.h" #include "pxm_utils.h" @@ -309,6 +310,7 @@ int n, j; char c1, c2; char junk[max_comment_length + 10]; ifstream in; +const char *method_name = "Pbm::read() -> "; // // clear out old image, if any @@ -324,7 +326,7 @@ in.open(filename); if ( !in ) { - mlog << Warning << "\nPbm::read() -> unable to read image file \"" << filename << "\"\n\n"; + mlog << Warning << "\n" << method_name << "unable to read image file \"" << filename << "\"\n\n"; return ( 0 ); @@ -333,20 +335,7 @@ if ( !in ) { // // copy filename // - -Name = new char [1 + strlen(filename)]; - -if ( !Name ) { - - mlog << Warning << "\nPbm::read() -> can't allocate memory for file name\n\n"; - - clear(); - - return ( 0 ); - -} - -strcpy(Name, filename); +Name = m_strcpy2(filename, method_name, "Name"); // // read magic cookie @@ -357,7 +346,7 @@ in.get(c2); if ( !in ) { - mlog << Warning << "\nPbm::read() -> unable to read magic cookie in image file \"" << filename << "\"\n\n"; + mlog << Warning << "\n" << method_name << "unable to read magic cookie in image file \"" << filename << "\"\n\n"; clear(); @@ -367,7 +356,7 @@ if ( !in ) { if ( (c1 != 'P') || (c2 != '4') ) { - mlog << Warning << "\nPbm::read() -> bad magic number in image file \"" << filename << "\"\n\n"; + mlog << Warning << "\n" << method_name << "bad magic number in image file \"" << filename << "\"\n\n"; clear(); @@ -408,7 +397,7 @@ n = total_data_bytes(); if ( !(data = new unsigned char [n]) ) { - mlog << Warning << "\nPbm::read() -> memory allocation error\n\n"; + mlog << Warning << "\n" << method_name << "memory allocation error\n\n"; clear(); @@ -418,7 +407,7 @@ if ( !(data = new unsigned char [n]) ) { if ( !in.read((char *) data, n) ) { - mlog << Warning << "\nPbm::read() -> trouble reading image data\n\n"; + mlog << Warning << "\n" << method_name << "trouble reading image data\n\n"; clear(); diff --git a/met/src/libcode/vx_pxm/pxm_base.cc b/met/src/libcode/vx_pxm/pxm_base.cc index 5e4450e36c..ea27132927 100644 --- a/met/src/libcode/vx_pxm/pxm_base.cc +++ b/met/src/libcode/vx_pxm/pxm_base.cc @@ -23,6 +23,7 @@ using namespace std; #include "pxm_base.h" #include "vx_log.h" +#include "string_fxns.h" #include "check_endian.h" @@ -110,6 +111,7 @@ return; void PxmBase::copy_common(const PxmBase & p) { +const char *method_name = "PxmBase::copy_common() "; if ( this == &p ) return; @@ -130,23 +132,21 @@ Ncols = p.Ncols; if ( p.Name ) { - Name = new char [1 + strlen(p.Name)]; - - strcpy(Name, p.Name); + Name = m_strcpy2(p.Name, method_name, "Name"); } if ( p.Ncomments > 0 ) { int j; + char a_var_name[512+1]; Ncomments = p.Ncomments; for (j=0; j= max_comments ) { - mlog << Error << "\nvoid PxmBase::add_comment(const char *) -> too meny comments!\n\n"; + mlog << Error << "\n" << method_name << "too meny comments!\n\n"; exit ( 1 ); } -Comment[Ncomments] = new char [1 + strlen(text)]; - -strcpy(Comment[Ncomments], text); +Comment[Ncomments] = m_strcpy2(text, method_name, "Comment"); ++Ncomments; From f691aa5b7ad12b5def353351bcf4abf4bf928a10 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Mon, 30 Aug 2021 23:58:27 -0600 Subject: [PATCH 146/200] #1855 Calls m_strcpy intead of strcpy --- met/src/libcode/vx_data2d_grib/grib_strings.cc | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/met/src/libcode/vx_data2d_grib/grib_strings.cc b/met/src/libcode/vx_data2d_grib/grib_strings.cc index 37a0152c7c..47e94e0c4a 100644 --- a/met/src/libcode/vx_data2d_grib/grib_strings.cc +++ b/met/src/libcode/vx_data2d_grib/grib_strings.cc @@ -264,8 +264,10 @@ int str_to_grib_code(const char *c, int &pcode, double &pthresh_lo, double &pthr int str_to_grib_code(const char *c, int &pcode, double &pthresh_lo, double &pthresh_hi, int ptv) { int gc = bad_data_int; - char tmp_str[512]; + const int buf_len = 512; + char tmp_str[buf_len + 1]; char *ptr = (char *) 0, *save_ptr = (char *) 0; + const char *method_name = "str_to_grib_code() -> "; // Parse out strings of the form: // PROB @@ -273,11 +275,11 @@ int str_to_grib_code(const char *c, int &pcode, // PROB(string>lo) // PROB(string " + mlog << Error << "\n" << method_name << "problems parsing the string \"" << c << "\".\n\n"; exit(1); @@ -304,9 +306,11 @@ int str_to_grib_code(const char *c, int &pcode, int str_to_prob_info(const char *c, double &pthresh_lo, double &pthresh_hi, int ptv) { int gc = bad_data_int, i, n_lt, n_gt; - char tmp_str[512]; + const int buf_len = 512; + char tmp_str[buf_len + 1]; char *ptr = (char *) 0, *save_ptr = (char *) 0; SingleThresh st; + const char *method_name = "str_to_prob_info()"; // Parse out strings of the form: // lo') n_gt++; } - strcpy(tmp_str, c); + m_strcpy(tmp_str, c, method_name); // Single inequality if(n_lt + n_gt == 1) { From 7fb2ecdd982819ea516b3adb5e7740da4c6121fe Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Tue, 31 Aug 2021 00:04:00 -0600 Subject: [PATCH 147/200] #1855 Removed spaces at the empty line --- met/src/libcode/vx_ps/vx_ps.cc | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/met/src/libcode/vx_ps/vx_ps.cc b/met/src/libcode/vx_ps/vx_ps.cc index f7d12def88..3b903b1630 100644 --- a/met/src/libcode/vx_ps/vx_ps.cc +++ b/met/src/libcode/vx_ps/vx_ps.cc @@ -1786,35 +1786,35 @@ if (strlen(c) > 1) { // // ligature? // - + LigatureInfo lig; - + if ( c[1] && afm.has_ligature(c[0], c[1], lig) ) { handle_ligature(lig, afm, cur); - + c += 2; - + return; - + } - + // // is it the start of a kern pair? // - + KPX kp; - + if ( c[1] && afm.has_kern_pair(c[0], c[1], kp) ) { - + cur->add_char(cm); - + handle_kern_pair(kp, afm, cur); - + ++c; - + return; - + } } From 3a2405d6097a588a75993aae7e70917c326f04df Mon Sep 17 00:00:00 2001 From: johnhg Date: Tue, 31 Aug 2021 09:38:06 -0600 Subject: [PATCH 148/200] Bugfix 1891 gen_vx_mask (#1895) * Per #1891, tighten up the gen_vx_mask logic a bit. Use a global config for the default NC compression level. Then read the input and mask fields using local variables instead of the global one to ensure they don't affect eachother. Also took the opportunity to refine the logic so that we only create a mtddf object in one spot, in the get_data_plane() function. * Per #1891, add a new test in unit_gen_vx_mask.xml that fails prior to #1891 and succeeds with these changes. * Per #1891, file name typo in unit_gen_vx_mask.xml. --- .../tools/other/gen_vx_mask/gen_vx_mask.cc | 186 +++++++++--------- met/src/tools/other/gen_vx_mask/gen_vx_mask.h | 17 +- test/xml/unit_gen_vx_mask.xml | 22 +++ 3 files changed, 120 insertions(+), 105 deletions(-) diff --git a/met/src/tools/other/gen_vx_mask/gen_vx_mask.cc b/met/src/tools/other/gen_vx_mask/gen_vx_mask.cc index 3b20c7ad60..3b220f8e75 100644 --- a/met/src/tools/other/gen_vx_mask/gen_vx_mask.cc +++ b/met/src/tools/other/gen_vx_mask/gen_vx_mask.cc @@ -24,7 +24,8 @@ // 006 07/09/18 Bullock Add shapefile masking type. // 007 04/08/19 Halley Gotway Add percentile thresholds. // 008 04/06/20 Halley Gotway Generalize input_grid option. -// 009 06/01/21 Seth Linden Change -type from optional to required +// 009 06/01/21 Seth Linden Change -type from optional to required. +// 010 08/30/21 Halley Gotway MET #1891 fix input and mask fields. // //////////////////////////////////////////////////////////////////////// @@ -102,7 +103,7 @@ void process_command_line(int argc, char **argv) { if(argc == 1) usage(); // Initialize the configuration object - config.read(replace_path(config_const_filename).c_str()); + global_config.read(replace_path(config_const_filename).c_str()); // Parse the command line into tokens cline.set(argc, argv); @@ -161,15 +162,6 @@ void process_command_line(int argc, char **argv) { //////////////////////////////////////////////////////////////////////// void process_input_grid(DataPlane &dp) { - Met2dDataFileFactory mtddf_factory; - Met2dDataFile *mtddf_ptr = (Met2dDataFile *) 0; - GrdFileType ftype = FileType_None; - - // Get the gridded file type from the data config string, if present - if(input_field_str.length() > 0) { - config.read_string(input_field_str.c_str()); - ftype = parse_conf_file_type(&config); - } // Parse info.name as a white-space separated string StringArray sa; @@ -193,28 +185,12 @@ void process_input_grid(DataPlane &dp) { << "Use the grid defined by file \"" << input_gridname << "\".\n"; - // Attempt to open the data file - mtddf_ptr = mtddf_factory.new_met_2d_data_file(input_gridname.c_str(), ftype); - if(!mtddf_ptr) { - mlog << Error << "\nprocess_input_grid() -> " - << "can't open input file \"" << input_gridname << "\"\n\n"; - exit(1); - } - - // Read the input data plane, if requested - if(input_field_str.length() > 0) { - get_data_plane(mtddf_ptr, input_field_str.c_str(), dp); - } - // Check for the output of a previous call to this tool - else if(get_gen_vx_mask_data(mtddf_ptr, dp)) { - } - - // Extract the grid - grid = mtddf_ptr->grid(); + // Read the input grid and data plane, if requested + get_data_plane(input_gridname, input_field_str, true, dp, grid); } // If not yet set, fill the input data plane with zeros - if(dp.is_empty()) { + if(dp.is_empty()) { dp.set_size(grid.nx(), grid.ny()); dp.set_constant(0.0); } @@ -223,18 +199,12 @@ void process_input_grid(DataPlane &dp) { << "Parsed Input Grid:\t" << grid.name() << " (" << grid.nx() << " x " << grid.ny() << ")\n"; - // Clean up - if(mtddf_ptr) { delete mtddf_ptr; mtddf_ptr = (Met2dDataFile *) 0; } - return; } //////////////////////////////////////////////////////////////////////// void process_mask_file(DataPlane &dp) { - Met2dDataFileFactory mtddf_factory; - Met2dDataFile *mtddf_ptr = (Met2dDataFile *) 0; - GrdFileType ftype = FileType_None; // Initialize solar_ut = (unixtime) 0; @@ -282,26 +252,10 @@ void process_mask_file(DataPlane &dp) { // Otherwise, process the mask file as a gridded data file else { - // Get the gridded file type from the mask config string, if present - if(mask_field_str.length() > 0) { - config.read_string(mask_field_str.c_str()); - ftype = parse_conf_file_type(&config); - } - - mtddf_ptr = mtddf_factory.new_met_2d_data_file(mask_filename.c_str(), ftype); - if(!mtddf_ptr) { - mlog << Error << "\nprocess_mask_file() -> " - << "can't open gridded mask data file \"" << mask_filename << "\"\n\n"; - exit(1); - } - - // Read mask_field, if specified - if(mask_field_str.length() > 0) { - get_data_plane(mtddf_ptr, mask_field_str.c_str(), dp); - } - - // Extract the grid - grid_mask = mtddf_ptr->grid(); + // Read the mask grid and data plane, if requested + get_data_plane(mask_filename, mask_field_str, + mask_type == MaskType_Data, + dp, grid_mask); mlog << Debug(2) << "Parsed Mask Grid:\t" << grid_mask.name() @@ -393,70 +347,105 @@ void process_mask_file(DataPlane &dp) { exit(1); } - // Clean up - if(mtddf_ptr) { delete mtddf_ptr; mtddf_ptr = (Met2dDataFile *) 0; } - return; } //////////////////////////////////////////////////////////////////////// -void get_data_plane(Met2dDataFile *mtddf_ptr, - const char *config_str, DataPlane &dp) { - VarInfoFactory vi_factory; - VarInfo *vi_ptr = (VarInfo *) 0; - double dmin, dmax; +void get_data_plane(const ConcatString &file_name, + const ConcatString &config_str, + bool read_gen_vx_mask_output, + DataPlane &dp, Grid &dp_grid) { + ConcatString local_cs = config_str; + GrdFileType ftype = FileType_None; - // Parse the config string - config.read_string(config_str); + // Initialize to the global configuration + MetConfig local_config = global_config; - // Allocate new VarInfo object - vi_ptr = vi_factory.new_var_info(mtddf_ptr->file_type()); - if(!vi_ptr) { - mlog << Error << "\nget_data_plane() -> " - << "can't allocate new VarInfo pointer.\n\n"; - exit(1); + // Parse non-empty config strings + if(local_cs.length() > 0) { + local_config.read_string(local_cs.c_str()); + ftype = parse_conf_file_type(&local_config); } - // Read config into the VarInfo object - vi_ptr->set_dict(config); - - // Get data plane from the file for this VarInfo object - if(!mtddf_ptr->data_plane(*vi_ptr, dp)) { + // Attempt to open the data file + Met2dDataFileFactory mtddf_factory; + Met2dDataFile *mtddf_ptr = (Met2dDataFile *) 0; + mtddf_ptr = mtddf_factory.new_met_2d_data_file(file_name.c_str(), ftype); + if(!mtddf_ptr) { mlog << Error << "\nget_data_plane() -> " - << "trouble reading field \"" << config_str - << "\" from file \"" << mtddf_ptr->filename() << "\"\n\n"; + << "can't open input file \"" << file_name << "\"\n\n"; exit(1); } - // Dump the range of data values read - dp.data_range(dmin, dmax); - mlog << Debug(3) - << "Read field \"" << vi_ptr->magic_str() << "\" from \"" - << mtddf_ptr->filename() << "\" with data ranging from " - << dmin << " to " << dmax << ".\n"; + // Read gen_vx_mask output from a previous run + if(read_gen_vx_mask_output && + local_cs.length() == 0 && + mtddf_ptr->file_type() == FileType_NcMet) { + if(get_gen_vx_mask_config_str((MetNcMetDataFile *) mtddf_ptr, local_cs)) { + local_config.read_string(local_cs.c_str()); + } + } + + // Read data plane, if requested + if(local_cs.length() > 0) { + + // Allocate new VarInfo object + VarInfoFactory vi_factory; + VarInfo *vi_ptr = (VarInfo *) 0; + vi_ptr = vi_factory.new_var_info(mtddf_ptr->file_type()); + if(!vi_ptr) { + mlog << Error << "\nget_data_plane() -> " + << "can't allocate new VarInfo pointer.\n\n"; + exit(1); + } + + // Read config into the VarInfo object + vi_ptr->set_dict(local_config); + + // Get data plane from the file for this VarInfo object + if(!mtddf_ptr->data_plane(*vi_ptr, dp)) { + mlog << Error << "\nget_data_plane() -> " + << "trouble reading field \"" << local_cs + << "\" from file \"" << mtddf_ptr->filename() << "\"\n\n"; + exit(1); + } + + // Dump the range of data values read + double dmin, dmax; + dp.data_range(dmin, dmax); + mlog << Debug(3) + << "Read field \"" << vi_ptr->magic_str() << "\" from \"" + << mtddf_ptr->filename() << "\" with data ranging from " + << dmin << " to " << dmax << ".\n"; + + // Clean up + if(vi_ptr) { delete vi_ptr; vi_ptr = (VarInfo *) 0; } + + } // end if + + // Extract the grid + dp_grid = mtddf_ptr->grid(); // Clean up - if(vi_ptr) { delete vi_ptr; vi_ptr = (VarInfo *) 0; } + if(mtddf_ptr) { delete mtddf_ptr; mtddf_ptr = (Met2dDataFile *) 0; } return; } //////////////////////////////////////////////////////////////////////// -bool get_gen_vx_mask_data(Met2dDataFile *mtddf_ptr, DataPlane &dp) { +bool get_gen_vx_mask_config_str(MetNcMetDataFile *mnmdf_ptr, + ConcatString &config_str) { bool status = false; - ConcatString tool, config_str; + ConcatString tool; int i; - // Must be MET NetCDF format - if(mtddf_ptr->file_type() != FileType_NcMet) return(status); - - // Cast pointer of correct type - MetNcMetDataFile *mnmdf_ptr = (MetNcMetDataFile *) mtddf_ptr; + // Check for null pointer + if(!mnmdf_ptr) return(status); // Check for the MET_tool global attribute - if(!get_global_att(mnmdf_ptr->MetNc->Nc, (string)"MET_tool", tool)) return(status); + if(!get_global_att(mnmdf_ptr->MetNc->Nc, (string) "MET_tool", tool)) return(status); // Check for gen_vx_mask output if(tool != program_name) return(status); @@ -469,8 +458,9 @@ bool get_gen_vx_mask_data(Met2dDataFile *mtddf_ptr, DataPlane &dp) { mnmdf_ptr->MetNc->Var[i].name == "lon") continue; // Read the first non-lat/lon variable - config_str << "'name=\"" << mnmdf_ptr->MetNc->Var[i].name << "\"; level=\"(*,*)\";'"; - get_data_plane(mtddf_ptr, config_str.c_str(), dp); + config_str << cs_erase + << "'name=\"" << mnmdf_ptr->MetNc->Var[i].name + << "\"; level=\"(*,*)\";'"; status = true; break; } @@ -1231,7 +1221,7 @@ void write_netcdf(const DataPlane &dp) { } int deflate_level = compress_level; - if (deflate_level < 0) deflate_level = config.nc_compression(); + if (deflate_level < 0) deflate_level = global_config.nc_compression(); // Define Variables mask_var = add_var(f_out, string(mask_name), ncFloat, lat_dim, lon_dim, deflate_level); @@ -1444,7 +1434,7 @@ void usage() { << mlog.verbosity_level() << ") (optional).\n" << "\t\t\"-compress level\" overrides the compression level of " - << "NetCDF variable (" << config.nc_compression() + << "NetCDF variable (" << global_config.nc_compression() << ") (optional).\n\n" << flush; diff --git a/met/src/tools/other/gen_vx_mask/gen_vx_mask.h b/met/src/tools/other/gen_vx_mask/gen_vx_mask.h index 70181b8b4e..fe6f6f901c 100644 --- a/met/src/tools/other/gen_vx_mask/gen_vx_mask.h +++ b/met/src/tools/other/gen_vx_mask/gen_vx_mask.h @@ -17,7 +17,8 @@ // 000 12/09/14 Halley Gotway New // 001 06/02/16 Halley Gotway Add box masking type. // 002 11/15/16 Halley Gotway Add solar masking types. -// 003 06/03/21 Seth Linden Changed default mask type to MaskType_None +// 003 06/03/21 Seth Linden Changed default mask type to MaskType_None. +// 004 08/30/21 Halley Gotway MET #1891 fix input and mask fields. // //////////////////////////////////////////////////////////////////////// @@ -32,6 +33,7 @@ using namespace std; #include "vx_cal.h" #include "mask_poly.h" #include "vx_grid.h" +#include "data2d_nc_met.h" #include "data_plane.h" #include "vx_data2d.h" #include "vx_data2d_factory.h" @@ -112,7 +114,7 @@ static MaskPoly poly_mask; static Grid grid, grid_mask; // Configuration object for reading config strings -static MetConfig config; +static MetConfig global_config; static int compress_level = -1; //////////////////////////////////////////////////////////////////////// @@ -120,10 +122,11 @@ static int compress_level = -1; static void process_command_line(int, char **); static void process_input_grid(DataPlane &dp); static void process_mask_file(DataPlane &dp); -static void get_data_plane(Met2dDataFile *mtddf_ptr, - const char *config_str, DataPlane &dp); -static bool get_gen_vx_mask_data(Met2dDataFile *mtddf_ptr, - DataPlane &dp); +static void get_data_plane(const ConcatString &file_name, + const ConcatString &config_str, bool, + DataPlane &dp, Grid &dp_grid); +static bool get_gen_vx_mask_config_str(MetNcMetDataFile *, + ConcatString &); static void get_shapefile_outline(ShpPolyRecord &shape); static void apply_poly_mask(DataPlane &dp); static void apply_shape_mask(DataPlane &dp); @@ -135,7 +138,7 @@ static void apply_data_mask(DataPlane &dp); static void apply_solar_mask(DataPlane &dp); static void apply_lat_lon_mask(DataPlane &dp); static DataPlane combine(const DataPlane &dp_data, - const DataPlane &dp_mask, SetLogic); + const DataPlane &dp_mask, SetLogic); static void write_netcdf(const DataPlane &dp); static void usage(); static void set_type(const StringArray &); diff --git a/test/xml/unit_gen_vx_mask.xml b/test/xml/unit_gen_vx_mask.xml index 9e9faf2638..8ada4b6649 100644 --- a/test/xml/unit_gen_vx_mask.xml +++ b/test/xml/unit_gen_vx_mask.xml @@ -438,4 +438,26 @@ + + + + + + + &MET_BIN;/gen_vx_mask + \ + &DATA_DIR_MODEL;/grib1/gfs/gfs_2012040900_F012.grib \ + &DATA_DIR_MODEL;/grib2/gfs/gfs_2012040900_F012.grib2 \ + &OUTPUT_DIR;/gen_vx_mask/DATA_TWO_FILE_TYPES.nc \ + -type data \ + -input_field 'name="TMP"; level="Z2"; file_type=GRIB1;' \ + -mask_field 'name="LAND"; level="L0";' \ + -name TMP_2M_LAND \ + -thresh lt0.5 -value -9999 -v 3 + + + &OUTPUT_DIR;/gen_vx_mask/DATA_TWO_FILE_TYPES.nc + + + From d80307c92082a6ab2fb2a792ee657b6902230be4 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Tue, 31 Aug 2021 10:03:01 -0600 Subject: [PATCH 149/200] #1855 sonarqube: replaced strlen to m_strlen --- .../basic/enum_to_string/my_enum_scanner.cc | 4 ++-- met/src/basic/vx_config/my_config_scanner.cc | 9 +++++---- met/src/basic/vx_util/ascii_table.cc | 3 ++- met/src/basic/vx_util/filename_suffix.cc | 2 +- met/src/basic/vx_util/is_number.cc | 9 +++++---- met/src/basic/vx_util/roman_numeral.cc | 8 +++++--- met/src/basic/vx_util/thresh_array.cc | 2 +- met/src/libcode/vx_afm/afm.cc | 2 +- met/src/libcode/vx_analysis_util/stat_job.cc | 7 ++++--- .../libcode/vx_data2d_factory/is_bufr_file.cc | 3 ++- .../libcode/vx_data2d_factory/is_grib_file.cc | 2 +- .../vx_data2d_factory/is_netcdf_file.cc | 2 +- .../libcode/vx_data2d_grib/grib_classes.cc | 2 +- .../libcode/vx_data2d_grib/grib_strings.cc | 2 +- met/src/libcode/vx_grid/find_grid_by_name.cc | 4 ++-- met/src/libcode/vx_gsl_prob/gsl_randist.cc | 2 +- met/src/libcode/vx_ps/ps_text.cc | 8 +++++--- met/src/libcode/vx_pxm/pgm.cc | 5 +++-- met/src/libcode/vx_pxm/ppm.cc | 5 +++-- met/src/libcode/vx_pxm/pxm_base.cc | 2 +- .../libcode/vx_python3_utils/wchar_argv.cc | 5 +++-- met/src/libcode/vx_shapedata/shapedata.cc | 2 +- .../vx_statistics/pair_data_ensemble.cc | 2 +- .../libcode/vx_statistics/pair_data_point.cc | 4 ++-- met/src/libcode/vx_tc_util/atcf_line_base.cc | 8 ++++---- met/src/tools/core/mode/mode_exec.cc | 2 +- met/src/tools/dev_utils/met_nc_file.cc | 6 +++--- met/src/tools/dev_utils/nceptab_to_flat.cc | 2 +- met/src/tools/other/ascii2nc/met_handler.cc | 2 +- met/src/tools/other/gsi_tools/gsi_util.cc | 2 +- met/src/tools/other/lidar2nc/lidar2nc.cc | 4 ++-- .../tools/other/mode_graphics/cgraph_main.cc | 4 ++-- .../other/mode_time_domain/mtd_txt_output.cc | 8 ++++---- .../other/mode_time_domain/nc_utils_local.cc | 3 ++- met/src/tools/other/pb2nc/pb2nc.cc | 20 +++++++++---------- .../plot_point_obs_conf_info.cc | 4 ++-- met/src/tools/other/wwmca_tool/wwmca_plot.cc | 9 +++++---- 37 files changed, 92 insertions(+), 78 deletions(-) diff --git a/met/src/basic/enum_to_string/my_enum_scanner.cc b/met/src/basic/enum_to_string/my_enum_scanner.cc index 81ef54eae5..14a4ed41a6 100644 --- a/met/src/basic/enum_to_string/my_enum_scanner.cc +++ b/met/src/basic/enum_to_string/my_enum_scanner.cc @@ -432,7 +432,7 @@ int do_id() { -// column += strlen(yytext); +// column += m_strlen(yytext); if ( enum_mode || last_was_enum || last_was_class ) { @@ -456,7 +456,7 @@ int do_int() { -// column += strlen(yytext); +// column += m_strlen(yytext); if ( !enum_mode ) return ( 0 ); diff --git a/met/src/basic/vx_config/my_config_scanner.cc b/met/src/basic/vx_config/my_config_scanner.cc index 288952689b..bed0a4cd90 100644 --- a/met/src/basic/vx_config/my_config_scanner.cc +++ b/met/src/basic/vx_config/my_config_scanner.cc @@ -26,6 +26,7 @@ using namespace std; #include "math_constants.h" #include "util_constants.h" #include "is_number.h" +#include "string_fxns.h" #include "dictionary.h" #include "builtin.h" @@ -527,7 +528,7 @@ int do_id() int j, k; -Column += strlen(configtext); +Column += m_strlen(configtext); if ( is_lhs ) { strncpy(configlval.text, configtext, max_id_length); return ( IDENTIFIER ); } @@ -657,7 +658,7 @@ int do_int() { -// Column += strlen(configtext); +// Column += m_strlen(configtext); configlval.nval.i = atoi(configtext); @@ -678,7 +679,7 @@ bool do_float() { -// Column += strlen(configtext); +// Column += m_strlen(configtext); configlval.nval.d = atof(configtext); @@ -1113,7 +1114,7 @@ int do_comp() int return_value = 0; -Column += strlen(configtext); +Column += m_strlen(configtext); if ( strcmp(configtext, "<" ) == 0 ) { configlval.cval = thresh_lt; return_value = COMPARISON; } else if ( strcmp(configtext, ">" ) == 0 ) { configlval.cval = thresh_gt; return_value = COMPARISON; } diff --git a/met/src/basic/vx_util/ascii_table.cc b/met/src/basic/vx_util/ascii_table.cc index 2dd56ba419..d5700f6721 100644 --- a/met/src/basic/vx_util/ascii_table.cc +++ b/met/src/basic/vx_util/ascii_table.cc @@ -26,6 +26,7 @@ using namespace std; #include "ascii_table.h" #include "comma_string.h" #include "fix_float.h" +#include "string_fxns.h" #include "util_constants.h" //////////////////////////////////////////////////////////////////////// @@ -1533,7 +1534,7 @@ out[field_width] = (char) 0; // end-of-string marker if ( !text ) return; -len = strlen(text); +len = m_strlen(text); if ( len == 0 ) return; diff --git a/met/src/basic/vx_util/filename_suffix.cc b/met/src/basic/vx_util/filename_suffix.cc index 3cafe60f3a..0a050964cc 100644 --- a/met/src/basic/vx_util/filename_suffix.cc +++ b/met/src/basic/vx_util/filename_suffix.cc @@ -42,7 +42,7 @@ const char * f = get_short_name(filename); // to avoid things like "./foo" // start at the end of the filename // -const char * s = f + (strlen(f) - 1); +const char * s = f + (m_strlen(f) - 1); // // move left until we see a period diff --git a/met/src/basic/vx_util/is_number.cc b/met/src/basic/vx_util/is_number.cc index f1c8b9c32f..4cdebd6d9a 100644 --- a/met/src/basic/vx_util/is_number.cc +++ b/met/src/basic/vx_util/is_number.cc @@ -21,6 +21,7 @@ using namespace std; #include #include "is_number.h" +#include "string_fxns.h" #include "substring.h" @@ -46,7 +47,7 @@ static int is_allowed_float_char(const char c); static const char allowed_float_chars [] = "+-Ee.0123456789"; -static const int n_allowed_float_chars = strlen(allowed_float_chars); +static const int n_allowed_float_chars = m_strlen(allowed_float_chars); //////////////////////////////////////////////////////////////////////// @@ -112,7 +113,7 @@ int is_float(const char * text) if ( !text ) return ( 0 ); -const int n = strlen(text); +const int n = m_strlen(text); if ( n == 0 ) return ( 0 ); @@ -184,7 +185,7 @@ if ( is_sign_char(t[0]) ) ++t; // at most one decimal point // -n = strlen(t); +n = m_strlen(t); digit_count = dp_count = 0; @@ -226,7 +227,7 @@ char junk[128]; // if the "e" is the first or last character, return "no" // -n = strlen(text); +n = m_strlen(text); if ( (exp_pos == 0) || (exp_pos == (n - 1)) ) return ( 0 ); diff --git a/met/src/basic/vx_util/roman_numeral.cc b/met/src/basic/vx_util/roman_numeral.cc index 5ce42c0109..83b90b8cf4 100644 --- a/met/src/basic/vx_util/roman_numeral.cc +++ b/met/src/basic/vx_util/roman_numeral.cc @@ -21,6 +21,7 @@ using namespace std; #include #include "roman_numeral.h" +#include "string_fxns.h" #include "vx_log.h" @@ -49,13 +50,14 @@ void roman_numeral(int n, char * out, const int lower_case_flag) { +const char *method_name = "roman_numeral() -> "; // // range check // if ( (n < roman_numeral_min) || (n > roman_numeral_max) ) { - mlog << Error << "\nroman_numeral() -> range check error!\n\n"; + mlog << Error << "\n" << method_name << "range check error!\n\n"; exit ( 1 ); @@ -94,7 +96,7 @@ rn_add(c, n, 1, rn_1, rn_5, rn_10); if ( lower_case_flag ) { int j; - const int k = strlen(s); + const int k = m_strlen(s); for (j=0; jreferenceCount = 1; // Strip off leading path component // -j = strlen(filename) - 1; +j = m_strlen(filename) - 1; while ( (j >= 0) && (filename[j] != '/') ) --j; diff --git a/met/src/libcode/vx_data2d_grib/grib_strings.cc b/met/src/libcode/vx_data2d_grib/grib_strings.cc index 47e94e0c4a..52ab29462e 100644 --- a/met/src/libcode/vx_data2d_grib/grib_strings.cc +++ b/met/src/libcode/vx_data2d_grib/grib_strings.cc @@ -321,7 +321,7 @@ int str_to_prob_info(const char *c, double &pthresh_lo, double &pthresh_hi, pthresh_lo = pthresh_hi = bad_data_double; // Count the number of '<' or '>' characters - for(i=0, n_lt=0, n_gt=0; i<(int)strlen(c); i++) { + for(i=0, n_lt=0, n_gt=0; i<(int)m_strlen(c); i++) { if(c[i] == '<') n_lt++; if(c[i] == '>') n_gt++; } diff --git a/met/src/libcode/vx_grid/find_grid_by_name.cc b/met/src/libcode/vx_grid/find_grid_by_name.cc index a5f426b66d..06d5a1c374 100644 --- a/met/src/libcode/vx_grid/find_grid_by_name.cc +++ b/met/src/libcode/vx_grid/find_grid_by_name.cc @@ -278,7 +278,7 @@ else phi_2 = phi_1; c = grid_strings[j++].c_str(); -if ( strlen(c) != 1 ) { +if ( m_strlen(c) != 1 ) { mlog << Error << "\nparse_lambert_grid() -> " << "bad hemisphere in grid spec\n\n"; @@ -399,7 +399,7 @@ lat_scale = atof(grid_strings[j++].c_str()); c = grid_strings[j++].c_str(); -if ( strlen(c) != 1 ) { +if ( m_strlen(c) != 1 ) { mlog << Error << "\nparse_stereographic_grid() -> " << "bad hemisphere in grid spec\n\n"; diff --git a/met/src/libcode/vx_gsl_prob/gsl_randist.cc b/met/src/libcode/vx_gsl_prob/gsl_randist.cc index 92b3031d68..d03cc10f8d 100644 --- a/met/src/libcode/vx_gsl_prob/gsl_randist.cc +++ b/met/src/libcode/vx_gsl_prob/gsl_randist.cc @@ -43,7 +43,7 @@ void rng_set(gsl_rng *&r, const char *rng_name, const char *rng_seed) { setenv("GSL_RNG_TYPE", rng_name, 1); // Set the GSL_RNG_SEED environment variable - if(rng_seed != (const char *) 0 && strlen(rng_seed) > 0) { + if(rng_seed != (const char *) 0 && m_strlen(rng_seed) > 0) { setenv("GSL_RNG_SEED", rng_seed, 1); } // If rng_seed is not set, set the seed using the current time diff --git a/met/src/libcode/vx_ps/ps_text.cc b/met/src/libcode/vx_ps/ps_text.cc index 93c4c22a9a..b161eea7a7 100644 --- a/met/src/libcode/vx_ps/ps_text.cc +++ b/met/src/libcode/vx_ps/ps_text.cc @@ -354,7 +354,7 @@ void VxpsTextNode::set_text(const char * s) const char *method_name = "VxpsTextNode::set_text"; if ( Text ) { delete [] Text; Text = (char *) 0; Nalloc = 0; } -Nchars = strlen(s); +Nchars = m_strlen(s); extend(Nchars + 2); @@ -616,9 +616,11 @@ void base_8_string(int k, char * out) { +const char *method_name = "base_8_string() -> "; + if ( (k < 0) || (k > 255) ) { - mlog << Error << "\nbase_8_string() -> bad value ... " << k << "\n\n"; + mlog << Error << "\n" << method_name << "bad value ... " << k << "\n\n"; exit ( 1 ); @@ -647,7 +649,7 @@ for (j=0; j<3; ++j) { // done // -strcpy(out, c); +m_strcpy(out, c, method_name); return; diff --git a/met/src/libcode/vx_pxm/pgm.cc b/met/src/libcode/vx_pxm/pgm.cc index f8eb026cd8..9b73d3b4df 100644 --- a/met/src/libcode/vx_pxm/pgm.cc +++ b/met/src/libcode/vx_pxm/pgm.cc @@ -28,6 +28,7 @@ using namespace std; #include "vx_log.h" #include "vx_math.h" +#include "string_fxns.h" //////////////////////////////////////////////////////////////////////// @@ -279,7 +280,7 @@ if ( !in ) { // copy filename // -Name = new char [1 + strlen(filename)]; +Name = new char [1 + m_strlen(filename)]; if ( !Name ) { @@ -291,7 +292,7 @@ if ( !Name ) { } -memcpy(Name, filename, 1 + strlen(filename)); +memcpy(Name, filename, 1 + m_strlen(filename)); // // read magic cookie diff --git a/met/src/libcode/vx_pxm/ppm.cc b/met/src/libcode/vx_pxm/ppm.cc index c12c130e56..a5df76dc77 100644 --- a/met/src/libcode/vx_pxm/ppm.cc +++ b/met/src/libcode/vx_pxm/ppm.cc @@ -29,6 +29,7 @@ using namespace std; #include "vx_log.h" #include "vx_math.h" +#include "string_fxns.h" //////////////////////////////////////////////////////////////////////// @@ -279,7 +280,7 @@ if ( !in ) { // copy filename // -Name = new char [1 + strlen(filename)]; +Name = new char [1 + m_strlen(filename)]; if ( !Name ) { @@ -291,7 +292,7 @@ if ( !Name ) { } -memcpy(Name, filename, 1 + strlen(filename)); +memcpy(Name, filename, 1 + m_strlen(filename)); // // read magic cookie diff --git a/met/src/libcode/vx_pxm/pxm_base.cc b/met/src/libcode/vx_pxm/pxm_base.cc index ea27132927..1946f1d289 100644 --- a/met/src/libcode/vx_pxm/pxm_base.cc +++ b/met/src/libcode/vx_pxm/pxm_base.cc @@ -219,7 +219,7 @@ if ( !Name ) return ( (const char *) 0 ); int j; -j = strlen(Name) - 1; +j = m_strlen(Name) - 1; while ( (j >= 0) && (Name[j] != '/') ) --j; diff --git a/met/src/libcode/vx_python3_utils/wchar_argv.cc b/met/src/libcode/vx_python3_utils/wchar_argv.cc index 2460fa5776..449e1d638f 100644 --- a/met/src/libcode/vx_python3_utils/wchar_argv.cc +++ b/met/src/libcode/vx_python3_utils/wchar_argv.cc @@ -25,6 +25,7 @@ using namespace std; #include "wchar_argv.h" #include "concat_string.h" +#include "string_fxns.h" #include "vx_log.h" @@ -219,8 +220,8 @@ argv_len = 0; for (j=0; j<_argc; ++j) { - len[j] = strlen(_argv[j]); // we're using the len array here because - // we don't want to call strlen more than + len[j] = m_strlen(_argv[j]); // we're using the len array here because + // we don't want to call m_strlen more than // once on each argv value argv_len += len[j]; diff --git a/met/src/libcode/vx_shapedata/shapedata.cc b/met/src/libcode/vx_shapedata/shapedata.cc index 319aa69e81..7ecd485115 100644 --- a/met/src/libcode/vx_shapedata/shapedata.cc +++ b/met/src/libcode/vx_shapedata/shapedata.cc @@ -497,7 +497,7 @@ double ShapeData::get_attr(const ConcatString &attr_name, else if(strcasecmp(attr_name.c_str(), "COMPLEXITY") == 0) { attr_val = complexity(); } - else if(strncasecmp(attr_name.c_str(), "INTENSITY_", strlen("INTENSITY_")) == 0) { + else if(strncasecmp(attr_name.c_str(), "INTENSITY_", m_strlen("INTENSITY_")) == 0) { StringArray sa = attr_name.split("_"); attr_val = intensity_percentile(raw_ptr, atoi(sa[1].c_str()), precip_flag); } diff --git a/met/src/libcode/vx_statistics/pair_data_ensemble.cc b/met/src/libcode/vx_statistics/pair_data_ensemble.cc index 53c4993580..d6869221fc 100644 --- a/met/src/libcode/vx_statistics/pair_data_ensemble.cc +++ b/met/src/libcode/vx_statistics/pair_data_ensemble.cc @@ -1360,7 +1360,7 @@ void VxPairDataEnsemble::add_point_obs(float *hdr_arr, int *hdr_typ_arr, (sid_exc_filt.n() && sid_exc_filt.has(hdr_sid_str))) return; // Check whether the observation variable name matches (rej_var) - if ((var_name != 0) && (0 < strlen(var_name))) { + if ((var_name != 0) && (0 < m_strlen(var_name))) { if ( var_name != obs_info->name() ) { return; } diff --git a/met/src/libcode/vx_statistics/pair_data_point.cc b/met/src/libcode/vx_statistics/pair_data_point.cc index daa40d1e9d..d81b26ad85 100644 --- a/met/src/libcode/vx_statistics/pair_data_point.cc +++ b/met/src/libcode/vx_statistics/pair_data_point.cc @@ -902,7 +902,7 @@ void VxPairDataPoint::add_point_obs(float *hdr_arr, const char *hdr_typ_str, // Check whether the GRIB code for the observation matches // the specified code - if((var_name != 0) && (0 < strlen(var_name))) { + if((var_name != 0) && (0 < m_strlen(var_name))) { if(var_name != obs_info->name()) { rej_var++; return; @@ -1802,7 +1802,7 @@ ConcatString point_obs_to_string(float *hdr_arr, const char *hdr_typ_str, const char *var_name) { ConcatString obs_cs, name; - if((var_name != 0) && (0 < strlen(var_name))) name = var_name; + if((var_name != 0) && (0 < m_strlen(var_name))) name = var_name; else name = obs_arr[1]; // diff --git a/met/src/libcode/vx_tc_util/atcf_line_base.cc b/met/src/libcode/vx_tc_util/atcf_line_base.cc index 42e8d199e3..2f35ed9e49 100644 --- a/met/src/libcode/vx_tc_util/atcf_line_base.cc +++ b/met/src/libcode/vx_tc_util/atcf_line_base.cc @@ -402,7 +402,7 @@ double parse_lat(const char *s) { v = parse_int(s); // Convert tenths of a degree to degrees - int buf_len = strlen(s); + int buf_len = m_strlen(s); if (buf_len > 0) { switch(s[buf_len - 1]) { case 'N': v *= 0.1; break; @@ -431,7 +431,7 @@ double parse_lon(const char *s) { v = parse_int(s); // Convert tenths of a degree to degrees - int buf_len = strlen(s); + int buf_len = m_strlen(s); if (buf_len > 0) { switch(s[buf_len - 1]) { case 'E': v *= 0.1; break; @@ -457,7 +457,7 @@ double parse_lon(const char *s) { int parse_int(const char *s, const int bad_data) { int v; - if(strlen(s) > 0) v = atoi(s); + if(m_strlen(s) > 0) v = atoi(s); else v = bad_data_int; // Check bad data value @@ -485,7 +485,7 @@ ATCFLineType string_to_atcflinetype(const char *s) { // YYYYMMDDHH in the 4th column for Genesis Tracks else if(is_yyyymmddhh(s)) t = ATCFLineType_GenTrack; else if(is_number(s)) t = ATCFLineType_Track; // ADECK - else if(strlen(s) == 0) t = ATCFLineType_Track; // BDECK + else if(m_strlen(s) == 0) t = ATCFLineType_Track; // BDECK else if(strcasecmp(s, "TR") == 0) t = ATCFLineType_ProbTR; else if(strcasecmp(s, "IN") == 0) t = ATCFLineType_ProbIN; else if(strcasecmp(s, "RI") == 0) t = ATCFLineType_ProbRI; diff --git a/met/src/tools/core/mode/mode_exec.cc b/met/src/tools/core/mode/mode_exec.cc index d25ccde24b..f0d77012f5 100644 --- a/met/src/tools/core/mode/mode_exec.cc +++ b/met/src/tools/core/mode/mode_exec.cc @@ -1753,7 +1753,7 @@ void nc_add_string(NcFile * f, const char * text, const char * var_name, const c if ( ! text ) t = "XXX"; else t = text; - const int N = strlen(t); + const int N = m_strlen(t); dim = add_dim(f, dim_name, N); diff --git a/met/src/tools/dev_utils/met_nc_file.cc b/met/src/tools/dev_utils/met_nc_file.cc index b1e35a2ab6..262fd089bb 100644 --- a/met/src/tools/dev_utils/met_nc_file.cc +++ b/met/src/tools/dev_utils/met_nc_file.cc @@ -278,19 +278,19 @@ bool MetNcFile::readFile(const int desired_grib_code, char station_id_buffer[max_str_len]; char hdr_vld_buffer[max_str_len]; // Read the corresponding header type for this observation - str_length = strlen(hdr_typ_str_full[hdr_index]); + str_length = m_strlen(hdr_typ_str_full[hdr_index]); if (str_length > typ_len) str_length = typ_len; strncpy(message_type_buffer, hdr_typ_str_full[hdr_index], str_length); message_type_buffer[str_length] = bad_data_char; // Read the corresponding header Station ID for this observation - str_length = strlen(hdr_sid_str_full[hdr_index]); + str_length = m_strlen(hdr_sid_str_full[hdr_index]); if (str_length > sid_len) str_length = sid_len; strncpy(station_id_buffer, hdr_sid_str_full[hdr_index], str_length); station_id_buffer[str_length] = bad_data_char; // Read the corresponding valid time for this observation - str_length = strlen(hdr_vld_str_full[hdr_index]); + str_length = m_strlen(hdr_vld_str_full[hdr_index]); if (str_length > vld_len) str_length = vld_len; strncpy(hdr_vld_buffer, hdr_vld_str_full[hdr_index], str_length); hdr_vld_buffer[str_length] = bad_data_char; diff --git a/met/src/tools/dev_utils/nceptab_to_flat.cc b/met/src/tools/dev_utils/nceptab_to_flat.cc index 3916da530a..4968cacd48 100644 --- a/met/src/tools/dev_utils/nceptab_to_flat.cc +++ b/met/src/tools/dev_utils/nceptab_to_flat.cc @@ -278,7 +278,7 @@ cout << '\"' << c << "\" "; c = strtok(s, ",\""); c = strtok(s, ",\"["); -k = strlen(c) - 1; +k = m_strlen(c) - 1; if ( c[k] == ' ' ) c[k] = (char) 0; diff --git a/met/src/tools/other/ascii2nc/met_handler.cc b/met/src/tools/other/ascii2nc/met_handler.cc index 22fc024fdd..17fdff2fda 100644 --- a/met/src/tools/other/ascii2nc/met_handler.cc +++ b/met/src/tools/other/ascii2nc/met_handler.cc @@ -153,7 +153,7 @@ bool MetHandler::_readObservations(LineDataFile &ascii_file) // Save the observation info int grib_code = atoi(data_line[6]); - for (unsigned int i=0; i= max_wct_infos ) { @@ -2113,7 +2113,7 @@ if ( empty(in) ) { int j, k; char c0, c1; -const int N = strlen(in); +const int N = m_strlen(in); char * s = (char *) 0; FT_UInt fi_glyph_index = 0; FT_UInt fl_glyph_index = 0; diff --git a/met/src/tools/other/mode_time_domain/mtd_txt_output.cc b/met/src/tools/other/mode_time_domain/mtd_txt_output.cc index 3b717c6b5d..f39a27829f 100644 --- a/met/src/tools/other/mode_time_domain/mtd_txt_output.cc +++ b/met/src/tools/other/mode_time_domain/mtd_txt_output.cc @@ -92,7 +92,7 @@ for (j=0; j= 0 && strlen("Variable index can't be negative")); + //assert(var_index >= 0 && m_strlen("Variable index can't be negative")); string var_name = bufr_obs_name_arr[var_index]; Observation obs = Observation(hdr_typ.text(), hdr_sid.text(), diff --git a/met/src/tools/other/plot_point_obs/plot_point_obs_conf_info.cc b/met/src/tools/other/plot_point_obs/plot_point_obs_conf_info.cc index a53740f278..6bf63f95ab 100644 --- a/met/src/tools/other/plot_point_obs/plot_point_obs_conf_info.cc +++ b/met/src/tools/other/plot_point_obs/plot_point_obs_conf_info.cc @@ -390,7 +390,7 @@ void PlotPointObsConfInfo::read_config(const char *user_file_name) { conf.read(replace_path(default_config_filename).c_str()); // Read the user file name, if provided - if(strlen(user_file_name) > 0) { + if(m_strlen(user_file_name) > 0) { mlog << Debug(1) << "User Config File: " << user_file_name << "\n"; conf.read(user_file_name); @@ -436,7 +436,7 @@ void PlotPointObsConfInfo::process_config( } // Parse plot_grid_string, if set - if(strlen(plot_grid_string) > 0) { + if(m_strlen(plot_grid_string) > 0) { // Parse as a white-space separated string sa.parse_wsss(plot_grid_string); diff --git a/met/src/tools/other/wwmca_tool/wwmca_plot.cc b/met/src/tools/other/wwmca_tool/wwmca_plot.cc index fce0ed780b..42ec608cb3 100644 --- a/met/src/tools/other/wwmca_tool/wwmca_plot.cc +++ b/met/src/tools/other/wwmca_tool/wwmca_plot.cc @@ -263,7 +263,7 @@ short_name = get_short_name(filename); // allocate space for the pixel time filename (make it slightly // larger than the input filename to ensure that it is large enough) -pt_filename = new char [strlen(filename) + 10]; +pt_filename = new char [m_strlen(filename) + 10]; // create pixel time filename and read it in set_pixel_time_filename(filename, pt_filename); @@ -385,12 +385,13 @@ void set_pixel_time_filename(const char * cp_name, char * pt_name) static const char * pt_name_start = "WWMCA_PIXL_TIME_MEANS"; int cp_length, short_cp_length; int i, j; + const char *method_name = "set_pixel_time_filename() -> "; // get the short name of the cloud percent file short_cp_name = get_short_name(cp_name); // get the lengths of the cloud percent filename including path and without path - cp_length = strlen(cp_name); + cp_length = m_strlen(cp_name); short_cp_length = short_cp_name.length(); // copy the path to the files @@ -399,9 +400,9 @@ void set_pixel_time_filename(const char * cp_name, char * pt_name) // now create the new pixel time filename which consists of the pt_name_start and the // rest of the cp_name after removing its start (WWMCA_TOTAL_CLOUD_PCT) - strcpy(pt_name + i, pt_name_start); + m_strcpy(pt_name + i, pt_name_start, method_name); - for (j = i + strlen(pt_name_start); j < cp_length; j++) + for (j = i + m_strlen(pt_name_start); j < cp_length; j++) pt_name[j] = cp_name[j]; pt_name[j] = '\0'; // null terminate the string From 183f53fab4e54a2692cd29937501589a51f2cc7f Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Tue, 31 Aug 2021 10:04:57 -0600 Subject: [PATCH 150/200] #1855 sonarqube: replaced strcpy to m_strcpy --- met/src/basic/vx_config/config_util.cc | 4 +++- met/src/basic/vx_config/icode.cc | 23 ++++++++++++------- met/src/basic/vx_util/ordinal.cc | 11 +++++---- .../vx_analysis_util/analysis_utils.cc | 8 +++---- met/src/libcode/vx_ps/vx_ps.cc | 6 +++-- met/src/libcode/vx_pxm/pcm.cc | 5 ++-- 6 files changed, 36 insertions(+), 21 deletions(-) diff --git a/met/src/basic/vx_config/config_util.cc b/met/src/basic/vx_config/config_util.cc index 01345181ac..70f718a90d 100644 --- a/met/src/basic/vx_config/config_util.cc +++ b/met/src/basic/vx_config/config_util.cc @@ -18,6 +18,7 @@ using namespace std; #include "vx_math.h" #include "vx_util.h" +#include "string_fxns.h" #include "GridTemplate.h" @@ -2343,8 +2344,9 @@ const char * statlinetype_to_string(const STATLineType t) { /////////////////////////////////////////////////////////////////////////////// void statlinetype_to_string(const STATLineType t, char *out) { + const char *method_name = "statlinetype_to_string() -> "; - strcpy(out, statlinetype_to_string(t)); + m_strcpy(out, statlinetype_to_string(t), method_name); return; } diff --git a/met/src/basic/vx_config/icode.cc b/met/src/basic/vx_config/icode.cc index fda6db8f01..6ce8b1f903 100644 --- a/met/src/basic/vx_config/icode.cc +++ b/met/src/basic/vx_config/icode.cc @@ -29,6 +29,7 @@ using namespace std; #include "indent.h" #include "icode.h" #include "dictionary.h" +#include "string_fxns.h" #include "celltype_to_string.h" @@ -162,6 +163,8 @@ void IcodeCell::assign(const IcodeCell & icc) { +const char *method_name = "IcodeCell::assign() -> "; + i = icc.i; d = icc.d; @@ -170,17 +173,17 @@ type = icc.type; if ( type == identifier ) { - name = new char [1 + strlen(icc.name)]; + name = new char [1 + m_strlen(icc.name)]; - strcpy(name, icc.name); + m_strcpy(name, icc.name, method_name, "name"); } if ( type == character_string ) { - text = new char [1 + strlen(icc.text)]; + text = new char [1 + m_strlen(icc.text)]; - strcpy(text, icc.text); + m_strcpy(text, icc.text, method_name, "text"); } @@ -413,13 +416,15 @@ void IcodeCell::set_identifier(const char * Text) { +const char *method_name = "IcodeCell::set_identifier() -> "; + clear(); type = identifier; -name = new char [1 + strlen(Text)]; +name = new char [1 + m_strlen(Text)]; -strcpy(name, Text); +m_strcpy(name, Text, method_name); return; @@ -434,15 +439,17 @@ void IcodeCell::set_string(const char * Text) { +const char *method_name = "IcodeCell::set_string() -> "; + clear(); -const int n = strlen(Text); +const int n = m_strlen(Text); type = character_string; text = new char [1 + n]; -strcpy(text, Text); +m_strcpy(text, Text, method_name); text[n] = 0; diff --git a/met/src/basic/vx_util/ordinal.cc b/met/src/basic/vx_util/ordinal.cc index b99768acde..fde21f237d 100644 --- a/met/src/basic/vx_util/ordinal.cc +++ b/met/src/basic/vx_util/ordinal.cc @@ -21,6 +21,7 @@ using namespace std; #include #include "ordinal.h" +#include "string_fxns.h" #include "vx_log.h" @@ -40,6 +41,8 @@ void ordinal_suffix(int n, char * out) { +const char *method_name = "ordinal_suffix() -> "; + // // suffix rule is the same for both // negative numbers and positive numbers @@ -57,13 +60,13 @@ n %= 100; // handle zero as a special case // -if ( n == 0 ) { strcpy(out, th); return; } +if ( n == 0 ) { m_strcpy(out, th, method_name, "out1"); return; } // // "teen" numbers are an exception // -if ( (n >= 10) && (n <= 20) ) { strcpy(out, th); return; } +if ( (n >= 10) && (n <= 20) ) { m_strcpy(out, th, method_name, "out1"); return; } // // if we get to this point, we only need to look @@ -92,13 +95,13 @@ switch ( n ) { // // should never happen // - mlog << Error << "\nordinal_suffix() -> totally confused!\n\n"; + mlog << Error << "\n" << method_name << "totally confused!\n\n"; exit ( 1 ); } // switch -strcpy(out, ans); +m_strcpy(out, ans, method_name, "out3"); // diff --git a/met/src/libcode/vx_analysis_util/analysis_utils.cc b/met/src/libcode/vx_analysis_util/analysis_utils.cc index 298683a373..1282aceedf 100644 --- a/met/src/libcode/vx_analysis_util/analysis_utils.cc +++ b/met/src/libcode/vx_analysis_util/analysis_utils.cc @@ -35,18 +35,18 @@ const char * delim = " "; char * c = (char *) 0; char * lp = (char *) 0; char * L = (char *) 0; - +const char *method_name = "parse_line() -> "; // // copy the line // -n = strlen(line); +n = m_strlen(line); L = new char [1 + n]; memset(L, 0, 1 + n); -strcpy(L, line); +m_strcpy(L, line, method_name); // // tokenize the line @@ -87,7 +87,7 @@ int all_digits(const char * line) int j, n; -n = strlen(line); +n = m_strlen(line); for (j=0; j 1) { +if (m_strlen(c) > 1) { // // ligature? diff --git a/met/src/libcode/vx_pxm/pcm.cc b/met/src/libcode/vx_pxm/pcm.cc index 3919805709..6b96bf5ae4 100644 --- a/met/src/libcode/vx_pxm/pcm.cc +++ b/met/src/libcode/vx_pxm/pcm.cc @@ -29,6 +29,7 @@ using namespace std; #include "vx_log.h" #include "vx_math.h" +#include "string_fxns.h" //////////////////////////////////////////////////////////////////////// @@ -399,7 +400,7 @@ if ( !in ) { // copy filename // -Name = new char [1 + strlen(filename)]; +Name = new char [1 + m_strlen(filename)]; if ( !Name ) { @@ -411,7 +412,7 @@ if ( !Name ) { } -memcpy(Name, filename, 1 + strlen(filename)); +memcpy(Name, filename, 1 + m_strlen(filename)); // // read magic cookie From 7b1a64b2cf2aa15640fe9619ecbd6c21253a4623 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Tue, 31 Aug 2021 10:07:12 -0600 Subject: [PATCH 151/200] #1855 sonarqube: replaced strlen to m_strlen --- met/src/basic/vx_util/make_path.cc | 4 ++-- met/src/libcode/vx_summary/summary_obs.cc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/met/src/basic/vx_util/make_path.cc b/met/src/basic/vx_util/make_path.cc index 1ec06ec40d..9fd81b7b5b 100644 --- a/met/src/basic/vx_util/make_path.cc +++ b/met/src/basic/vx_util/make_path.cc @@ -57,7 +57,7 @@ const char *method_name = "make_path() "; char *subpath = m_strcpy2(path, method_name); if (subpath) { - j = strlen(subpath) - 1; + j = m_strlen(subpath) - 1; while ( (j >= 0) && (subpath[j] != '/') ) subpath[j--] = (char) 0; @@ -65,7 +65,7 @@ if (subpath) { mlog << Debug(1) << "\n\n " << method_name << "subpath = \"" << subpath << "\"\n\n"; - if ( strlen(subpath) == 0 ) { + if ( m_strlen(subpath) == 0 ) { if (subpath) { delete [] subpath; subpath = (char *) 0; } return ( 0 ); } diff --git a/met/src/libcode/vx_summary/summary_obs.cc b/met/src/libcode/vx_summary/summary_obs.cc index 4a2ef5a768..b1b9c74701 100644 --- a/met/src/libcode/vx_summary/summary_obs.cc +++ b/met/src/libcode/vx_summary/summary_obs.cc @@ -231,7 +231,7 @@ bool SummaryObs::summarizeObs(const TimeSummaryInfo &summary_info) // Collect variable names var_name = curr_obs->getVarName().c_str(); - if (0 < strlen(var_name) && !summary_vnames.has(var_name)) { + if (0 < m_strlen(var_name) && !summary_vnames.has(var_name)) { summary_vnames.add(var_name); } // If this is a new key, create a new NumArray From cf8ef98396a9f7e1b0ca6abb3b1c045e43abb7bd Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Tue, 31 Aug 2021 10:10:06 -0600 Subject: [PATCH 152/200] #1855 sonarqube: replaced strlen to m_strlen --- met/src/basic/vx_util/string_fxns.cc | 33 +++++++--------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/met/src/basic/vx_util/string_fxns.cc b/met/src/basic/vx_util/string_fxns.cc index ff575d3757..1b257aae18 100644 --- a/met/src/basic/vx_util/string_fxns.cc +++ b/met/src/basic/vx_util/string_fxns.cc @@ -119,7 +119,7 @@ const char * short_name = (const char *) 0; if ( path ) { int j; - j = strlen(path) - 1; + j = m_strlen(path) - 1; while ( (j >= 0) && (path[j] != '/') ) --j; @@ -146,7 +146,7 @@ void append_char(char *str, const char c) // If the specified characater does not already exist at the // end of the string, add one. // - ptr = str + strlen(str) - 1; + ptr = str + m_strlen(str) - 1; if(*ptr != c) { *(++ptr) = c; @@ -172,7 +172,7 @@ void strip_char(char *str, const char c) // If the specified character exists at the end of the string, // remove it. // - ptr = str + strlen(str) - 1; + ptr = str + m_strlen(str) - 1; if(*ptr == c) { *(ptr) = 0; @@ -198,7 +198,7 @@ int num_tokens(const char *test_str, const char *separator) // if(!test_str) return(0); - int buf_len = strlen(test_str); + int buf_len = m_strlen(test_str); if(buf_len <= 0) return(0); // @@ -250,7 +250,7 @@ bool has_prefix(const char **prefix_list, int n_prefix, // case-insensitive matching. // for(i=0; i buf_len) str_len = buf_len; memset(to_str, 0, str_len); - if (ENHANCE_STR_APIS) { - string temp_str = from_str; - temp_str.copy(to_str, str_len); - to_str[str_len] = 0; - - // Kludge: The sizeof from_str is 8 when the filenames come from a python script - if (strcmp(from_str, to_str)) { - str_len = strlen(from_str); - if (str_len > buf_len) str_len = buf_len; - temp_str.copy(to_str, str_len); - to_str[str_len] = 0; - } - } - else strncpy(to_str, from_str, str_len); + strncpy(to_str, from_str, str_len); if (strcmp(from_str, to_str)) { mlog << Warning << "\n" << method_name From 5acda755a28970754082cfd32c804c673ef17704 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Tue, 31 Aug 2021 10:10:29 -0600 Subject: [PATCH 153/200] #1855 sonarqube: replaced strlen to m_strlen --- met/src/libcode/vx_tc_util/track_info.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/src/libcode/vx_tc_util/track_info.cc b/met/src/libcode/vx_tc_util/track_info.cc index be717f65c7..3d95a084e1 100644 --- a/met/src/libcode/vx_tc_util/track_info.cc +++ b/met/src/libcode/vx_tc_util/track_info.cc @@ -607,7 +607,7 @@ bool TrackInfo::is_match(const TrackInfo &t) const { bool TrackInfo::is_interp() const { const char *s = Technique.c_str(); - s += (strlen(Technique.c_str()) - 1); + s += (m_strlen(Technique.c_str()) - 1); // Return true if the last character of the model name is 'I' return(*s == 'I'); From d054d81af1484762015e079b38c80b5d73296b82 Mon Sep 17 00:00:00 2001 From: hsoh-u Date: Tue, 31 Aug 2021 19:03:42 -0600 Subject: [PATCH 154/200] #1855 Replaced strncpy to m_strncpy and enhance m_strcpy & m_strncpy (#1901) Co-authored-by: Howard Soh --- .../basic/enum_to_string/my_enum_scanner.cc | 4 --- met/src/basic/vx_config/my_config_scanner.cc | 25 ++++++++------- met/src/basic/vx_util/ascii_table.cc | 3 +- met/src/basic/vx_util/string_fxns.cc | 23 +++++++++++-- met/src/libcode/vx_color/my_color_scanner.cc | 9 ++++-- .../vx_data2d_grib/data2d_grib_utils.cc | 12 ++++--- .../libcode/vx_data2d_grib2/data2d_grib2.cc | 5 ++- .../vx_data2d_nc_pinterp/pinterp_file.cc | 8 ++--- met/src/libcode/vx_data2d_nccf/nccf_file.cc | 2 +- met/src/libcode/vx_nc_obs/nc_obs_util.cc | 2 +- .../libcode/vx_python3_utils/wchar_argv.cc | 3 +- .../tools/dev_utils/gribtab.dat_to_flat.cc | 3 +- met/src/tools/dev_utils/met_nc_file.cc | 19 +++++------ met/src/tools/dev_utils/nceptab_to_flat.cc | 3 +- met/src/tools/other/ioda2nc/ioda2nc.cc | 12 ++++--- .../other/mode_time_domain/nc_utils_local.cc | 7 ++-- met/src/tools/other/pb2nc/pb2nc.cc | 32 +++++++++---------- met/src/tools/tc_utils/tc_dland/tc_poly.cc | 3 +- met/src/tools/tc_utils/tc_pairs/tc_pairs.cc | 7 ++-- 19 files changed, 109 insertions(+), 73 deletions(-) diff --git a/met/src/basic/enum_to_string/my_enum_scanner.cc b/met/src/basic/enum_to_string/my_enum_scanner.cc index 14a4ed41a6..65b89273ab 100644 --- a/met/src/basic/enum_to_string/my_enum_scanner.cc +++ b/met/src/basic/enum_to_string/my_enum_scanner.cc @@ -432,8 +432,6 @@ int do_id() { -// column += m_strlen(yytext); - if ( enum_mode || last_was_enum || last_was_class ) { strncpy(yylval.name, yytext, sizeof(yylval.name)); @@ -456,8 +454,6 @@ int do_int() { -// column += m_strlen(yytext); - if ( !enum_mode ) return ( 0 ); yylval.ival = atoi(yytext); diff --git a/met/src/basic/vx_config/my_config_scanner.cc b/met/src/basic/vx_config/my_config_scanner.cc index bed0a4cd90..376fa10f5f 100644 --- a/met/src/basic/vx_config/my_config_scanner.cc +++ b/met/src/basic/vx_config/my_config_scanner.cc @@ -527,10 +527,14 @@ int do_id() { int j, k; +const char *method_name = "do_id() -> "; Column += m_strlen(configtext); -if ( is_lhs ) { strncpy(configlval.text, configtext, max_id_length); return ( IDENTIFIER ); } +if ( is_lhs ) { + m_strncpy(configlval.text, configtext, max_id_length, method_name, "configlval.text1"); + return ( IDENTIFIER ); +} // // print? @@ -642,7 +646,8 @@ for (j=0; j= max_id_length ) { - mlog << Error << "\ndo_quoted_string() -> " + mlog << Error << "\n" << method_name << "string too long! ... c = \"" << c << "\"\n\n"; exit ( 1 ); @@ -787,7 +789,7 @@ while ( replace_env(s) ) { if ( s.length() >= max_id_length ) { - mlog << Error << "\ndo_quoted_string() -> " + mlog << Error << "\n" << method_name << "string \"" << s << "\" too long!\n\n"; exit ( 1 ); @@ -798,9 +800,9 @@ clear_lexeme(); if ( s.nonempty() ) { - strncpy((char *) lexeme, s.c_str(), max_id_length); + m_strncpy((char *) lexeme, s.c_str(), max_id_length, method_name, "lexeme"); - strncpy(configlval.text, line, max_id_length); + m_strncpy(configlval.text, line, max_id_length, method_name, "configlval.text"); } else { @@ -1150,7 +1152,8 @@ int do_fort_thresh() { -strncpy(configlval.text, configtext, sizeof(configlval.text)); +const char *method_name = "do_fort_thresh() -> "; +m_strncpy(configlval.text, configtext, sizeof(configlval.text), method_name); return ( FORTRAN_THRESHOLD ); diff --git a/met/src/basic/vx_util/ascii_table.cc b/met/src/basic/vx_util/ascii_table.cc index d5700f6721..8e45eed53d 100644 --- a/met/src/basic/vx_util/ascii_table.cc +++ b/met/src/basic/vx_util/ascii_table.cc @@ -981,6 +981,7 @@ void AsciiTable::set_entry(const int r, const int c, double x) { ConcatString str; +const char *method_name = "AsciiTable::set_entry() -> "; if ( fabs(x - BadDataValue) < 0.0001 ) str = BadDataStr; else { @@ -994,7 +995,7 @@ fix_float(str); if ( DoCommaString ) { char junk[256]; - strncpy(junk, str.c_str(), str.length()); + m_strncpy(junk, str.c_str(), str.length(), method_name); char * p = (char *) 0; long X; ConcatString s; diff --git a/met/src/basic/vx_util/string_fxns.cc b/met/src/basic/vx_util/string_fxns.cc index 1b257aae18..a11be50848 100644 --- a/met/src/basic/vx_util/string_fxns.cc +++ b/met/src/basic/vx_util/string_fxns.cc @@ -31,7 +31,7 @@ using namespace std; #include "vx_log.h" -const bool ENHANCE_STR_APIS = false; +const bool ENHANCE_STR_APIS = true; //////////////////////////////////////////////////////////////////////// @@ -412,7 +412,11 @@ int m_strlen(const char *str) { void m_strcpy(char *to_str, const char *from_str, const char *method_name, const char *extra_msg) { - strcpy(to_str, from_str); + if (ENHANCE_STR_APIS) { + int str_len = sizeof to_str; + m_strncpy(to_str, from_str, str_len, method_name, extra_msg); + } + else strcpy(to_str, from_str); } @@ -463,7 +467,20 @@ void m_strncpy(char *to_str, const char *from_str, const int buf_len, if (str_len > buf_len) str_len = buf_len; memset(to_str, 0, str_len); - strncpy(to_str, from_str, str_len); + if (ENHANCE_STR_APIS) { + string temp_str = from_str; + temp_str.copy(to_str, str_len); + to_str[str_len] = 0; + + // Kludge: The sizeof from_str is 8 when the filenames come from a python script + if (strcmp(from_str, to_str)) { + str_len = m_strlen(from_str); + if (str_len > buf_len) str_len = buf_len; + temp_str.copy(to_str, str_len); + to_str[str_len] = 0; + } + } + else strncpy(to_str, from_str, str_len); if (strcmp(from_str, to_str)) { mlog << Warning << "\n" << method_name diff --git a/met/src/libcode/vx_color/my_color_scanner.cc b/met/src/libcode/vx_color/my_color_scanner.cc index d211900ddc..c845be959d 100644 --- a/met/src/libcode/vx_color/my_color_scanner.cc +++ b/met/src/libcode/vx_color/my_color_scanner.cc @@ -16,6 +16,8 @@ using namespace std; #include +#include "string_fxns.h" + #include "color_parser.h" // this must be included before color_parser_yacc.h #include "color.h" @@ -516,6 +518,8 @@ int do_id() { +const char *method_name = "is_id() -> "; + if ( strcmp(colortext, "blend" ) == 0 ) return ( BLEND ); if ( strcmp(colortext, "hsv" ) == 0 ) return ( HSV ); if ( strcmp(colortext, "cmyk" ) == 0 ) return ( CMYK ); @@ -532,7 +536,7 @@ if ( clist.has_name(colortext, index) ) { } -strncpy(colorlval.text, colortext, sizeof(colorlval.text) - 1); +m_strncpy(colorlval.text, colortext, sizeof(colorlval.text) - 1, method_name); @@ -681,6 +685,7 @@ void do_quoted_string() int n; char c; char line[max_lexeme_size + 1]; +const char *method_name = "do_quoted_string() -> "; memset(line, 0, sizeof(line)); @@ -728,7 +733,7 @@ while ( n < max_lexeme_size ) { line[n] = (char) 0; -strncpy(colorlval.text, line, sizeof(colorlval.text)); +m_strncpy(colorlval.text, line, sizeof(colorlval.text), method_name); colorlval.text[ sizeof(colorlval.text) - 1 ] = (char) 0; diff --git a/met/src/libcode/vx_data2d_grib/data2d_grib_utils.cc b/met/src/libcode/vx_data2d_grib/data2d_grib_utils.cc index 337526cc4c..4ef896f158 100644 --- a/met/src/libcode/vx_data2d_grib/data2d_grib_utils.cc +++ b/met/src/libcode/vx_data2d_grib/data2d_grib_utils.cc @@ -21,6 +21,7 @@ using namespace std; #include "data2d_grib_utils.h" #include "angles.h" #include "is_bad_data.h" +#include "string_fxns.h" #include "vx_log.h" #include "vx_math.h" @@ -41,6 +42,7 @@ bool is_prelim_match( VarInfoGrib & vinfo, const GribRecord & g) int ens_application, ens_type, ens_number, vinfo_ens_type; int vinfo_ens_number; unixtime ut, init_ut, valid_ut; + const char *method_name = "is_prelim_match() -> "; int p_code, code_for_lookup= vinfo.field_rec (); double p_thresh_lo, p_thresh_hi; @@ -110,8 +112,8 @@ bool is_prelim_match( VarInfoGrib & vinfo, const GribRecord & g) } char *ens_number_str = new char[vinfo_ens.length()]; - strncpy(ens_number_str, vinfo_ens.text()+1, - (size_t) vinfo_ens.length()); + m_strncpy(ens_number_str, vinfo_ens.text()+1, + (size_t) vinfo_ens.length(), method_name); ens_number_str[vinfo_ens.length()-1] = (char) 0; // if the string is numeric @@ -123,7 +125,7 @@ bool is_prelim_match( VarInfoGrib & vinfo, const GribRecord & g) // if one of the parameters was not set - error if( is_bad_data(vinfo_ens_number) || is_bad_data(vinfo_ens_type) ) { - mlog << Error << "\nis_prelim_match() -> " + mlog << Error << "\n" << method_name << "unrecognized GRIB_ens value '" << vinfo_ens << "' should be '" << conf_key_grib_ens_hi_res_ctl << "' or '" << conf_key_grib_ens_low_res_ctl @@ -179,7 +181,7 @@ bool is_prelim_match( VarInfoGrib & vinfo, const GribRecord & g) // if either the field name or the indices are specified, bail if( bad_data_int == vinfo_ptv || bad_data_int == code_for_lookup ) { - mlog << Error << "\nis_prelim_match() -> " + mlog << Error << "\n" << method_name << "either name or GRIB1_ptv and GRIB1_code must be " << "specified in field information\n\n"; exit(1); @@ -190,7 +192,7 @@ bool is_prelim_match( VarInfoGrib & vinfo, const GribRecord & g) //if did not find with params from the header - try default if( !GribTable.lookup_grib1(code_for_lookup, default_grib1_ptv, default_grib1_center, default_grib1_subcenter, tab) ) { - mlog << Error << "\nis_prelim_match() -> " + mlog << Error << "\n" << method_name << "no parameter found with matching GRIB1_ptv (" << vinfo_ptv << ") " << "GRIB1_code (" << vinfo.field_rec() << "). Use the MET_GRIB_TABLES " diff --git a/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc b/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc index 5cb7cbf6d3..82168ac52b 100644 --- a/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc +++ b/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc @@ -27,6 +27,7 @@ using namespace std; #include "data2d_grib2.h" #include "grib_strings.h" +#include "string_fxns.h" #include "vx_data2d.h" #include "vx_math.h" #include "vx_log.h" @@ -363,6 +364,8 @@ void MetGrib2DataFile::find_record_matches( VarInfoGrib2* vinfo, vector &listMatchRange ){ + const char *method_name = "MetGrib2DataFile::find_record_matches() -> "; + // clear the contents of the result vectors listMatchExact.clear(); listMatchRange.clear(); @@ -389,7 +392,7 @@ void MetGrib2DataFile::find_record_matches( VarInfoGrib2* vinfo, vinfo_ens_type = 2; } char* ens_number_str = new char[vinfo_ens.length() ]; - strncpy(ens_number_str, vinfo_ens.text()+1, (size_t) vinfo_ens.length()); + m_strncpy(ens_number_str, vinfo_ens.text()+1, (size_t) vinfo_ens.length(), method_name); ens_number_str[vinfo_ens.length()-1] = (char) 0; // if the string is numeric diff --git a/met/src/libcode/vx_data2d_nc_pinterp/pinterp_file.cc b/met/src/libcode/vx_data2d_nc_pinterp/pinterp_file.cc index b1b93d9e8a..a84210752f 100644 --- a/met/src/libcode/vx_data2d_nc_pinterp/pinterp_file.cc +++ b/met/src/libcode/vx_data2d_nc_pinterp/pinterp_file.cc @@ -184,12 +184,12 @@ int month, day, year, hour, minute, second, str_len; char time_str[max_str_len]; string c; NcVar v; - +const char *method_name = "PinterpFile::open() -> "; close(); Nc = open_ncfile(filename); -mlog << Debug(5) << "\nPinterpFile::open() -> " +mlog << Debug(5) << "\n" << method_name << "opend \"" << filename << "\".\n\n"; if ( IS_INVALID_NC_P(Nc) ) { close(); return ( false ); } @@ -245,7 +245,7 @@ if ( has_var(Nc, times_var_name) ) { for (j=0; j " + mlog << Error << "\n" << method_name << "error parsing time string \"" << time_str << "\".\n\n"; return ( false ); } diff --git a/met/src/libcode/vx_data2d_nccf/nccf_file.cc b/met/src/libcode/vx_data2d_nccf/nccf_file.cc index 4de72e0f44..5bc0fea1d1 100644 --- a/met/src/libcode/vx_data2d_nccf/nccf_file.cc +++ b/met/src/libcode/vx_data2d_nccf/nccf_file.cc @@ -2577,7 +2577,7 @@ void NcCfFile::get_grid_mapping_geostationary( ConcatString scene_id; if (get_global_att(_ncFile, (string)"scene_id", scene_id)) { char* scene_id_str = new char[scene_id.length()+1]; - strncpy(scene_id_str, scene_id.text(), scene_id.length()); + m_strncpy(scene_id_str, scene_id.text(), scene_id.length(), method_name.c_str()); scene_id_str[scene_id.length()] = 0; data.scene_id = scene_id_str; } diff --git a/met/src/libcode/vx_nc_obs/nc_obs_util.cc b/met/src/libcode/vx_nc_obs/nc_obs_util.cc index f545ea0690..70ea844d49 100644 --- a/met/src/libcode/vx_nc_obs/nc_obs_util.cc +++ b/met/src/libcode/vx_nc_obs/nc_obs_util.cc @@ -1396,7 +1396,7 @@ int write_nc_string_array (NcVar *ncVar, StringArray &strArray, const int str_le len_n = string_data.length(); len_p = strnlen(data_buf[buf_index], str_len); if (len_n > str_len) len_n = str_len; - strncpy(data_buf[buf_index], string_data.c_str(), len_n); + m_strncpy(data_buf[buf_index], string_data.c_str(), len_n, method_name.c_str()); for (int idx=len_n; idx &observations) + const string &desired_station_id, + const string &desired_message_type, + vector< SDObservation > &observations) { static const string method_name = "MetNcFile::readFile()"; @@ -77,7 +77,7 @@ bool MetNcFile::readFile(const int desired_grib_code, if (!_ncFile || IS_INVALID_NC_P(_ncFile)) { mlog << Error << "\n" << method_name << " -> trouble opening netCDF file " - << _filePath << "\n\n"; + << _filePath << "\n\n"; //_ncFile->close(); delete _ncFile; _ncFile = (NcFile *) 0; @@ -255,8 +255,6 @@ bool MetNcFile::readFile(const int desired_grib_code, break; // Read the current observation quality flag - //strncpy(obs_qty_str, obs_qty_str_block[i_offset], strl_count); - // Get the header index and variable type for this observation. @@ -280,19 +278,22 @@ bool MetNcFile::readFile(const int desired_grib_code, // Read the corresponding header type for this observation str_length = m_strlen(hdr_typ_str_full[hdr_index]); if (str_length > typ_len) str_length = typ_len; - strncpy(message_type_buffer, hdr_typ_str_full[hdr_index], str_length); + m_strncpy(message_type_buffer, hdr_typ_str_full[hdr_index], str_length, + method_name.c_str(), "message_type_buffer"); message_type_buffer[str_length] = bad_data_char; // Read the corresponding header Station ID for this observation str_length = m_strlen(hdr_sid_str_full[hdr_index]); if (str_length > sid_len) str_length = sid_len; - strncpy(station_id_buffer, hdr_sid_str_full[hdr_index], str_length); + m_strncpy(station_id_buffer, hdr_sid_str_full[hdr_index], str_length, + method_name.c_str(), "station_id_buffer"); station_id_buffer[str_length] = bad_data_char; // Read the corresponding valid time for this observation str_length = m_strlen(hdr_vld_str_full[hdr_index]); if (str_length > vld_len) str_length = vld_len; - strncpy(hdr_vld_buffer, hdr_vld_str_full[hdr_index], str_length); + m_strncpy(hdr_vld_buffer, hdr_vld_str_full[hdr_index], str_length, + method_name.c_str(), "hdr_vld_buffer"); hdr_vld_buffer[str_length] = bad_data_char; diff --git a/met/src/tools/dev_utils/nceptab_to_flat.cc b/met/src/tools/dev_utils/nceptab_to_flat.cc index 4968cacd48..e0a4fa76f3 100644 --- a/met/src/tools/dev_utils/nceptab_to_flat.cc +++ b/met/src/tools/dev_utils/nceptab_to_flat.cc @@ -238,8 +238,9 @@ int n, k; char line2[1024]; char * s = line2; char * c = (char *) 0; +const char *method_name = "parse_line() -> "; -strncpy(line2, line, sizeof(line2)); +m_strncpy(line2, line, sizeof(line2), method_name); // // check to make sure it's got a double quote in it diff --git a/met/src/tools/other/ioda2nc/ioda2nc.cc b/met/src/tools/other/ioda2nc/ioda2nc.cc index f822a1b005..83b3ae5c81 100644 --- a/met/src/tools/other/ioda2nc/ioda2nc.cc +++ b/met/src/tools/other/ioda2nc/ioda2nc.cc @@ -610,7 +610,8 @@ void process_ioda_file(int i_pb) { } char valid_time[ndatetime+1]; - strncpy(valid_time, (const char *)(hdr_vld_block + (i_read * ndatetime)), ndatetime); + m_strncpy(valid_time, (const char *)(hdr_vld_block + (i_read * ndatetime)), + ndatetime, method_name, "valid_time"); valid_time[ndatetime] = 0; msg_ut = yyyymmddThhmmss_to_unix(valid_time); @@ -660,7 +661,7 @@ void process_ioda_file(int i_pb) { if(has_msg_type) { int buf_len = sizeof(modified_hdr_typ); - strncpy(hdr_typ, hdr_msg_types+(i_read*nstring), nstring); + m_strncpy(hdr_typ, hdr_msg_types+(i_read*nstring), nstring, method_name, "hdr_typ"); hdr_typ[nstring] = 0; // Null terminate the message type string cleanup_hdr_buf(hdr_typ, nstring); @@ -679,17 +680,18 @@ void process_ioda_file(int i_pb) { << "Switching report type \"" << hdr_typ << "\" to message type \"" << mappedMessageType << "\".\n"; if(mappedMessageType.length() < HEADER_STR_LEN) buf_len = HEADER_STR_LEN; - strncpy(modified_hdr_typ, mappedMessageType.c_str(), buf_len); + m_strncpy(modified_hdr_typ, mappedMessageType.c_str(), buf_len, + method_name, "modified_hdr_typ"); } else { - strncpy(modified_hdr_typ, hdr_typ, buf_len); + m_strncpy(modified_hdr_typ, hdr_typ, buf_len, method_name, "modified_hdr_typ2"); } modified_hdr_typ[buf_len-1] = 0; } if(has_station_id) { char tmp_sid[nstring+1]; - strncpy(tmp_sid, hdr_station_ids+(i_read*nstring), nstring); + m_strncpy(tmp_sid, hdr_station_ids+(i_read*nstring), nstring, method_name, "tmp_sid"); tmp_sid[nstring] = 0; cleanup_hdr_buf(tmp_sid, nstring); hdr_sid = tmp_sid; diff --git a/met/src/tools/other/mode_time_domain/nc_utils_local.cc b/met/src/tools/other/mode_time_domain/nc_utils_local.cc index 0e8453b0a3..171ce59d9b 100644 --- a/met/src/tools/other/mode_time_domain/nc_utils_local.cc +++ b/met/src/tools/other/mode_time_domain/nc_utils_local.cc @@ -41,11 +41,13 @@ const char * string_att(const NcFile & Nc, const char * name) { +const char *method_name = "string_att() -> "; NcGroupAtt *att = get_nc_att(&Nc, (string)name); if ( GET_NC_TYPE_ID_P(att) != NcType::nc_CHAR ) { - mlog << Error << "\n\n string_att() -> attribute \"" << name << "\" is not a character string!\n\n"; + mlog << Error << "\n" << method_name << "attribute \"" << name + << "\" is not a character string!\n\n"; exit ( 1 ); @@ -53,8 +55,7 @@ if ( GET_NC_TYPE_ID_P(att) != NcType::nc_CHAR ) { ConcatString value; get_att_value_chars(att, value); -// strncpy(cbuf, value.c_str(), value.length()); -strncpy(cbuf, value.c_str(), cbuf_size - 1); +m_strncpy(cbuf, value.c_str(), cbuf_size - 1, method_name); cbuf[cbuf_size - 1] = (char) 0; diff --git a/met/src/tools/other/pb2nc/pb2nc.cc b/met/src/tools/other/pb2nc/pb2nc.cc index b9ff7c828a..588e3a62e7 100644 --- a/met/src/tools/other/pb2nc/pb2nc.cc +++ b/met/src/tools/other/pb2nc/pb2nc.cc @@ -672,7 +672,7 @@ void get_variable_info(const char* tbl_filename) { } if ('0' != line[BUFR_NUMBER_START]) continue; - strncpy(var_name, (line+BUFR_NAME_START), BUFR_NAME_LEN); + m_strncpy(var_name, (line+BUFR_NAME_START), BUFR_NAME_LEN, method_name, "var_name"); var_name[BUFR_NAME_LEN] = '\0'; for (int idx=(BUFR_NAME_LEN-1); idx >=0; idx--) { if (' ' != var_name[idx] ) break; @@ -681,7 +681,7 @@ void get_variable_info(const char* tbl_filename) { if (0 == m_strlen(var_name)) continue; var_count1++; - strncpy(var_desc, (line+BUFR_DESCRIPTION_START), BUFR_DESCRIPTION_LEN); + m_strncpy(var_desc, (line+BUFR_DESCRIPTION_START), BUFR_DESCRIPTION_LEN, method_name, "var_desc"); var_desc[BUFR_DESCRIPTION_LEN] = '\0'; for (int idx=(BUFR_DESCRIPTION_LEN-1); idx>=0; idx--) { if (' ' != var_desc[idx] && '|' != var_desc[idx]) { @@ -700,7 +700,7 @@ void get_variable_info(const char* tbl_filename) { if (NULL != strstr(line,"MNEMONIC")) break; if (NULL == strstr(line,"EVENT")) continue; - strncpy(var_name, (line+BUFR_NAME_START), BUFR_NAME_LEN); + m_strncpy(var_name, (line+BUFR_NAME_START), BUFR_NAME_LEN, method_name, "var_name2"); var_name[BUFR_NAME_LEN] = '\0'; for (int idx=(BUFR_NAME_LEN-1); idx >=0; idx--) { if (' ' != var_name[idx] ) break; @@ -708,7 +708,7 @@ void get_variable_info(const char* tbl_filename) { } //if (NULL == strstr(var_name,"EVENT")) continue; - strncpy(var_desc, (line+BUFR_SEQUENCE_START), BUFR_SEQUENCE_LEN); + m_strncpy(var_desc, (line+BUFR_SEQUENCE_START), BUFR_SEQUENCE_LEN, method_name, "var_desc2"); var_desc[BUFR_SEQUENCE_LEN] = '\0'; for (int idx=(BUFR_SEQUENCE_LEN-1); idx>=0; idx--) { if (' ' != var_desc[idx] && '|' != var_desc[idx]) { @@ -728,7 +728,7 @@ void get_variable_info(const char* tbl_filename) { if (' ' == line[BUFR_NAME_START]) continue; if ('-' == line[BUFR_NAME_START]) break; - strncpy(var_name, (line+BUFR_NAME_START), BUFR_NAME_LEN); + m_strncpy(var_name, (line+BUFR_NAME_START), BUFR_NAME_LEN, method_name, "var_name3"); var_name[BUFR_NAME_LEN] = '\0'; for (int idx=(BUFR_NAME_LEN-1); idx >=0; idx--) { if (' ' != var_name[idx] ) break; @@ -737,10 +737,10 @@ void get_variable_info(const char* tbl_filename) { if (NULL != strstr(line,"CCITT IA5")) { ascii_vars.add(var_name); - strncpy(var_unit_str, "CCITT IA5", sizeof(var_unit_str)); + m_strncpy(var_unit_str, "CCITT IA5", sizeof(var_unit_str), method_name, "var_unit_str1"); } else { - strncpy(var_unit_str, (line+BUFR_UNIT_START), BUFR_UNIT_LEN); + m_strncpy(var_unit_str, (line+BUFR_UNIT_START), BUFR_UNIT_LEN, method_name, "var_unit_str2"); var_unit_str[BUFR_UNIT_LEN] = '\0'; for (int idx=(BUFR_UNIT_LEN-1); idx>=0; idx--) { if (' ' != var_unit_str[idx] && '|' != var_unit_str[idx]) { @@ -1004,8 +1004,8 @@ void process_pbfile(int i_pb) { if (cal_pbl) { is_same_header = false; prev_hdr_vld_ut = -1; - strncpy(prev_hdr_typ, not_assigned, m_strlen(not_assigned)); - strncpy(prev_hdr_sid, not_assigned, m_strlen(not_assigned)); + m_strncpy(prev_hdr_typ, not_assigned, m_strlen(not_assigned), method_name, "prev_hdr_typ"); + m_strncpy(prev_hdr_sid, not_assigned, m_strlen(not_assigned), method_name, "prev_hdr_sid"); } IMM = JMM =1; @@ -1281,10 +1281,10 @@ void process_pbfile(int i_pb) { << "Switching report type \"" << hdr_typ << "\" to message type \"" << mappedMessageType << "\".\n"; if (mappedMessageType.length() > HEADER_STR_LEN) max_buf = HEADER_STR_LEN; - strncpy(modified_hdr_typ, mappedMessageType.c_str(), max_buf); + m_strncpy(modified_hdr_typ, mappedMessageType.c_str(), max_buf, method_name, "modified_hdr_typ1"); } else { - strncpy(modified_hdr_typ, hdr_typ, sizeof(modified_hdr_typ)); + m_strncpy(modified_hdr_typ, hdr_typ, sizeof(modified_hdr_typ), method_name, "modified_hdr_typ2"); } if (max_buf >= max_str_len) max_buf--; modified_hdr_typ[max_buf] = '\0'; @@ -1842,8 +1842,8 @@ void process_pbfile(int i_pb) { prev_hdr_lat = hdr_lat; prev_hdr_lon = hdr_lon; prev_hdr_elv = hdr_elv; - strncpy(prev_hdr_typ, hdr_typ, m_strlen(not_assigned)); - strncpy(prev_hdr_sid, hdr_sid.c_str(), m_strlen(not_assigned)); + m_strncpy(prev_hdr_typ, hdr_typ, m_strlen(not_assigned), method_name, "prev_hdr_typ"); + m_strncpy(prev_hdr_sid, hdr_sid.c_str(), m_strlen(not_assigned), method_name, "prev_hdr_sid"); } // If the number of observations for this header is non-zero, @@ -2125,7 +2125,7 @@ void process_pbfile_metadata(int i_pb) { ConcatString var_name; ConcatString hdr_name_str; - strncpy(tmp_str, prepbufr_hdrs_str, sizeof(tmp_str)); + m_strncpy(tmp_str, prepbufr_hdrs_str, sizeof(tmp_str), method_name, "tmp_str1"); length = m_strlen(tmp_str); readpbint_(&unit, &i_ret, &nlev, bufr_obs, tmp_str, &length, &hdr_level ); is_prepbufr_hdr = (0 < nlev); @@ -2148,7 +2148,7 @@ void process_pbfile_metadata(int i_pb) { } else { var_name = default_sid_name; - strncpy(tmp_str, bufr_avail_sid_names, sizeof(tmp_str)); + m_strncpy(tmp_str, bufr_avail_sid_names, sizeof(tmp_str), method_name, "tmp_str2"); length = m_strlen(tmp_str); readpbint_(&unit, &i_ret, &nlev, bufr_obs, tmp_str, &length, &hdr_level ); if (0 < nlev) { @@ -2165,7 +2165,7 @@ void process_pbfile_metadata(int i_pb) { if (0 < hdr_name_str.length()) hdr_name_str.add(" "); hdr_name_str.add(var_name); - strncpy(tmp_str, bufr_avail_latlon_names, sizeof(tmp_str)); + m_strncpy(tmp_str, bufr_avail_latlon_names, sizeof(tmp_str), method_name, "tmp_str3"); length = m_strlen(tmp_str); readpbint_(&unit, &i_ret, &nlev, bufr_obs, tmp_str, &length, &hdr_level ); if (0 < nlev) { diff --git a/met/src/tools/tc_utils/tc_dland/tc_poly.cc b/met/src/tools/tc_utils/tc_dland/tc_poly.cc index ef50388018..16560e110b 100644 --- a/met/src/tools/tc_utils/tc_dland/tc_poly.cc +++ b/met/src/tools/tc_utils/tc_dland/tc_poly.cc @@ -353,6 +353,7 @@ double TCPolyArray::min_dist(double lat, double lon, int &imin) const { bool operator>>(istream & in, TCPoly & p) { int i, n; double x, y; + const char *method_name = "operator>> -> "; p.clear(); @@ -370,7 +371,7 @@ bool operator>>(istream & in, TCPoly & p) { // NNN is the 3-digit number of points // AAAAAAAA is the 8-character name of the region n = atoi(a[0].c_str()); - strncpy(name, line.c_str()+4, 8); + m_strncpy(name, line.c_str()+4, 8, method_name); name[8] = '\0'; name_cs = name; name_cs.ws_strip(); diff --git a/met/src/tools/tc_utils/tc_pairs/tc_pairs.cc b/met/src/tools/tc_utils/tc_pairs/tc_pairs.cc index 0013656a81..7a70c0736a 100644 --- a/met/src/tools/tc_utils/tc_pairs/tc_pairs.cc +++ b/met/src/tools/tc_utils/tc_pairs/tc_pairs.cc @@ -1440,11 +1440,12 @@ void derive_baseline_model(const ConcatString &model, float bl_lat[nvtx], bl_lon[nvtx], bl_vmax[nvtx]; TrackInfo new_track; TrackPoint new_point; + const char *method_name = "derive_baseline_model() -> "; // Check bounds if(i_start < 0 || i_start >= ti.n_points()) { mlog << Error - << "\nderive_baseline_model() -> " + << "\n" << method_name << "range check error for i_start = " << i_start << "\n\n"; exit(1); } @@ -1504,7 +1505,7 @@ void derive_baseline_model(const ConcatString &model, } // Store the basin name - strncpy(basin, ti.basin().c_str(), 2); + m_strncpy(basin, ti.basin().c_str(), 2, method_name); // Store the valid time of the starting point unix_to_mdyhms(ti[i_start].valid(), @@ -1561,7 +1562,7 @@ void derive_baseline_model(const ConcatString &model, } else { mlog << Error - << "\nderive_baseline_model() -> " + << "\n" << method_name << "unsupported baseline model type \"" << model << "\".\n\n"; exit(1); From cf190b3b47274c6171556e3c474ed47ece55dc27 Mon Sep 17 00:00:00 2001 From: hsoh-u Date: Wed, 1 Sep 2021 09:50:17 -0600 Subject: [PATCH 155/200] #1855 Turn off new strcpy functions --- met/src/basic/vx_util/string_fxns.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/src/basic/vx_util/string_fxns.cc b/met/src/basic/vx_util/string_fxns.cc index a11be50848..3b1213d3af 100644 --- a/met/src/basic/vx_util/string_fxns.cc +++ b/met/src/basic/vx_util/string_fxns.cc @@ -31,7 +31,7 @@ using namespace std; #include "vx_log.h" -const bool ENHANCE_STR_APIS = true; +const bool ENHANCE_STR_APIS = false; //////////////////////////////////////////////////////////////////////// From afe023e78a0faf2f0216f0722504d8f45b44f249 Mon Sep 17 00:00:00 2001 From: hsoh-u Date: Wed, 1 Sep 2021 10:06:58 -0600 Subject: [PATCH 156/200] #1855 Corretced typo (arguments were swapped at MetPythonDataFile::open) --- met/src/libcode/vx_data2d_python/data2d_python.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/src/libcode/vx_data2d_python/data2d_python.cc b/met/src/libcode/vx_data2d_python/data2d_python.cc index e246dc8ca2..56998a706f 100644 --- a/met/src/libcode/vx_data2d_python/data2d_python.cc +++ b/met/src/libcode/vx_data2d_python/data2d_python.cc @@ -180,7 +180,7 @@ if ( file_argc > 0 ) { for ( i=0; i Date: Wed, 1 Sep 2021 10:21:28 -0600 Subject: [PATCH 157/200] #1855 Make sure the to_str is null terminated after strncpy --- met/src/basic/vx_util/string_fxns.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/met/src/basic/vx_util/string_fxns.cc b/met/src/basic/vx_util/string_fxns.cc index 3b1213d3af..8e477d073c 100644 --- a/met/src/basic/vx_util/string_fxns.cc +++ b/met/src/basic/vx_util/string_fxns.cc @@ -480,7 +480,10 @@ void m_strncpy(char *to_str, const char *from_str, const int buf_len, to_str[str_len] = 0; } } - else strncpy(to_str, from_str, str_len); + else { + strncpy(to_str, from_str, str_len); + to_str[str_len] = 0; + } if (strcmp(from_str, to_str)) { mlog << Warning << "\n" << method_name From 253ad50b5c6c31a6159dc8ed08b9650a0333aea1 Mon Sep 17 00:00:00 2001 From: jprestop Date: Wed, 1 Sep 2021 13:31:05 -0600 Subject: [PATCH 158/200] Feature 1827 v10.1.0 beta2 (#1902) * Per #1827, updated release notes * Per #1827, Added extra ~ under header * Update met/docs/Users_Guide/release-notes.rst Co-authored-by: johnhg * Update met/docs/Users_Guide/release-notes.rst Co-authored-by: johnhg * Update met/docs/Users_Guide/release-notes.rst Co-authored-by: johnhg * Per #1827, rereferenced GitHub issue number Co-authored-by: Julie Prestopnik Co-authored-by: johnhg --- met/docs/Users_Guide/release-notes.rst | 30 ++++++++++++++++++++++++-- met/docs/version | 2 +- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/met/docs/Users_Guide/release-notes.rst b/met/docs/Users_Guide/release-notes.rst index 187c21fc93..8404a82d8c 100644 --- a/met/docs/Users_Guide/release-notes.rst +++ b/met/docs/Users_Guide/release-notes.rst @@ -5,7 +5,33 @@ 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-beta1 release notes (|release_date|) +MET Version 10.1.0-beta2 release notes (|release_date|) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* Fix the findings from SonarQube (`#1855 `_). +* Fix gen_vx_mask so that the -input_field and -mask_field options are processed independently (`#1891 `_). +* Enhance Stat-Analysis to write the GO Index and CBS Index into a new STAT line type (`#1788 `_). +* Enhance MET to compute the CBS Index (`#1031 `_). +* Fix integer overflow in Grid-Diag (`#1886 `_). +* Fix failure of Ensemble-Stat when verifying against gridded ECMWF GRIB1 files (`#1879 `_). +* Fix consumption of too much memory by Stat-Analysis (`#1875 `_). +* Fix failure in plot_tcmpr.R script when a directory is passed in with -lookin (`#1872 `_). +* Enable TC-Pairs to only write output for a configurable list of valid times (`#1870 `_). +* Add check for the start offset and data count are valid before calling NetCDF API (`#1852 `_). +* Add new column, Scatter Index, for CNT line type (`#1843 `_). +* Enable point2grid to support double type latitude/longitude variables (`#1838 `_). +* Treat warnings from the documentation as errors to facilitate continuous integration with GHA (`#1819 `_). +* Fix the output of point2grid which is flipped and rotated with lat/lon to lat/lon conversion (`#1817 `_). +* Add ORANK line type to the HiRA output from Point-Stat (`#1764 `_). +* Make the specification of a binary threshold in Wavelet-Stat optional (`#1746 `_). +* Document the statistics from the RPS line type in Appendix C (`#1853 `_). +* Fix broken URLs in default MET config files (`#1864 `_). +* Add G and G-Beta to the DMAP line type from Grid-Stat (`#1673 `_). +* Create and publish a PDF of the MET User's Guide (`#1453 `_). +* Update documentation to reference GitHub Discussions instead of MET Help (`#1833 `_). +* 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 `_). @@ -31,7 +57,7 @@ MET Version 10.0.0 release notes (20210510) * Run the nightly build as the shared met_test user (`#1116 `_). * Correct the time offset for tests in unit_plot_data_plane.xml (`#1677 `_). * Enhance the sample plotting R-script to read output from different versions of MET (`#1653 `_). - * Update the default configuration options to compile the development code with the debug (-g) option and the production code without it (`#1788 `_). + * Update the default configuration options to compile the development code with the debug (-g) option and the production code without it (`#1778 `_). * Update MET to compile using GCC version 10 (`#1552 `_). * Update MET to compile using PGI version 20 (`#1317 `_). diff --git a/met/docs/version b/met/docs/version index 2e6b7f7038..b915cf62d2 100644 --- a/met/docs/version +++ b/met/docs/version @@ -1 +1 @@ -10.0.0-beta4 +10.1.0-beta2 From 2b8027179a4d8f24c065e2955588488b20948590 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 8 Sep 2021 00:47:09 -0600 Subject: [PATCH 159/200] #1903 Added str_wrappers.cc & str_wrappers.h. They are moved from string_fxns --- met/src/basic/vx_log/Makefile.am | 1 + met/src/basic/vx_log/str_wrappers.cc | 100 +++++++++++++++++++++++++++ met/src/basic/vx_log/str_wrappers.h | 40 +++++++++++ 3 files changed, 141 insertions(+) create mode 100644 met/src/basic/vx_log/str_wrappers.cc create mode 100644 met/src/basic/vx_log/str_wrappers.h diff --git a/met/src/basic/vx_log/Makefile.am b/met/src/basic/vx_log/Makefile.am index 710c1c5843..9e4ba32cf2 100644 --- a/met/src/basic/vx_log/Makefile.am +++ b/met/src/basic/vx_log/Makefile.am @@ -16,6 +16,7 @@ libvx_log_a_SOURCES = concat_string.cc concat_string.h \ indent.cc indent.h \ logger.cc logger.h \ string_array.cc string_array.h \ + str_wrappers.cc str_wrappers.h \ vx_log.h # Build the library when making a distribution so that diff --git a/met/src/basic/vx_log/str_wrappers.cc b/met/src/basic/vx_log/str_wrappers.cc new file mode 100644 index 0000000000..9e59375fc4 --- /dev/null +++ b/met/src/basic/vx_log/str_wrappers.cc @@ -0,0 +1,100 @@ +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +// ** Copyright UCAR (c) 1992 - 2021 +// ** University Corporation for Atmospheric Research (UCAR) +// ** National Center for Atmospheric Research (NCAR) +// ** Research Applications Lab (RAL) +// ** P.O.Box 3000, Boulder, Colorado, 80307-3000, USA +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* + + + +//////////////////////////////////////////////////////////////////////// + + +using namespace std; + +#include "logger.h" +#include "str_wrappers.h" + + +//////////////////////////////////////////////////////////////////////// + +int m_strlen(const char *str, bool buf_size) { + int str_len = -1; + if (str) str_len = buf_size ? sizeof str : strlen(str); + + return str_len; +} + +//////////////////////////////////////////////////////////////////////// +// to_str should be allocated before calling this. + +void m_strcpy(char *to_str, const char *from_str, const char *method_name, + const char *extra_msg) { + + int str_len = m_strlen(to_str, true); + m_strncpy(to_str, from_str, str_len, method_name, extra_msg); + +} + +//////////////////////////////////////////////////////////////////////// +// to_string should not allocated. This allocates and return to_str after copying + +char *m_strcpy2(const char *from_str, const char *method_name, const char *extra_msg) { + char *to_str = (char *) 0; + if (from_str) { + int str_len = m_strlen(from_str); + + to_str = new char[str_len + 1]; + + if(!to_str) { + mlog << Error << "\n" << method_name + << "memory allocation error (m_strcpy)" + << (extra_msg == 0 ? "" : extra_msg) << "\n\n"; + exit(1); + } + + m_strncpy(to_str, from_str, str_len, method_name, extra_msg); + } + else { + mlog << Error << "\n" << method_name + << " Do not copy the string because a from_string is NULL. " + << (extra_msg == 0 ? "" : extra_msg) << "\n\n"; + } + + return to_str; +} + +//////////////////////////////////////////////////////////////////////// + +void m_strncpy(char *to_str, const char *from_str, const int buf_len, + const char *method_name, const char *extra_msg, bool truncate) { + if (!from_str){ + mlog << Warning << "\n" << method_name + << " Do not copy the string because a from_string is NULL. " + << (extra_msg == 0 ? "" : extra_msg) << "\n\n"; + } + else if (!to_str){ + mlog << Warning << "\n" << method_name + << " Do not copy the string because a to_string is NULL. " + << (extra_msg == 0 ? "" : extra_msg) << "\n\n"; + } + else { // (from_str && to_str) + int str_len = m_strlen(from_str); + if (str_len > buf_len) str_len = buf_len; + + memset(to_str, 0, str_len); + string temp_str = from_str; + temp_str.copy(to_str, str_len); + to_str[str_len] = 0; + + if (!truncate && strcmp(from_str, to_str)) { + mlog << Warning << "\n" << method_name + << " truncated a string " << (extra_msg == 0 ? "" : extra_msg) + << " from \"" << from_str << "\" to \"" << to_str << "\"\n\n"; + } + } + +} + + diff --git a/met/src/basic/vx_log/str_wrappers.h b/met/src/basic/vx_log/str_wrappers.h new file mode 100644 index 0000000000..d45e7b375c --- /dev/null +++ b/met/src/basic/vx_log/str_wrappers.h @@ -0,0 +1,40 @@ +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +// ** Copyright UCAR (c) 1992 - 2021 +// ** 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 __STR_WRAPPERS_H__ +#define __STR_WRAPPERS_H__ + + +//////////////////////////////////////////////////////////////////////// + +extern int m_strlen(const char *str, bool buf_size=false); + +extern void m_strcpy(char *to_str, const char *from_str, const char *method_name, + const char *extra_msg=(char *)0); +extern char *m_strcpy2(const char *from_str, const char *method_name, + const char *extra_msg=(char *)0); +extern void m_strncpy(char *to_str, const char *from_str, const int buf_len, + const char *method_name, const char *extra_msg=(char *)0, + bool truncate=false); + +//////////////////////////////////////////////////////////////////////// + + +#endif // __STR_WRAPPERS_H__ + + +//////////////////////////////////////////////////////////////////////// + + + + From 003a5fcba54fcf1718776a1bd6bc36c1dc1cb0d5 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 8 Sep 2021 00:49:40 -0600 Subject: [PATCH 160/200] #1903 Added enum_to_string.h. They are moved from enum_to_string.cc --- met/src/basic/enum_to_string/Makefile.am | 2 +- .../basic/enum_to_string/enum_to_string.cc | 6 +- met/src/basic/enum_to_string/enum_to_string.h | 55 +++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 met/src/basic/enum_to_string/enum_to_string.h diff --git a/met/src/basic/enum_to_string/Makefile.am b/met/src/basic/enum_to_string/Makefile.am index 1f03b2ccef..4877eb5147 100644 --- a/met/src/basic/enum_to_string/Makefile.am +++ b/met/src/basic/enum_to_string/Makefile.am @@ -16,7 +16,7 @@ enum_to_string_SOURCES = enum_parser.yy \ code.cc code.h \ scope.cc scope.h \ my_enum_scanner.cc \ - enum_to_string.cc + enum_to_string.cc enum_to_string.h enum_to_string_CPPFLAGS = -DCOPYRIGHT_DIR="\"${abs_top_srcdir}/data\"" ${MET_CPPFLAGS} enum_to_string_LDFLAGS = ${MET_LDFLAGS} enum_to_string_LDADD = -lvx_cal \ diff --git a/met/src/basic/enum_to_string/enum_to_string.cc b/met/src/basic/enum_to_string/enum_to_string.cc index 9ef21eb944..d80452387a 100644 --- a/met/src/basic/enum_to_string/enum_to_string.cc +++ b/met/src/basic/enum_to_string/enum_to_string.cc @@ -32,7 +32,7 @@ using namespace std; #include "scope.h" #include "vx_log.h" -#include "vx_cal.h" +#include "enum_to_string.h" //////////////////////////////////////////////////////////////////////// @@ -129,7 +129,7 @@ int main(int argc, char * argv[]) generation_gmt = time(0); -int j = strlen(argv[0]) - 1; +int j = m_strlen(argv[0]) - 1; while ( (j >= 0) && (argv[0][j] != '/') ) --j; @@ -395,7 +395,7 @@ void yyerror(const char * s) int c; -c = (int) (column - strlen(yytext)); +c = (int) (column - m_strlen(yytext)); cout << "\n\n " << program_name << " -> " << "syntax error in file \"" << header_filename << "\" at line " << LineNumber diff --git a/met/src/basic/enum_to_string/enum_to_string.h b/met/src/basic/enum_to_string/enum_to_string.h new file mode 100644 index 0000000000..0d2baf1c68 --- /dev/null +++ b/met/src/basic/enum_to_string/enum_to_string.h @@ -0,0 +1,55 @@ +// *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* +// ** Copyright UCAR (c) 1992 - 2021 +// ** 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 __ENUM_TO_STRING_H__ +#define __ENUM_TO_STRING_H__ + + +//////////////////////////////////////////////////////////////////////// + + +#include "vx_cal.h" + + +//////////////////////////////////////////////////////////////////////// + + +extern bool do_prefix; + +extern const char * header_suffix; + +extern bool do_angle_brackets; + +extern bool do_array; + +extern bool do_reverse; + +extern bool do_concat_string; + +extern bool verbose; + +extern unixtime generation_gmt; + +extern const char * header_filename; + +extern const char * program_name; + + +//////////////////////////////////////////////////////////////////////// + + +#endif /* __ENUM_TO_STRING_H__ */ + + +//////////////////////////////////////////////////////////////////////// + + From 15907182e9d0d61579c0b184f1f6ac6a9c22a2a3 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 8 Sep 2021 00:52:43 -0600 Subject: [PATCH 161/200] #1903 Moved include statements to the top. Included enum_to_string.h & str_wrappers.h. Changed 0 to NULL to reset the pointer --- met/src/basic/enum_to_string/code.cc | 92 +++++++++------------------- 1 file changed, 28 insertions(+), 64 deletions(-) diff --git a/met/src/basic/enum_to_string/code.cc b/met/src/basic/enum_to_string/code.cc index ed79e593e5..e72238eecf 100644 --- a/met/src/basic/enum_to_string/code.cc +++ b/met/src/basic/enum_to_string/code.cc @@ -10,16 +10,6 @@ //////////////////////////////////////////////////////////////////////// -static const bool do_name_len_decl = true; - -static const bool echo_pound_define_after_endif = true; - -static const char copyright_filename [] = "copyright_notice.txt"; // relative to MET_BASE_DIR - - -//////////////////////////////////////////////////////////////////////// - - using namespace std; @@ -33,43 +23,22 @@ using namespace std; #include #include "code.h" +#include "enum_to_string.h" +#include "str_wrappers.h" #include "vx_cal.h" //////////////////////////////////////////////////////////////////////// -static const char * sep = "////////////////////////////////////////////////////////////////////////\n"; - - -//////////////////////////////////////////////////////////////////////// - - - // - // these have external linkage - // - - -extern bool do_prefix; - -extern const char * header_suffix; - -extern bool do_angle_brackets; - -extern bool do_array; - -extern bool do_reverse; - -extern bool do_concat_string; - -extern bool verbose; +static const bool do_name_len_decl = true; -extern unixtime generation_gmt; +static const bool echo_pound_define_after_endif = true; -extern const char * header_filename; +static const char copyright_filename [] = "copyright_notice.txt"; // relative to MET_BASE_DIR -extern const char * program_name; +static const char * sep = "////////////////////////////////////////////////////////////////////////\n"; //////////////////////////////////////////////////////////////////////// @@ -111,7 +80,7 @@ char upper[256]; char pound_define[256]; char junk[256]; int len, scope_len, max_len; -char * len_name = (char *) 0; +char * len_name = (char *) NULL; // if ( e.scope() ) snprintf(full_id, sizeof(full_id), "%s::%s", e.scope(), e.id(j)); @@ -121,12 +90,12 @@ max_len = 0; -if ( e.scope() ) scope_len = strlen(e.scope()) + 2; // includes "::" +if ( e.scope() ) scope_len = m_strlen(e.scope()) + 2; // includes "::" else scope_len = 0; for (j=0; j<(e.n_ids()); ++j) { - len = strlen(e.id(j)); + len = m_strlen(e.id(j)); len += scope_len; @@ -265,11 +234,6 @@ if ( do_array ) { } -// f << "#endif // " << pound_define << "\n" -// << "\n\n" -// << sep -// << "\n\n"; - f << "#endif"; if ( echo_pound_define_after_endif ) f << " /* " << pound_define << " */\n"; @@ -285,7 +249,7 @@ f << "\n\n" f.close(); -if ( len_name ) { delete [] len_name; len_name = (char *) 0; } +if ( len_name ) { delete [] len_name; len_name = (char *) NULL; } return; @@ -301,7 +265,6 @@ void write_cs_header(const EnumInfo & e) if ( e.n_ids() == 0 ) return; -int j; ofstream f; char filename[256]; char lower[256]; @@ -309,7 +272,7 @@ char upper[256]; char pound_define[256]; char junk[256]; int len, scope_len, max_len; -char * len_name = (char *) 0; +char * len_name = (char *) NULL; // if ( e.scope() ) snprintf(full_id, sizeof(full_id), "%s::%s", e.scope(), e.id(j)); @@ -319,12 +282,12 @@ max_len = 0; -if ( e.scope() ) scope_len = strlen(e.scope()) + 2; // includes "::" +if ( e.scope() ) scope_len = m_strlen(e.scope()) + 2; // includes "::" else scope_len = 0; -for (j=0; j<(e.n_ids()); ++j) { +for (int j=0; j<(e.n_ids()); ++j) { - len = strlen(e.id(j)); + len = m_strlen(e.id(j)); len += scope_len; @@ -486,7 +449,7 @@ f << "\n\n" f.close(); -if ( len_name ) { delete [] len_name; len_name = (char *) 0; } +if ( len_name ) { delete [] len_name; len_name = (char *) NULL; } return; @@ -766,7 +729,7 @@ for (j=0; j<(e.n_ids()); ++j) { if ( e.scope() ) snprintf(full_id, sizeof(full_id), "%s::%s", e.scope(), e.id(j)); else snprintf(full_id, sizeof(full_id), "%s", e.id(j)); - k = strlen(e.id(j)); + k = m_strlen(e.id(j)); out << " " << "case " << full_id << ": "; @@ -850,7 +813,7 @@ for (j=0; j<(e.n_ids()); ++j) { if ( e.scope() ) snprintf(full_id, sizeof(full_id), "%s::%s", e.scope(), e.id(j)); else snprintf(full_id, sizeof(full_id), "%s", e.id(j)); - k = strlen(e.id(j)); + k = m_strlen(e.id(j)); out << " " << "case " << full_id << ": "; @@ -927,7 +890,7 @@ n = e.n_ids(); for (j=0; j= 0) && (header_filename[j] != '/') ) --j; @@ -1118,10 +1081,11 @@ void patch_name(char * len_name) int j, n; int pos; -char * new_name = (char *) 0; +char * new_name = (char *) NULL; char c; +const char *method_name = "patch_name() -> "; -n = strlen(len_name); +n = m_strlen(len_name); new_name = new char [n + 1]; @@ -1151,14 +1115,14 @@ for (j=0; j Date: Wed, 8 Sep 2021 01:05:08 -0600 Subject: [PATCH 162/200] #1903 Moved m_strXXX to str_wrappers. Includes str_wrappers.h instead of string_fxns.h --- met/src/basic/vx_util/ascii_table.cc | 1 - met/src/basic/vx_util/filename_suffix.cc | 1 + met/src/basic/vx_util/get_filenames.cc | 1 - met/src/basic/vx_util/is_number.cc | 2 +- met/src/basic/vx_util/make_path.cc | 1 - met/src/basic/vx_util/ordinal.cc | 1 - met/src/basic/vx_util/roman_numeral.cc | 1 - met/src/basic/vx_util/string_fxns.cc | 135 +++-------------------- met/src/basic/vx_util/string_fxns.h | 9 -- met/src/basic/vx_util/thresh_array.cc | 1 - 10 files changed, 20 insertions(+), 133 deletions(-) diff --git a/met/src/basic/vx_util/ascii_table.cc b/met/src/basic/vx_util/ascii_table.cc index 8e45eed53d..28fb9004d6 100644 --- a/met/src/basic/vx_util/ascii_table.cc +++ b/met/src/basic/vx_util/ascii_table.cc @@ -26,7 +26,6 @@ using namespace std; #include "ascii_table.h" #include "comma_string.h" #include "fix_float.h" -#include "string_fxns.h" #include "util_constants.h" //////////////////////////////////////////////////////////////////////// diff --git a/met/src/basic/vx_util/filename_suffix.cc b/met/src/basic/vx_util/filename_suffix.cc index 0a050964cc..1c20b292bf 100644 --- a/met/src/basic/vx_util/filename_suffix.cc +++ b/met/src/basic/vx_util/filename_suffix.cc @@ -19,6 +19,7 @@ using namespace std; #include #include +#include "str_wrappers.h" #include "string_fxns.h" #include "filename_suffix.h" #include "concat_string.h" diff --git a/met/src/basic/vx_util/get_filenames.cc b/met/src/basic/vx_util/get_filenames.cc index b777c78455..d0067fa437 100644 --- a/met/src/basic/vx_util/get_filenames.cc +++ b/met/src/basic/vx_util/get_filenames.cc @@ -29,7 +29,6 @@ using namespace std; #include "vx_log.h" #include "get_filenames.h" -#include "string_fxns.h" //////////////////////////////////////////////////////////////////////// diff --git a/met/src/basic/vx_util/is_number.cc b/met/src/basic/vx_util/is_number.cc index 4cdebd6d9a..f7bb865cb3 100644 --- a/met/src/basic/vx_util/is_number.cc +++ b/met/src/basic/vx_util/is_number.cc @@ -21,7 +21,7 @@ using namespace std; #include #include "is_number.h" -#include "string_fxns.h" +#include "str_wrappers.h" #include "substring.h" diff --git a/met/src/basic/vx_util/make_path.cc b/met/src/basic/vx_util/make_path.cc index 9fd81b7b5b..53dcb632ca 100644 --- a/met/src/basic/vx_util/make_path.cc +++ b/met/src/basic/vx_util/make_path.cc @@ -26,7 +26,6 @@ using namespace std; #include "make_path.h" #include "vx_log.h" -#include "string_fxns.h" //////////////////////////////////////////////////////////////////////// diff --git a/met/src/basic/vx_util/ordinal.cc b/met/src/basic/vx_util/ordinal.cc index fde21f237d..87ec74679e 100644 --- a/met/src/basic/vx_util/ordinal.cc +++ b/met/src/basic/vx_util/ordinal.cc @@ -21,7 +21,6 @@ using namespace std; #include #include "ordinal.h" -#include "string_fxns.h" #include "vx_log.h" diff --git a/met/src/basic/vx_util/roman_numeral.cc b/met/src/basic/vx_util/roman_numeral.cc index 83b90b8cf4..02bc520282 100644 --- a/met/src/basic/vx_util/roman_numeral.cc +++ b/met/src/basic/vx_util/roman_numeral.cc @@ -21,7 +21,6 @@ using namespace std; #include #include "roman_numeral.h" -#include "string_fxns.h" #include "vx_log.h" diff --git a/met/src/basic/vx_util/string_fxns.cc b/met/src/basic/vx_util/string_fxns.cc index 8e477d073c..3ab58e411c 100644 --- a/met/src/basic/vx_util/string_fxns.cc +++ b/met/src/basic/vx_util/string_fxns.cc @@ -31,8 +31,6 @@ using namespace std; #include "vx_log.h" -const bool ENHANCE_STR_APIS = false; - //////////////////////////////////////////////////////////////////////// @@ -114,7 +112,7 @@ const char * get_short_name(const char * path) { -const char * short_name = (const char *) 0; +const char * short_name = (const char *) NULL; if ( path ) { int j; @@ -140,7 +138,7 @@ return ( short_name ); void append_char(char *str, const char c) { - char *ptr = (char *) 0; + char *ptr = (char *) NULL; // // If the specified characater does not already exist at the @@ -166,7 +164,7 @@ void append_char(char *str, const char c) void strip_char(char *str, const char c) { - char *ptr = (char *) 0; + char *ptr = (char *) NULL; // // If the specified character exists at the end of the string, @@ -188,9 +186,9 @@ void strip_char(char *str, const char c) int num_tokens(const char *test_str, const char *separator) { - int n; - char *temp_str = (char *) 0; - char *c = (char *) 0; + int n = 0; + char *temp_str = (char *) NULL; + char *c = (char *) NULL; const char *method_name = "num_tokens() -> "; // @@ -216,18 +214,19 @@ int num_tokens(const char *test_str, const char *separator) // // Check for an empty string // - if(!c) { delete [] temp_str; temp_str = 0; return(0); } - else n = 1; - - // - // Parse remaining tokens - // - // - while((c = strtok(0, separator)) != NULL) n++; + if(c) { + n = 1; + + // + // Parse remaining tokens + // + // + while((c = strtok(0, separator)) != NULL) n++; + } } - if(temp_str) { delete [] temp_str; temp_str = (char *) 0; } + if(temp_str) { delete [] temp_str; temp_str = (char *) NULL; } return(n); } @@ -309,7 +308,7 @@ int regex_apply(const char* pat, int num_mat, const char* str, char** &mat) } regfree(re); - if( re ) { delete re; re = 0; } + if( re ) { delete re; re = NULL; } return num_act; } @@ -384,7 +383,7 @@ ConcatString str_trim(const ConcatString str){ int parse_thresh_index(const char *col_name) { int i = 0; - const char *ptr = (const char *) 0; + const char *ptr = (const char *) NULL; if((ptr = strrchr(col_name, '_')) != NULL) i = atoi(++ptr); else { @@ -397,102 +396,4 @@ int parse_thresh_index(const char *col_name) { return(i); } -//////////////////////////////////////////////////////////////////////// - -int m_strlen(const char *str) { - int str_len = 0; - if (str) str_len = strlen(str); // or use sizeof str; - - return str_len; -} - -//////////////////////////////////////////////////////////////////////// -// to_string is allocated. - -void m_strcpy(char *to_str, const char *from_str, const char *method_name, - const char *extra_msg) { - - if (ENHANCE_STR_APIS) { - int str_len = sizeof to_str; - m_strncpy(to_str, from_str, str_len, method_name, extra_msg); - } - else strcpy(to_str, from_str); - -} - -//////////////////////////////////////////////////////////////////////// -// to_string is not allocated. Allocate to_string and return the to_string after copying - -char *m_strcpy2(const char *from_str, const char *method_name, const char *extra_msg) { - char *to_str = (char *) 0; - if (from_str) { - int str_len = m_strlen(from_str); - - to_str = new char[str_len + 1]; - - if(!to_str) { - mlog << Error << "\n" << method_name - << "memory allocation error (m_strcpy)" - << (extra_msg == 0 ? "" : extra_msg) << "\n\n"; - exit(1); - } - - m_strcpy(to_str, from_str, method_name, extra_msg); - } - else { - mlog << Error << "\n" << method_name - << " Do not copy the string because a from_string is NULL. " - << (extra_msg == 0 ? "" : extra_msg) << "\n\n"; - } - - return to_str; -} - -//////////////////////////////////////////////////////////////////////// - -void m_strncpy(char *to_str, const char *from_str, const int buf_len, - const char *method_name, const char *extra_msg) { - if (!from_str){ - mlog << Warning << "\n" << method_name - << " Do not copy the string because a from_string is NULL. " - << (extra_msg == 0 ? "" : extra_msg) << "\n\n"; - } - else if (!to_str){ - mlog << Warning << "\n" << method_name - << " Do not copy the string because a to_string is NULL. " - << (extra_msg == 0 ? "" : extra_msg) << "\n\n"; - } - else { // (from_str && to_str) - int str_len = m_strlen(from_str); - if (str_len > buf_len) str_len = buf_len; - - memset(to_str, 0, str_len); - if (ENHANCE_STR_APIS) { - string temp_str = from_str; - temp_str.copy(to_str, str_len); - to_str[str_len] = 0; - - // Kludge: The sizeof from_str is 8 when the filenames come from a python script - if (strcmp(from_str, to_str)) { - str_len = m_strlen(from_str); - if (str_len > buf_len) str_len = buf_len; - temp_str.copy(to_str, str_len); - to_str[str_len] = 0; - } - } - else { - strncpy(to_str, from_str, str_len); - to_str[str_len] = 0; - } - - if (strcmp(from_str, to_str)) { - mlog << Warning << "\n" << method_name - << " truncated a string " << (extra_msg == 0 ? "" : extra_msg) - << " from \"" << from_str << "\" to \"" << to_str << "\"\n\n"; - } - } - -} - - //////////////////////////////////////////////////////////////////////// diff --git a/met/src/basic/vx_util/string_fxns.h b/met/src/basic/vx_util/string_fxns.h index b64edbbb86..84db62c4b1 100644 --- a/met/src/basic/vx_util/string_fxns.h +++ b/met/src/basic/vx_util/string_fxns.h @@ -59,15 +59,6 @@ extern ConcatString str_trim(const ConcatString str); extern int parse_thresh_index(const char *str); -extern int m_strlen(const char *str); - -extern void m_strcpy(char *to_str, const char *from_str, const char *method_name, - const char *extra_msg=(char *)0); -extern char *m_strcpy2(const char *from_str, const char *method_name, - const char *extra_msg=(char *)0); -extern void m_strncpy(char *to_str, const char *from_str, const int buf_len, - const char *method_name, const char *extra_msg=(char *)0); - //////////////////////////////////////////////////////////////////////// diff --git a/met/src/basic/vx_util/thresh_array.cc b/met/src/basic/vx_util/thresh_array.cc index 2dd8b1fd9d..75ea29b4ff 100644 --- a/met/src/basic/vx_util/thresh_array.cc +++ b/met/src/basic/vx_util/thresh_array.cc @@ -18,7 +18,6 @@ using namespace std; #include "thresh_array.h" #include "vx_math.h" #include "vx_log.h" -#include "string_fxns.h" //////////////////////////////////////////////////////////////////////// From 4e241fc2acefe57fe51a6c499448ecee19ebbdc9 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 8 Sep 2021 01:06:43 -0600 Subject: [PATCH 163/200] #1903 Changed strXXX to m_strXXX --- met/src/basic/enum_to_string/info.cc | 66 ++++++++++--------- .../basic/enum_to_string/my_enum_scanner.cc | 4 +- met/src/basic/enum_to_string/scope.cc | 10 +-- 3 files changed, 44 insertions(+), 36 deletions(-) diff --git a/met/src/basic/enum_to_string/info.cc b/met/src/basic/enum_to_string/info.cc index ba716a3ce1..52c5ab8471 100644 --- a/met/src/basic/enum_to_string/info.cc +++ b/met/src/basic/enum_to_string/info.cc @@ -20,6 +20,7 @@ using namespace std; #include #include "info.h" +#include "str_wrappers.h" //////////////////////////////////////////////////////////////////////// @@ -93,17 +94,17 @@ void EnumInfo::init_from_scratch() { -s = (char **) 0; +s = (char **) NULL; -Name = (char *) 0; +Name = (char *) NULL; -LowerCaseName = (char *) 0; +LowerCaseName = (char *) NULL; -Scope = (char *) 0; +Scope = (char *) NULL; -U_Scope = (char *) 0; +U_Scope = (char *) NULL; -Header = (char *) 0; +Header = (char *) NULL; Nalloc = Nids = 0; @@ -126,21 +127,21 @@ int j; for (j=0; j max_len ) max_len = k; @@ -287,14 +288,15 @@ void EnumInfo::add_id(const char * text) { int k; +const char *method_name = "EnumInfo::add_id() -> "; extend(Nids + 1); -k = strlen(text); +k = m_strlen(text); s[Nids] = new char [1 + k]; -strncpy(s[Nids], text, k); +m_strncpy(s[Nids], text, k, method_name); s[Nids][k] = (char) 0; // just to make sure @@ -311,26 +313,27 @@ return; void EnumInfo::set_name(const char * text) { +const char *method_name = "EnumInfo::set_name() -> "; -if ( Name ) { delete [] Name; Name = (char *) 0; } +if ( Name ) { delete [] Name; Name = (char *) NULL; } -if ( LowerCaseName ) { delete [] LowerCaseName; LowerCaseName = (char *) 0; } +if ( LowerCaseName ) { delete [] LowerCaseName; LowerCaseName = (char *) NULL; } if ( !text ) return; int j, k; -k = strlen(text); +k = m_strlen(text); Name = new char [1 + k]; LowerCaseName = new char [1 + k]; -strncpy(Name, text, k); +m_strncpy(Name, text, k, method_name, "Name"); Name[k] = (char) 0; // just to make sure -strncpy(LowerCaseName, text, k); +m_strncpy(LowerCaseName, text, k, method_name, "LowerCaseName"); LowerCaseName[k] = (char) 0; // just to make sure @@ -349,12 +352,12 @@ return; void EnumInfo::set_scope(const char * text) - { +const char *method_name = "EnumInfo::set_scope() -> "; -if ( Scope ) { delete [] Scope; Scope = (char *) 0; } +if ( Scope ) { delete [] Scope; Scope = (char *) NULL; } -if ( U_Scope ) { delete [] U_Scope; U_Scope = (char *) 0; } +if ( U_Scope ) { delete [] U_Scope; U_Scope = (char *) NULL; } if ( !text ) return; @@ -362,11 +365,11 @@ int j, k, m; char c; -k = strlen(text); +k = m_strlen(text); Scope = new char [1 + k]; -strncpy(Scope, text, k); +m_strncpy(Scope, text, k, method_name); Scope[k] = (char) 0; // just to make sure @@ -399,16 +402,17 @@ return; void EnumInfo::set_header(const char * text) { +const char *method_name = "EnumInfo::set_header() -> "; -if ( Header ) { delete [] Header; Header = (char *) 0; } +if ( Header ) { delete [] Header; Header = (char *) NULL; } int k; -k = strlen(text); +k = m_strlen(text); Header = new char [1 + k]; -strncpy(Header, text, k); +m_strncpy(Header, text, k, method_name); Header[k] = (char) 0; // just to make sure diff --git a/met/src/basic/enum_to_string/my_enum_scanner.cc b/met/src/basic/enum_to_string/my_enum_scanner.cc index 65b89273ab..fd03afccf8 100644 --- a/met/src/basic/enum_to_string/my_enum_scanner.cc +++ b/met/src/basic/enum_to_string/my_enum_scanner.cc @@ -20,6 +20,7 @@ using namespace std; #include "scope.h" +#include "str_wrappers.h" //////////////////////////////////////////////////////////////////////// @@ -431,10 +432,11 @@ return; int do_id() { +const char *method_name = "do_id()"; if ( enum_mode || last_was_enum || last_was_class ) { - strncpy(yylval.name, yytext, sizeof(yylval.name)); + m_strncpy(yylval.name, yytext, sizeof(yylval.name), method_name); return ( 1 ); diff --git a/met/src/basic/enum_to_string/scope.cc b/met/src/basic/enum_to_string/scope.cc index 703d3b5215..86d094d3b0 100644 --- a/met/src/basic/enum_to_string/scope.cc +++ b/met/src/basic/enum_to_string/scope.cc @@ -20,6 +20,8 @@ using namespace std; #include #include "scope.h" +#include "str_wrappers.h" + //////////////////////////////////////////////////////////////////////// @@ -129,7 +131,7 @@ return; void ScopeStackElement::set_name(const char * text) { - +const char *method_name = "void ScopeStackElement::set_name(const char *) -> "; if ( Name ) { delete [] Name; Name = (const char *) 0; } if ( !text ) return; @@ -137,19 +139,19 @@ if ( !text ) return; int k; char * c = (char *) 0; -k = strlen(text); +k = m_strlen(text); c = new char [1 + k]; if ( !c ) { - cerr << "\n\n void ScopeStackElement::set_name(const char *) -> memory allocation error\n\n"; + cerr << "\n\n " << method_name << "memory allocation error\n\n"; exit ( 1 ); } -strncpy(c, text, k); +m_strncpy(c, text, k, method_name); c[k] = (char) 0; // just to make sure From b59eeaffde83b164759511139adb54ebdc3092b7 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 8 Sep 2021 01:08:19 -0600 Subject: [PATCH 164/200] #1903 Chaged dst_info to const --- met/src/basic/vx_cal/is_dst.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/src/basic/vx_cal/is_dst.cc b/met/src/basic/vx_cal/is_dst.cc index 57b9b2dfb0..94fb1be5a4 100644 --- a/met/src/basic/vx_cal/is_dst.cc +++ b/met/src/basic/vx_cal/is_dst.cc @@ -36,7 +36,7 @@ struct DstInfo { }; -static DstInfo dst_info[] = { +const static DstInfo dst_info[] = { { 4, 2, 10, 29 }, // 0 { 4, 1, 10, 28 }, // 1 From 7ff85de033da9f6b3102fcbb0e508d79cceb4f5c Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 8 Sep 2021 10:47:50 -0600 Subject: [PATCH 165/200] #1903 Separated two || conditions to avoid potential side effect --- met/src/basic/vx_config/my_config_scanner.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/met/src/basic/vx_config/my_config_scanner.cc b/met/src/basic/vx_config/my_config_scanner.cc index 376fa10f5f..72c7e06e72 100644 --- a/met/src/basic/vx_config/my_config_scanner.cc +++ b/met/src/basic/vx_config/my_config_scanner.cc @@ -26,7 +26,6 @@ using namespace std; #include "math_constants.h" #include "util_constants.h" #include "is_number.h" -#include "string_fxns.h" #include "dictionary.h" #include "builtin.h" @@ -1028,7 +1027,11 @@ if ( c == '$' ) { memset(env_name, 0, sizeof(env_name)); - while ( (env_pos < max_id_length) && ((c = fgetc(configin)) != R_curly) ) env_name[env_pos++] = (char) c; + // SonarQube: to avoid side effect by || operator + while (env_pos < max_id_length) { + if ((c = fgetc(configin)) == R_curly) break; + env_name[env_pos++] = (char) c; + } e = getenv ( env_name ); From cb10a135509a46fbf9e65926381ad5763484fa93 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 8 Sep 2021 11:15:19 -0600 Subject: [PATCH 166/200] #1903 Avoid the negative offset if the string length is 0 --- met/src/libcode/vx_tc_util/track_info.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/met/src/libcode/vx_tc_util/track_info.cc b/met/src/libcode/vx_tc_util/track_info.cc index 3d95a084e1..a1b030e1aa 100644 --- a/met/src/libcode/vx_tc_util/track_info.cc +++ b/met/src/libcode/vx_tc_util/track_info.cc @@ -606,11 +606,12 @@ bool TrackInfo::is_match(const TrackInfo &t) const { bool TrackInfo::is_interp() const { const char *s = Technique.c_str(); - - s += (m_strlen(Technique.c_str()) - 1); + int offset = (m_strlen(Technique.c_str()) - 1); // Return true if the last character of the model name is 'I' - return(*s == 'I'); + if offset < 0) return false; + else return(s[offset] == 'I'); + } //////////////////////////////////////////////////////////////////////// From 33c53c9563e62fe543345475f83762ff4becb744 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 8 Sep 2021 11:17:00 -0600 Subject: [PATCH 167/200] #1903 make sure the pointer is not NULL before releasing --- met/src/tools/other/mode_graphics/cgraph_main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/src/tools/other/mode_graphics/cgraph_main.cc b/met/src/tools/other/mode_graphics/cgraph_main.cc index eecf104a3c..4aed3893ce 100644 --- a/met/src/tools/other/mode_graphics/cgraph_main.cc +++ b/met/src/tools/other/mode_graphics/cgraph_main.cc @@ -1048,7 +1048,7 @@ if ( render_flag ) { // done // -if ( DoLigatures ) { delete [] new_string; new_string = (char *) 0; } +if ( DoLigatures && new_string != NULL ) { delete [] new_string; new_string = (char *) 0; } return; From cf8bea6bb70d21904c6b42a9ec76f01f4684dfaa Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 8 Sep 2021 11:22:32 -0600 Subject: [PATCH 168/200] #1903 Replaced strXXX to m_strXXX. Separated two || conditions to avoid the potential side effects --- met/src/basic/vx_log/concat_string.cc | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/met/src/basic/vx_log/concat_string.cc b/met/src/basic/vx_log/concat_string.cc index d35497884c..2f4e6550dd 100644 --- a/met/src/basic/vx_log/concat_string.cc +++ b/met/src/basic/vx_log/concat_string.cc @@ -22,6 +22,7 @@ using namespace std; #include "concat_string.h" #include "logger.h" +#include "str_wrappers.h" //////////////////////////////////////////////////////////////////////// @@ -76,7 +77,7 @@ ConcatString::~ConcatString() { clear(); -delete s; +if (s) delete s; } @@ -333,7 +334,7 @@ void ConcatString::chomp(const char c) void ConcatString::chomp(const char * suffix) { - size_t limit = length() - strlen(suffix); + size_t limit = length() - m_strlen(suffix); size_t pos = s->find(suffix, limit); if (pos != string::npos) s->erase(pos); } @@ -400,7 +401,7 @@ void ConcatString::elim_trailing_whitespace() bool ConcatString::startswith(const char * Text) const { - size_t pos = s->rfind(Text, strlen(Text)); + size_t pos = s->rfind(Text, m_strlen(Text)); return (pos != string::npos); } @@ -410,7 +411,7 @@ bool ConcatString::startswith(const char * Text) const bool ConcatString::endswith(const char * Text) const { - size_t pos = s->find(Text, s->length() - strlen(Text)); + size_t pos = s->find(Text, s->length() - m_strlen(Text)); return (pos != string::npos); } @@ -539,7 +540,7 @@ int ConcatString::format(const char *fmt, ...) { va_list vl; int status = -1; - char *tmp; + char *tmp = NULL; va_start(vl, fmt); status = vasprintf(&tmp, fmt, vl); @@ -587,7 +588,7 @@ void ConcatString::replace(const char * target, const char * replacement, size_t pos; while ((pos = s->find(target)) != string::npos) { - s->replace(pos, strlen(target), replacement); + s->replace(pos, m_strlen(target), replacement); } } @@ -1189,7 +1190,7 @@ bool is_empty(const char * text) { -return ( (text == NULL) || (*text == 0) || (strlen(text) == 0)); +return ( (text == NULL) || (*text == 0) || (m_strlen(text) == 0)); } @@ -1208,10 +1209,9 @@ static const char *method_name = "get_env() "; // Initialize env_value.clear(); -if (str.find('/') != string::npos || - (ptr = getenv(env_name)) == NULL) { - return(false); -} +// SonarQube: two ifs to avoid the side effect by the logical || operator +if (str.find('/') != string::npos) return(false); +if ((ptr = getenv(env_name)) == NULL) return(false); env_value = ptr; str = env_value; From 30f71aebacc2bea48b63501cf16da46b2fe0faba Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 8 Sep 2021 11:25:41 -0600 Subject: [PATCH 169/200] #1903 Allow to truncate the string on calling m_strncpy --- met/src/tools/other/pb2nc/pb2nc.cc | 21 ++++++++++++++------- met/src/tools/tc_utils/tc_dland/tc_poly.cc | 4 ++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/met/src/tools/other/pb2nc/pb2nc.cc b/met/src/tools/other/pb2nc/pb2nc.cc index 588e3a62e7..e0c0416670 100644 --- a/met/src/tools/other/pb2nc/pb2nc.cc +++ b/met/src/tools/other/pb2nc/pb2nc.cc @@ -672,7 +672,8 @@ void get_variable_info(const char* tbl_filename) { } if ('0' != line[BUFR_NUMBER_START]) continue; - m_strncpy(var_name, (line+BUFR_NAME_START), BUFR_NAME_LEN, method_name, "var_name"); + m_strncpy(var_name, (line+BUFR_NAME_START), BUFR_NAME_LEN, + method_name, "var_name", true); var_name[BUFR_NAME_LEN] = '\0'; for (int idx=(BUFR_NAME_LEN-1); idx >=0; idx--) { if (' ' != var_name[idx] ) break; @@ -681,7 +682,8 @@ void get_variable_info(const char* tbl_filename) { if (0 == m_strlen(var_name)) continue; var_count1++; - m_strncpy(var_desc, (line+BUFR_DESCRIPTION_START), BUFR_DESCRIPTION_LEN, method_name, "var_desc"); + m_strncpy(var_desc, (line+BUFR_DESCRIPTION_START), BUFR_DESCRIPTION_LEN, + method_name, "var_desc", true); var_desc[BUFR_DESCRIPTION_LEN] = '\0'; for (int idx=(BUFR_DESCRIPTION_LEN-1); idx>=0; idx--) { if (' ' != var_desc[idx] && '|' != var_desc[idx]) { @@ -700,7 +702,8 @@ void get_variable_info(const char* tbl_filename) { if (NULL != strstr(line,"MNEMONIC")) break; if (NULL == strstr(line,"EVENT")) continue; - m_strncpy(var_name, (line+BUFR_NAME_START), BUFR_NAME_LEN, method_name, "var_name2"); + m_strncpy(var_name, (line+BUFR_NAME_START), BUFR_NAME_LEN, + method_name, "var_name2", true); var_name[BUFR_NAME_LEN] = '\0'; for (int idx=(BUFR_NAME_LEN-1); idx >=0; idx--) { if (' ' != var_name[idx] ) break; @@ -708,7 +711,8 @@ void get_variable_info(const char* tbl_filename) { } //if (NULL == strstr(var_name,"EVENT")) continue; - m_strncpy(var_desc, (line+BUFR_SEQUENCE_START), BUFR_SEQUENCE_LEN, method_name, "var_desc2"); + m_strncpy(var_desc, (line+BUFR_SEQUENCE_START), BUFR_SEQUENCE_LEN, + method_name, "var_desc2", true); var_desc[BUFR_SEQUENCE_LEN] = '\0'; for (int idx=(BUFR_SEQUENCE_LEN-1); idx>=0; idx--) { if (' ' != var_desc[idx] && '|' != var_desc[idx]) { @@ -728,7 +732,8 @@ void get_variable_info(const char* tbl_filename) { if (' ' == line[BUFR_NAME_START]) continue; if ('-' == line[BUFR_NAME_START]) break; - m_strncpy(var_name, (line+BUFR_NAME_START), BUFR_NAME_LEN, method_name, "var_name3"); + m_strncpy(var_name, (line+BUFR_NAME_START), BUFR_NAME_LEN, + method_name, "var_name3", true); var_name[BUFR_NAME_LEN] = '\0'; for (int idx=(BUFR_NAME_LEN-1); idx >=0; idx--) { if (' ' != var_name[idx] ) break; @@ -737,10 +742,12 @@ void get_variable_info(const char* tbl_filename) { if (NULL != strstr(line,"CCITT IA5")) { ascii_vars.add(var_name); - m_strncpy(var_unit_str, "CCITT IA5", sizeof(var_unit_str), method_name, "var_unit_str1"); + m_strncpy(var_unit_str, "CCITT IA5", sizeof(var_unit_str), + method_name, "var_unit_str1", true); } else { - m_strncpy(var_unit_str, (line+BUFR_UNIT_START), BUFR_UNIT_LEN, method_name, "var_unit_str2"); + m_strncpy(var_unit_str, (line+BUFR_UNIT_START), BUFR_UNIT_LEN, + method_name, "var_unit_str2", true); var_unit_str[BUFR_UNIT_LEN] = '\0'; for (int idx=(BUFR_UNIT_LEN-1); idx>=0; idx--) { if (' ' != var_unit_str[idx] && '|' != var_unit_str[idx]) { diff --git a/met/src/tools/tc_utils/tc_dland/tc_poly.cc b/met/src/tools/tc_utils/tc_dland/tc_poly.cc index 16560e110b..650e2197b8 100644 --- a/met/src/tools/tc_utils/tc_dland/tc_poly.cc +++ b/met/src/tools/tc_utils/tc_dland/tc_poly.cc @@ -353,7 +353,7 @@ double TCPolyArray::min_dist(double lat, double lon, int &imin) const { bool operator>>(istream & in, TCPoly & p) { int i, n; double x, y; - const char *method_name = "operator>> -> "; + const char *method_name = "TCPolyArray::operator>> -> "; p.clear(); @@ -371,7 +371,7 @@ bool operator>>(istream & in, TCPoly & p) { // NNN is the 3-digit number of points // AAAAAAAA is the 8-character name of the region n = atoi(a[0].c_str()); - m_strncpy(name, line.c_str()+4, 8, method_name); + m_strncpy(name, line.c_str()+4, 8, method_name, "name", true); name[8] = '\0'; name_cs = name; name_cs.ws_strip(); From a598da8d5eecccd50f100cb7ddd089258fe0048b Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 8 Sep 2021 11:27:35 -0600 Subject: [PATCH 170/200] #1903 Replaced strXXX calls to m_strXXX --- met/src/basic/vx_cal/time_array.cc | 10 +++++----- met/src/basic/vx_cal/time_strings.cc | 4 ++-- met/src/basic/vx_config/config_util.cc | 1 - met/src/basic/vx_config/icode.cc | 1 - met/src/basic/vx_log/vx_log.h | 2 +- met/src/libcode/vx_afm/afm.cc | 8 +++----- met/src/libcode/vx_color/my_color_scanner.cc | 2 +- met/src/libcode/vx_data2d_factory/is_bufr_file.cc | 3 --- met/src/libcode/vx_data2d_factory/parse_file_list.cc | 1 - met/src/libcode/vx_data2d_grib/data2d_grib_utils.cc | 1 - met/src/libcode/vx_data2d_grib2/data2d_grib2.cc | 1 - met/src/libcode/vx_data2d_python/data2d_python.cc | 2 +- met/src/libcode/vx_ps/ps_text.cc | 1 - met/src/libcode/vx_pxm/pbm.cc | 1 - met/src/libcode/vx_pxm/pcm.cc | 1 - met/src/libcode/vx_pxm/pgm.cc | 1 - met/src/libcode/vx_pxm/ppm.cc | 1 - met/src/libcode/vx_pxm/pxm_base.cc | 1 - met/src/libcode/vx_python3_utils/python3_script.cc | 1 - met/src/libcode/vx_python3_utils/wchar_argv.cc | 3 --- met/src/tools/other/mode_time_domain/nc_utils_local.cc | 1 - met/src/tools/other/wwmca_tool/wwmca_plot.cc | 2 +- 22 files changed, 14 insertions(+), 35 deletions(-) diff --git a/met/src/basic/vx_cal/time_array.cc b/met/src/basic/vx_cal/time_array.cc index cbbf8aa8eb..2dab0d0d9c 100644 --- a/met/src/basic/vx_cal/time_array.cc +++ b/met/src/basic/vx_cal/time_array.cc @@ -98,7 +98,7 @@ void TimeArray::init_from_scratch() { -e = (unixtime*) 0; +e = (unixtime*) NULL; clear(); @@ -114,7 +114,7 @@ void TimeArray::clear() { -if ( e ) { delete [] e; e = (unixtime *) 0; } +if ( e ) { delete [] e; e = (unixtime *) NULL; } Nelements = Nalloc = 0; @@ -194,7 +194,7 @@ if ( ! exact ) { } -unixtime * u = (unixtime *) 0; +unixtime * u = (unixtime *) NULL; u = new unixtime [n]; @@ -219,11 +219,11 @@ if ( e ) { } - delete [] e; e = (unixtime *) 0; + delete [] e; e = (unixtime *) NULL; } -e = u; u = (unixtime *) 0; +e = u; u = (unixtime *) NULL; Nalloc = n; diff --git a/met/src/basic/vx_cal/time_strings.cc b/met/src/basic/vx_cal/time_strings.cc index d15dea5280..51aec9d8a2 100644 --- a/met/src/basic/vx_cal/time_strings.cc +++ b/met/src/basic/vx_cal/time_strings.cc @@ -532,7 +532,7 @@ if ( !text ) { exit ( 1 ); } -else if ( strlen(text) == 0 ) { +else if ( m_strlen(text) == 0 ) { mlog << Error << "\ntimestring_to_unix(const char *) -> " << "empty time string!\n\n"; @@ -707,7 +707,7 @@ if ( !text ) { exit ( 1 ); } -else if ( strlen(text) == 0 ) { +else if ( m_strlen(text) == 0 ) { mlog << Error << "\ntimestring_to_sec(const char *) -> " << "empty time string!\n\n"; diff --git a/met/src/basic/vx_config/config_util.cc b/met/src/basic/vx_config/config_util.cc index 70f718a90d..094e429bb7 100644 --- a/met/src/basic/vx_config/config_util.cc +++ b/met/src/basic/vx_config/config_util.cc @@ -18,7 +18,6 @@ using namespace std; #include "vx_math.h" #include "vx_util.h" -#include "string_fxns.h" #include "GridTemplate.h" diff --git a/met/src/basic/vx_config/icode.cc b/met/src/basic/vx_config/icode.cc index 6ce8b1f903..33daf15cd9 100644 --- a/met/src/basic/vx_config/icode.cc +++ b/met/src/basic/vx_config/icode.cc @@ -29,7 +29,6 @@ using namespace std; #include "indent.h" #include "icode.h" #include "dictionary.h" -#include "string_fxns.h" #include "celltype_to_string.h" diff --git a/met/src/basic/vx_log/vx_log.h b/met/src/basic/vx_log/vx_log.h index 3dfa05f868..7ffb9d3ab8 100644 --- a/met/src/basic/vx_log/vx_log.h +++ b/met/src/basic/vx_log/vx_log.h @@ -24,7 +24,7 @@ using namespace std; #include "string_array.h" #include "file_fxns.h" #include "logger.h" - +#include "str_wrappers.h" //////////////////////////////////////////////////////////////////////// diff --git a/met/src/libcode/vx_afm/afm.cc b/met/src/libcode/vx_afm/afm.cc index 57c168ca4a..d8355916ef 100644 --- a/met/src/libcode/vx_afm/afm.cc +++ b/met/src/libcode/vx_afm/afm.cc @@ -26,7 +26,6 @@ using namespace std; #include "afm_token.h" #include "vx_log.h" -#include "string_fxns.h" //////////////////////////////////////////////////////////////////////// @@ -2284,11 +2283,10 @@ if ( s ) { delete [] s; s = (char *) 0; } if ( !text ) return; -int buf_len = m_strlen(text); -s = new char [1 + buf_len]; -const char *method_name = "set_string()"; +const char *method_name = "afm set_string()"; + +s = m_strcpy2(text, method_name); -m_strcpy(s, text, method_name); return; diff --git a/met/src/libcode/vx_color/my_color_scanner.cc b/met/src/libcode/vx_color/my_color_scanner.cc index c845be959d..96500f4d37 100644 --- a/met/src/libcode/vx_color/my_color_scanner.cc +++ b/met/src/libcode/vx_color/my_color_scanner.cc @@ -16,7 +16,7 @@ using namespace std; #include -#include "string_fxns.h" +#include "str_wrappers.h" #include "color_parser.h" // this must be included before color_parser_yacc.h #include "color.h" diff --git a/met/src/libcode/vx_data2d_factory/is_bufr_file.cc b/met/src/libcode/vx_data2d_factory/is_bufr_file.cc index 7ecfd1d5b5..78773558d7 100644 --- a/met/src/libcode/vx_data2d_factory/is_bufr_file.cc +++ b/met/src/libcode/vx_data2d_factory/is_bufr_file.cc @@ -1,5 +1,3 @@ - - // *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* // ** Copyright UCAR (c) 1992 - 2021 // ** University Corporation for Atmospheric Research (UCAR) @@ -27,7 +25,6 @@ using namespace std; #include "is_bufr_file.h" #include "vx_log.h" -#include "string_fxns.h" //////////////////////////////////////////////////////////////////////// diff --git a/met/src/libcode/vx_data2d_factory/parse_file_list.cc b/met/src/libcode/vx_data2d_factory/parse_file_list.cc index b8cd615fd2..cd01087acc 100644 --- a/met/src/libcode/vx_data2d_factory/parse_file_list.cc +++ b/met/src/libcode/vx_data2d_factory/parse_file_list.cc @@ -30,7 +30,6 @@ using namespace std; #include "parse_file_list.h" #include "data2d_factory_utils.h" -#include "string_fxns.h" //////////////////////////////////////////////////////////////////////// diff --git a/met/src/libcode/vx_data2d_grib/data2d_grib_utils.cc b/met/src/libcode/vx_data2d_grib/data2d_grib_utils.cc index 4ef896f158..a1f01334a8 100644 --- a/met/src/libcode/vx_data2d_grib/data2d_grib_utils.cc +++ b/met/src/libcode/vx_data2d_grib/data2d_grib_utils.cc @@ -21,7 +21,6 @@ using namespace std; #include "data2d_grib_utils.h" #include "angles.h" #include "is_bad_data.h" -#include "string_fxns.h" #include "vx_log.h" #include "vx_math.h" diff --git a/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc b/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc index 82168ac52b..20dc3681d2 100644 --- a/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc +++ b/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc @@ -27,7 +27,6 @@ using namespace std; #include "data2d_grib2.h" #include "grib_strings.h" -#include "string_fxns.h" #include "vx_data2d.h" #include "vx_math.h" #include "vx_log.h" diff --git a/met/src/libcode/vx_data2d_python/data2d_python.cc b/met/src/libcode/vx_data2d_python/data2d_python.cc index 56998a706f..e246dc8ca2 100644 --- a/met/src/libcode/vx_data2d_python/data2d_python.cc +++ b/met/src/libcode/vx_data2d_python/data2d_python.cc @@ -180,7 +180,7 @@ if ( file_argc > 0 ) { for ( i=0; i #include "vx_log.h" -#include "string_fxns.h" #include "ps_text.h" diff --git a/met/src/libcode/vx_pxm/pbm.cc b/met/src/libcode/vx_pxm/pbm.cc index d38539a330..7271fa570e 100644 --- a/met/src/libcode/vx_pxm/pbm.cc +++ b/met/src/libcode/vx_pxm/pbm.cc @@ -25,7 +25,6 @@ using namespace std; #include #include "vx_log.h" -#include "string_fxns.h" #include "pbm.h" #include "pxm_utils.h" diff --git a/met/src/libcode/vx_pxm/pcm.cc b/met/src/libcode/vx_pxm/pcm.cc index 6b96bf5ae4..299c931211 100644 --- a/met/src/libcode/vx_pxm/pcm.cc +++ b/met/src/libcode/vx_pxm/pcm.cc @@ -29,7 +29,6 @@ using namespace std; #include "vx_log.h" #include "vx_math.h" -#include "string_fxns.h" //////////////////////////////////////////////////////////////////////// diff --git a/met/src/libcode/vx_pxm/pgm.cc b/met/src/libcode/vx_pxm/pgm.cc index 9b73d3b4df..17ae16aefb 100644 --- a/met/src/libcode/vx_pxm/pgm.cc +++ b/met/src/libcode/vx_pxm/pgm.cc @@ -28,7 +28,6 @@ using namespace std; #include "vx_log.h" #include "vx_math.h" -#include "string_fxns.h" //////////////////////////////////////////////////////////////////////// diff --git a/met/src/libcode/vx_pxm/ppm.cc b/met/src/libcode/vx_pxm/ppm.cc index a5df76dc77..9a33b4b28a 100644 --- a/met/src/libcode/vx_pxm/ppm.cc +++ b/met/src/libcode/vx_pxm/ppm.cc @@ -29,7 +29,6 @@ using namespace std; #include "vx_log.h" #include "vx_math.h" -#include "string_fxns.h" //////////////////////////////////////////////////////////////////////// diff --git a/met/src/libcode/vx_pxm/pxm_base.cc b/met/src/libcode/vx_pxm/pxm_base.cc index 1946f1d289..2a668bee88 100644 --- a/met/src/libcode/vx_pxm/pxm_base.cc +++ b/met/src/libcode/vx_pxm/pxm_base.cc @@ -23,7 +23,6 @@ using namespace std; #include "pxm_base.h" #include "vx_log.h" -#include "string_fxns.h" #include "check_endian.h" diff --git a/met/src/libcode/vx_python3_utils/python3_script.cc b/met/src/libcode/vx_python3_utils/python3_script.cc index d9ac7f41e5..ec022ce765 100644 --- a/met/src/libcode/vx_python3_utils/python3_script.cc +++ b/met/src/libcode/vx_python3_utils/python3_script.cc @@ -14,7 +14,6 @@ using namespace std; #include "vx_log.h" #include "empty_string.h" -#include "string_fxns.h" #include "python3_util.h" #include "python3_script.h" diff --git a/met/src/libcode/vx_python3_utils/wchar_argv.cc b/met/src/libcode/vx_python3_utils/wchar_argv.cc index b876073860..9a52363c5b 100644 --- a/met/src/libcode/vx_python3_utils/wchar_argv.cc +++ b/met/src/libcode/vx_python3_utils/wchar_argv.cc @@ -1,5 +1,3 @@ - - //////////////////////////////////////////////////////////////////////// @@ -25,7 +23,6 @@ using namespace std; #include "wchar_argv.h" #include "concat_string.h" -#include "string_fxns.h" #include "vx_log.h" diff --git a/met/src/tools/other/mode_time_domain/nc_utils_local.cc b/met/src/tools/other/mode_time_domain/nc_utils_local.cc index 171ce59d9b..ce7b74b3ae 100644 --- a/met/src/tools/other/mode_time_domain/nc_utils_local.cc +++ b/met/src/tools/other/mode_time_domain/nc_utils_local.cc @@ -22,7 +22,6 @@ using namespace std; #include "nc_utils.h" #include "nc_utils_local.h" -#include "string_fxns.h" #include "vx_log.h" diff --git a/met/src/tools/other/wwmca_tool/wwmca_plot.cc b/met/src/tools/other/wwmca_tool/wwmca_plot.cc index 42ec608cb3..b8705dfc84 100644 --- a/met/src/tools/other/wwmca_tool/wwmca_plot.cc +++ b/met/src/tools/other/wwmca_tool/wwmca_plot.cc @@ -400,7 +400,7 @@ void set_pixel_time_filename(const char * cp_name, char * pt_name) // now create the new pixel time filename which consists of the pt_name_start and the // rest of the cp_name after removing its start (WWMCA_TOTAL_CLOUD_PCT) - m_strcpy(pt_name + i, pt_name_start, method_name); + m_strncpy((char *)(pt_name + i), pt_name_start, m_strlen(pt_name_start), method_name); for (j = i + m_strlen(pt_name_start); j < cp_length; j++) pt_name[j] = cp_name[j]; From 77e5489292bbed24e186dbb9d04d82ac21ac1c66 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Wed, 8 Sep 2021 11:35:28 -0600 Subject: [PATCH 171/200] #1903 Avoid the negative offset if the string length is 0 --- met/src/libcode/vx_tc_util/track_info.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/src/libcode/vx_tc_util/track_info.cc b/met/src/libcode/vx_tc_util/track_info.cc index a1b030e1aa..3566077b9b 100644 --- a/met/src/libcode/vx_tc_util/track_info.cc +++ b/met/src/libcode/vx_tc_util/track_info.cc @@ -609,7 +609,7 @@ bool TrackInfo::is_interp() const { int offset = (m_strlen(Technique.c_str()) - 1); // Return true if the last character of the model name is 'I' - if offset < 0) return false; + if (offset < 0) return false; else return(s[offset] == 'I'); } From 8e1437274fa68b175a4e1430d285ac86ede12f94 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Thu, 9 Sep 2021 16:44:51 -0600 Subject: [PATCH 172/200] Separated third AND condition to avoid a possible side effect (assigned lead) --- met/src/tools/tc_utils/tc_stat/tc_stat_job.cc | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/met/src/tools/tc_utils/tc_stat/tc_stat_job.cc b/met/src/tools/tc_utils/tc_stat/tc_stat_job.cc index ed0e22757c..ab99501d9f 100644 --- a/met/src/tools/tc_utils/tc_stat/tc_stat_job.cc +++ b/met/src/tools/tc_utils/tc_stat/tc_stat_job.cc @@ -4034,6 +4034,7 @@ ConcatString build_map_key(const char *prefix, const TCStatLine &l, const StringArray &case_cols) { int i; int lead = 0; + bool not_converted; ConcatString key, cur; // Initialize the map key with prefix @@ -4042,7 +4043,7 @@ ConcatString build_map_key(const char *prefix, const TCStatLine &l, // Build case information for the map key for(i=0; i Date: Thu, 9 Sep 2021 16:46:31 -0600 Subject: [PATCH 173/200] #1903 Renamed import (which is a keyword) to import_image) --- .../tools/other/mode_graphics/cgraph_main.cc | 25 ++++++++++--------- .../tools/other/mode_graphics/cgraph_main.h | 11 ++++---- .../other/mode_graphics/plot_mode_field.cc | 2 +- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/met/src/tools/other/mode_graphics/cgraph_main.cc b/met/src/tools/other/mode_graphics/cgraph_main.cc index 4aed3893ce..d9963263fc 100644 --- a/met/src/tools/other/mode_graphics/cgraph_main.cc +++ b/met/src/tools/other/mode_graphics/cgraph_main.cc @@ -810,7 +810,7 @@ FT_UInt previous; FT_Glyph_Metrics * metrics = (FT_Glyph_Metrics *) 0; FT_Vector k_delta; const bool use_kerning = DoKerning && FT_HAS_KERNING(face); -const char * new_string = (const char *) 0; +const char * new_string = (const char *) NULL; bool first_char = false; bool last_char = false; double x_bearing, y_bearing, advance; @@ -1048,7 +1048,8 @@ if ( render_flag ) { // done // -if ( DoLigatures && new_string != NULL ) { delete [] new_string; new_string = (char *) 0; } +if ( DoLigatures ) delete [] new_string; +new_string = (char *) 0; return; @@ -1119,11 +1120,11 @@ return; //////////////////////////////////////////////////////////////////////// -void CgraphBase::import(const Ppm & ppm, double x, double y, double u, double v, double _scale) +void CgraphBase::import_image(const Ppm & ppm, double x, double y, double u, double v, double _scale) { -import(ppm, x, y, u, v, _scale, _scale); +import_image(ppm, x, y, u, v, _scale, _scale); return; @@ -1133,7 +1134,7 @@ return; //////////////////////////////////////////////////////////////////////// -void CgraphBase::import(const Ppm & ppm, double x, double y, double u, double v, double x_scale, double y_scale) +void CgraphBase::import_image(const Ppm & ppm, double x, double y, double u, double v, double x_scale, double y_scale) { @@ -1753,7 +1754,7 @@ return; //////////////////////////////////////////////////////////////////////// -void Cgraph::import(const Ppm & ppm, const Box & b, const ViewGravity g) +void Cgraph::import_image(const Ppm & ppm, const Box & b, const ViewGravity g) { @@ -1782,7 +1783,7 @@ if ( g == fill_viewport ) { } -import(ppm, x, y, u, v, x_scale, y_scale); +import_image(ppm, x, y, u, v, x_scale, y_scale); return; @@ -1792,11 +1793,11 @@ return; //////////////////////////////////////////////////////////////////////// -void Cgraph::import(const Ppm & ppm, double x, double y, double u, double v, double _scale) +void Cgraph::import_image(const Ppm & ppm, double x, double y, double u, double v, double _scale) { -import(ppm, x, y, u, v, _scale, _scale); +import_image(ppm, x, y, u, v, _scale, _scale); return; @@ -1806,7 +1807,7 @@ return; //////////////////////////////////////////////////////////////////////// -void Cgraph::import(const Ppm & ppm, double x, double y, double u, double v, double x_scale, double y_scale) +void Cgraph::import_image(const Ppm & ppm, double x, double y, double u, double v, double x_scale, double y_scale) { @@ -2114,7 +2115,7 @@ if ( empty(in) ) { int j, k; char c0, c1; const int N = m_strlen(in); -char * s = (char *) 0; +char * s = (char *) NULL; FT_UInt fi_glyph_index = 0; FT_UInt fl_glyph_index = 0; @@ -2160,7 +2161,7 @@ while ( j < N ) { // done // -out = s; s = (char *) 0; +out = s; s = (char *) NULL; return; diff --git a/met/src/tools/other/mode_graphics/cgraph_main.h b/met/src/tools/other/mode_graphics/cgraph_main.h index d570e5e6cc..7c445bcdb0 100644 --- a/met/src/tools/other/mode_graphics/cgraph_main.h +++ b/met/src/tools/other/mode_graphics/cgraph_main.h @@ -148,11 +148,10 @@ class CgraphBase : public PSfile { // import images // - virtual void import(const Ppm &, double x, double y, double u, double v, double _scale = 1.0); - virtual void import(const Ppm &, double x, double y, double u, double v, double x_scale, double y_scale); + virtual void import_image(const Ppm &, double x, double y, double u, double v, double _scale = 1.0); + virtual void import_image(const Ppm &, double x, double y, double u, double v, double x_scale, double y_scale); // this is implemented in the CGraph2 class - // virtual void import(const Ppm &, const Box &, const ViewGravity); // // Type 1 fonts @@ -308,9 +307,9 @@ class Cgraph : public CgraphBase { // import images // - void import(const Ppm &, double x, double y, double u, double v, double _scale = 1.0); - void import(const Ppm &, double x, double y, double u, double v, double x_scale, double y_scale); - void import(const Ppm &, const Box &, const ViewGravity); + void import_image(const Ppm &, double x, double y, double u, double v, double _scale = 1.0); + void import_image(const Ppm &, double x, double y, double u, double v, double x_scale, double y_scale); + void import_image(const Ppm &, const Box &, const ViewGravity); // // text rendering diff --git a/met/src/tools/other/mode_graphics/plot_mode_field.cc b/met/src/tools/other/mode_graphics/plot_mode_field.cc index 23f12ba4bc..8d0894f154 100644 --- a/met/src/tools/other/mode_graphics/plot_mode_field.cc +++ b/met/src/tools/other/mode_graphics/plot_mode_field.cc @@ -536,7 +536,7 @@ if ( do_anno ) fill_box(whole_box, anno_bg_color, plot); get_data_ppm(mode_in, image); -plot.import(image, map_box.left(), map_box.bottom(), 0.0, 0.0, 1.0); +plot.import_image(image, map_box.left(), map_box.bottom(), 0.0, 0.0, 1.0); // // draw the map From 9f93ed82cecf9bcbe2f744f3bdb5c0a71dd5c6e8 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Thu, 9 Sep 2021 16:47:17 -0600 Subject: [PATCH 174/200] Initialize data at get_filtered_nc_data_2d --- met/src/tools/other/madis2nc/madis2nc.cc | 66 +++++++----------------- 1 file changed, 20 insertions(+), 46 deletions(-) diff --git a/met/src/tools/other/madis2nc/madis2nc.cc b/met/src/tools/other/madis2nc/madis2nc.cc index 29c5479f40..2b20587e1f 100644 --- a/met/src/tools/other/madis2nc/madis2nc.cc +++ b/met/src/tools/other/madis2nc/madis2nc.cc @@ -461,8 +461,13 @@ static bool get_filtered_nc_data_2d(NcVar var, int *data, const long *dim, bool status = false; int in_fill_value; + int data_len = dim[0] * dim[1]; const char *method_name = "get_filtered_nc_data_2d(int)"; + for (int offset=0; offset Date: Thu, 9 Sep 2021 16:48:18 -0600 Subject: [PATCH 175/200] #1903 Initialize r, g, b at dhsv_to_drgb --- met/src/libcode/vx_color/color.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/met/src/libcode/vx_color/color.cc b/met/src/libcode/vx_color/color.cc index ffb72de3ad..a15eef78b0 100644 --- a/met/src/libcode/vx_color/color.cc +++ b/met/src/libcode/vx_color/color.cc @@ -454,7 +454,9 @@ void dhsv_to_drgb(double h, double s, double v, double & r, double & g, double & { -if ( is_eq(s, 0.0) ) { r = g = b = v; return; }; +r = g = b = v; // initialze, default is missing at switch statement below + +if ( is_eq(s, 0.0) ) return; int i; double f, p, q, t; From ca814c9cfab48e2709f14948925d11e28143b718 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Thu, 9 Sep 2021 16:49:25 -0600 Subject: [PATCH 176/200] Modified to avoid unreachable return statement --- met/src/libcode/vx_data2d/table_lookup.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/met/src/libcode/vx_data2d/table_lookup.cc b/met/src/libcode/vx_data2d/table_lookup.cc index 7f5264d1ee..ea3385f323 100644 --- a/met/src/libcode/vx_data2d/table_lookup.cc +++ b/met/src/libcode/vx_data2d/table_lookup.cc @@ -843,10 +843,12 @@ bool TableFlatFile::read(const char * filename) ifstream in; ConcatString line; int n_lines; +bool status = false; +const char *method_name = "TableFlatFile::read(const char *) -> "; if ( empty(filename) ) { - mlog << Error << "\nTableFlatFile::read(const char *) ->" + mlog << Error << "\n" << method_name << "empty filename!\n\n"; exit ( 1 ); @@ -863,7 +865,7 @@ met_open(in, filename); if ( !in ) { - mlog << Error << "\nTableFlatFile::read(const char *) -> " + mlog << Error << "\n" << method_name << "unable to open input file \"" << filename << "\"\n\n"; exit ( 1 ); @@ -880,11 +882,11 @@ line.chomp('\n'); line.ws_strip(); - if ( line == "GRIB1" ) { return ( read_grib1(in, filename, n_lines - 1) ); } -else if ( line == "GRIB2" ) { return ( read_grib2(in, filename, n_lines - 1) ); } + if ( line == "GRIB1" ) status = read_grib1(in, filename, n_lines - 1); +else if ( line == "GRIB2" ) status = read_grib2(in, filename, n_lines - 1); else { - mlog << Error << "\nTableFlatFile::read(const char *) -> " + mlog << Error << "\n" << method_name << "unable unrecognized format spec \"" << line << "\" in file \"" << filename << "\"\n\n"; @@ -898,7 +900,7 @@ else { in.close(); -return ( false ); +return ( status ); } From 3163c59a609627c6b0c38cc0891a21b247af1868 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Thu, 9 Sep 2021 16:51:43 -0600 Subject: [PATCH 177/200] #1903 Separated the second AND condition to avoid a potential side effect (assignment at the second condition) --- met/src/libcode/vx_data2d_grib/grib_classes.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/met/src/libcode/vx_data2d_grib/grib_classes.cc b/met/src/libcode/vx_data2d_grib/grib_classes.cc index 51485d38c2..e76e9d2631 100644 --- a/met/src/libcode/vx_data2d_grib/grib_classes.cc +++ b/met/src/libcode/vx_data2d_grib/grib_classes.cc @@ -1358,9 +1358,13 @@ void GribFile::close() { -if ( rep && (--rep->referenceCount == 0) ) delete rep; +if ( rep ) { -rep = (GribFileRep *) 0; + if (--rep->referenceCount == 0) delete rep; + + rep = (GribFileRep *) NULL; + +} return; From 38854483546374e3d1e5280589444a1d933dadb7 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Thu, 9 Sep 2021 16:53:04 -0600 Subject: [PATCH 178/200] #1903 Removed unreachable break (after exit) --- met/src/libcode/vx_data2d_nccf/nccf_file.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/met/src/libcode/vx_data2d_nccf/nccf_file.cc b/met/src/libcode/vx_data2d_nccf/nccf_file.cc index 5bc0fea1d1..80ae51e415 100644 --- a/met/src/libcode/vx_data2d_nccf/nccf_file.cc +++ b/met/src/libcode/vx_data2d_nccf/nccf_file.cc @@ -740,7 +740,7 @@ void NcCfFile::dump(ostream & out, int depth) const if (AccumTime > 0) { unix_to_mdyhms(AccumTime, month, day, year, hour, minute, second); snprintf(junk, sizeof(junk), "%2d:%02d:%02d (%d seconds)", - hour, minute, second, AccumTime); + hour, minute, second, (int)AccumTime); out << prefix << "Accum Time = "; out << junk << "\n"; out << prefix << "\n"; @@ -1124,7 +1124,6 @@ bool NcCfFile::getData(NcVar * v, const LongArray & a, DataPlane & plane) const << " bad type [" << GET_NC_TYPE_NAME_P(v) << "] for variable \"" << (GET_NC_NAME_P(v)) << "\"\n\n"; exit ( 1 ); - break; } // switch From cb759e8bc18d518911aceb27c6053be20da3591b Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Thu, 9 Sep 2021 16:54:01 -0600 Subject: [PATCH 179/200] #1903 Removed a unused offset variable --- .../tools/other/ascii2nc/aeronet_handler.cc | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/met/src/tools/other/ascii2nc/aeronet_handler.cc b/met/src/tools/other/ascii2nc/aeronet_handler.cc index 1a1fe249a1..ef7025bec9 100644 --- a/met/src/tools/other/ascii2nc/aeronet_handler.cc +++ b/met/src/tools/other/ascii2nc/aeronet_handler.cc @@ -643,7 +643,6 @@ double AeronetHandler::extract_height(string hdr_field) { string height_str = ""; if (string::npos == hdr_field.find("Empty")) { - size_t offset; int token_count = 0; bool with_unit = false; string tmp_height; @@ -652,7 +651,7 @@ double AeronetHandler::extract_height(string hdr_field) { hdr_names.parse_delim(hdr_field.c_str(), "_"); // AOD_1640nm-Total,AOD_1640nm-AOD,AOD_1640nm-Rayleigh,AOD_1640nm-O3, // AOD_1640nm-NO2,AOD_1640nm-CO2,AOD_1640nm-CH4,AOD_1640nm-WaterVapor - if (0 == (offset = hdr_field.find(AOD_NAME))) { + if (0 == hdr_field.find(AOD_NAME)) { with_unit = true; tmp_height = hdr_names[hdr_names.n_elements()-1]; hdr_names.clear(); @@ -660,27 +659,27 @@ double AeronetHandler::extract_height(string hdr_field) { height_str = hdr_names[0]; } // Exact_Wavelengths_for_Input_AOD(um) - else if (0 == (offset = hdr_field.find(WAVELENGTHS_INPUT_AOD_NAME))) { + else if (0 == hdr_field.find(WAVELENGTHS_INPUT_AOD_NAME)) { StringArray tmp_hdr_names; tmp_hdr_names.parse_delim(WAVELENGTHS_INPUT_AOD_NAME.c_str(), "_"); token_count = tmp_hdr_names.n_elements(); } // 870nm_Input_AOD - else if (string::npos != (offset = hdr_field.find(INPUT_AOD_NAME))) { + else if (string::npos != hdr_field.find(INPUT_AOD_NAME)) { with_unit = true; height_str = hdr_names[0]; } // Exact_Wavelengths_of_AOD(um)_865nm // Exact_Wavelengths_of_PW(um)_935nm - else if (string::npos != (offset = hdr_field.find(WAVELENGTHS_AOD_NAME)) - || string::npos != (offset = hdr_field.find(WAVELENGTHS_PW_NAME)) ) { + else if (string::npos != hdr_field.find(WAVELENGTHS_AOD_NAME) + || string::npos != hdr_field.find(WAVELENGTHS_PW_NAME) ) { with_unit = true; StringArray tmp_hdr_names; tmp_hdr_names.parse_delim(WAVELENGTHS_AOD_NAME.c_str(), "_"); token_count = tmp_hdr_names.n_elements(); } // Exact_Wavelengths_of_INPUT_AOD(um) - else if (string::npos != (offset = hdr_field.find(WAVELENGTHS_INPUT_AOD_NAME)) ) { + else if (string::npos != hdr_field.find(WAVELENGTHS_INPUT_AOD_NAME) ) { StringArray tmp_hdr_names; tmp_hdr_names.parse_delim(WAVELENGTHS_INPUT_AOD_NAME.c_str(), "_"); token_count = tmp_hdr_names.n_elements(); @@ -720,29 +719,28 @@ int AeronetHandler::get_header_count_v3(StringArray hdr_tokens) { string AeronetHandler::make_var_name_from_header(string hdr_field) { string var_name = hdr_field; if (format_version == 3) { - int offset; bool found = true; StringArray hdr_names; // AOD_1640nm-Total,AOD_1640nm-AOD,AOD_1640nm-Rayleigh,AOD_1640nm-O3, // AOD_1640nm-NO2,AOD_1640nm-CO2,AOD_1640nm-CH4,AOD_1640nm-WaterVapor - if (0 == (offset = hdr_field.find(AOD_NAME))) { + if (0 == hdr_field.find(AOD_NAME)) { hdr_names.parse_delim(hdr_field.c_str(), "_"); var_name = hdr_names[0]; } // Exact_Wavelengths_for_Input_AOD(um) - else if (0 == (offset = hdr_field.find(WAVELENGTHS_INPUT_AOD_NAME))) { + else if (0 == hdr_field.find(WAVELENGTHS_INPUT_AOD_NAME)) { var_name = WAVELENGTHS_INPUT_AOD_NAME; } // const string Input_AOD_NAME = "Input_AOD"; // 870nm_Input_AOD - else if ((int) string::npos != (offset = hdr_field.find(INPUT_AOD_NAME))) { + else if ((int) string::npos != hdr_field.find(INPUT_AOD_NAME)) { var_name = INPUT_AOD_NAME; } // Exact_Wavelengths_of_AOD(um)_865nm - else if ((int) string::npos != (offset = hdr_field.find(WAVELENGTHS_AOD_NAME))) { + else if ((int) string::npos != hdr_field.find(WAVELENGTHS_AOD_NAME)) { var_name = WAVELENGTHS_AOD_NAME; } // Exact_Wavelengths_of_PW(um)_935nm - else if ((int) string::npos != (offset = hdr_field.find(WAVELENGTHS_PW_NAME))) { + else if ((int) string::npos != hdr_field.find(WAVELENGTHS_PW_NAME)) { var_name = WAVELENGTHS_PW_NAME; } else if ((hdr_field == OPTICAL_AIR_MASS_NAME)) { From 66389e044074f225386d4b2d84818f1f6a73e25d Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Thu, 9 Sep 2021 17:02:23 -0600 Subject: [PATCH 180/200] #1903 Initialize fcst variable --- met/src/libcode/vx_statistics/pair_data_ensemble.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/src/libcode/vx_statistics/pair_data_ensemble.cc b/met/src/libcode/vx_statistics/pair_data_ensemble.cc index d6869221fc..a305fa64ea 100644 --- a/met/src/libcode/vx_statistics/pair_data_ensemble.cc +++ b/met/src/libcode/vx_statistics/pair_data_ensemble.cc @@ -1793,7 +1793,7 @@ void VxPairDataEnsemble::set_skip_const(bool tf) { double compute_crps_emp(double obs, const NumArray &ens_na) { int i; - double fcst; + double fcst = 0.0; NumArray evals; // Store valid ensemble member values From 42c834e22b51928ee9538025989534e46b53c7a1 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Thu, 9 Sep 2021 17:03:15 -0600 Subject: [PATCH 181/200] Renamed module (keyword) to py_module --- met/src/libcode/vx_python3_utils/python3_script.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/met/src/libcode/vx_python3_utils/python3_script.cc b/met/src/libcode/vx_python3_utils/python3_script.cc index ec022ce765..e34fb3ed7a 100644 --- a/met/src/libcode/vx_python3_utils/python3_script.cc +++ b/met/src/libcode/vx_python3_utils/python3_script.cc @@ -244,10 +244,10 @@ void Python3_Script::import_read_tmp_ascii_py(void) { -ConcatString module; +ConcatString py_module; -module << cs_erase - << replace_path(read_tmp_ascii_py); +py_module << cs_erase + << replace_path(read_tmp_ascii_py); ConcatString command; @@ -255,14 +255,14 @@ run_python_string("import sys"); command << cs_erase << "sys.path.append(\"" - << module.dirname().c_str() + << py_module.dirname().c_str() << "\")"; mlog << Debug(3) << command << "\n"; run_python_string(command.text()); -mlog << Debug(2) << "Importing " << module << "\n"; +mlog << Debug(2) << "Importing " << py_module << "\n"; ConcatString path = "read_tmp_ascii"; From 28d0f2fba4145418a9436a1af3eb83e0093538f5 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Thu, 9 Sep 2021 17:04:24 -0600 Subject: [PATCH 182/200] Removed the second argument at m_strlen --- met/src/basic/vx_log/str_wrappers.cc | 8 ++++---- met/src/basic/vx_log/str_wrappers.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/met/src/basic/vx_log/str_wrappers.cc b/met/src/basic/vx_log/str_wrappers.cc index 9e59375fc4..2d6f486d1b 100644 --- a/met/src/basic/vx_log/str_wrappers.cc +++ b/met/src/basic/vx_log/str_wrappers.cc @@ -19,9 +19,9 @@ using namespace std; //////////////////////////////////////////////////////////////////////// -int m_strlen(const char *str, bool buf_size) { +int m_strlen(const char *str) { int str_len = -1; - if (str) str_len = buf_size ? sizeof str : strlen(str); + if (str) str_len = strlen(str); return str_len; } @@ -32,7 +32,7 @@ int m_strlen(const char *str, bool buf_size) { void m_strcpy(char *to_str, const char *from_str, const char *method_name, const char *extra_msg) { - int str_len = m_strlen(to_str, true); + int str_len = m_strlen(to_str); m_strncpy(to_str, from_str, str_len, method_name, extra_msg); } @@ -90,7 +90,7 @@ void m_strncpy(char *to_str, const char *from_str, const int buf_len, if (!truncate && strcmp(from_str, to_str)) { mlog << Warning << "\n" << method_name - << " truncated a string " << (extra_msg == 0 ? "" : extra_msg) + << " truncated a string " << (extra_msg == 0 ? " " : extra_msg) << " from \"" << from_str << "\" to \"" << to_str << "\"\n\n"; } } diff --git a/met/src/basic/vx_log/str_wrappers.h b/met/src/basic/vx_log/str_wrappers.h index d45e7b375c..5d74eef860 100644 --- a/met/src/basic/vx_log/str_wrappers.h +++ b/met/src/basic/vx_log/str_wrappers.h @@ -17,7 +17,7 @@ //////////////////////////////////////////////////////////////////////// -extern int m_strlen(const char *str, bool buf_size=false); +extern int m_strlen(const char *str); extern void m_strcpy(char *to_str, const char *from_str, const char *method_name, const char *extra_msg=(char *)0); From d12143be604cd0d9cf15b25e4cf50ea0202ee2c6 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Thu, 9 Sep 2021 17:06:28 -0600 Subject: [PATCH 183/200] #1903 Deleted extra two empty lines --- met/src/libcode/vx_data2d_nc_pinterp/pinterp_file.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/met/src/libcode/vx_data2d_nc_pinterp/pinterp_file.cc b/met/src/libcode/vx_data2d_nc_pinterp/pinterp_file.cc index a84210752f..03653ec6af 100644 --- a/met/src/libcode/vx_data2d_nc_pinterp/pinterp_file.cc +++ b/met/src/libcode/vx_data2d_nc_pinterp/pinterp_file.cc @@ -1,5 +1,3 @@ - - // *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* // ** Copyright UCAR (c) 1992 - 2021 // ** University Corporation for Atmospheric Research (UCAR) From 7a077731c0eff97042b4f1a39abc415040af0e54 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Thu, 9 Sep 2021 17:07:27 -0600 Subject: [PATCH 184/200] #1903 Formatting (tab to spaces) --- met/src/tools/dev_utils/insitu_nc_to_ascii.cc | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/met/src/tools/dev_utils/insitu_nc_to_ascii.cc b/met/src/tools/dev_utils/insitu_nc_to_ascii.cc index 04efec517e..efc0b22707 100644 --- a/met/src/tools/dev_utils/insitu_nc_to_ascii.cc +++ b/met/src/tools/dev_utils/insitu_nc_to_ascii.cc @@ -69,8 +69,6 @@ int main(int argc, char * argv []) FILE *output_file; if ((output_file = met_fopen(output_filepath, "w")) == 0) { -// mlog << Error << "\n" << method_name << " -> " -// << "error opening output file" << output_filepath << endl; cerr << "Error opening output file: " << output_filepath << endl; exit(1); @@ -89,8 +87,8 @@ int main(int argc, char * argv []) double max_edr; while (input_file.getNextRecord(aircraft_id, time_obs, - latitude, longitude, altitude, - qc_confidence, med_edr, max_edr)) + latitude, longitude, altitude, + qc_confidence, med_edr, max_edr)) { // Construct the time string @@ -98,7 +96,7 @@ int main(int argc, char * argv []) if (time_struct == 0) { // mlog << Error << "\n" << method_name << " -> " -// << "error converting time value to time structure" << endl; +// << "error converting time value to time structure" << endl; cerr << "Error converting time value to time structure" << endl; fclose(output_file); exit(1); @@ -108,23 +106,23 @@ int main(int argc, char * argv []) snprintf(time_obs_string, sizeof(time_obs_string), "%04d%02d%02d_%02d%02d%02d", - time_struct->tm_year + 1900, time_struct->tm_mon + 1, - time_struct->tm_mday, - time_struct->tm_hour, time_struct->tm_min, time_struct->tm_sec); + time_struct->tm_year + 1900, time_struct->tm_mon + 1, + time_struct->tm_mday, + time_struct->tm_hour, time_struct->tm_min, time_struct->tm_sec); // Write the observations. fprintf(output_file, "MEDEDR %10s %s %10.4f %10.4f %8.2f %3d %8.2f %8.2f %8.2f %8.2f\n", - aircraft_id.c_str(), time_obs_string, - latitude, longitude, altitude * FEET_TO_M, - MED_EDR_GRIB_CODE, MISSING_DATA_VALUE, altitude, - qc_confidence, med_edr); + aircraft_id.c_str(), time_obs_string, + latitude, longitude, altitude * FEET_TO_M, + MED_EDR_GRIB_CODE, MISSING_DATA_VALUE, altitude, + qc_confidence, med_edr); fprintf(output_file, "MAXEDR %10s %s %10.4f %10.4f %8.2f %3d %8.2f %8.2f %8.2f %8.2f\n", - aircraft_id.c_str(), time_obs_string, - latitude, longitude, altitude * FEET_TO_M, - MAX_EDR_GRIB_CODE, MISSING_DATA_VALUE, altitude, - qc_confidence, max_edr); + aircraft_id.c_str(), time_obs_string, + latitude, longitude, altitude * FEET_TO_M, + MAX_EDR_GRIB_CODE, MISSING_DATA_VALUE, altitude, + qc_confidence, max_edr); } fclose(output_file); From 8b528dd4b75871bb3f1c3906f4ca07c7e16870e7 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 10 Sep 2021 14:44:28 -0600 Subject: [PATCH 185/200] #1903 mstcpy is changed to m_strcpy2 --- met/src/basic/vx_config/icode.cc | 22 ++++--------------- .../vx_analysis_util/analysis_utils.cc | 9 +------- 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/met/src/basic/vx_config/icode.cc b/met/src/basic/vx_config/icode.cc index 33daf15cd9..b17aac432f 100644 --- a/met/src/basic/vx_config/icode.cc +++ b/met/src/basic/vx_config/icode.cc @@ -1,5 +1,3 @@ - - //////////////////////////////////////////////////////////////////////// @@ -172,17 +170,13 @@ type = icc.type; if ( type == identifier ) { - name = new char [1 + m_strlen(icc.name)]; - - m_strcpy(name, icc.name, method_name, "name"); + name = m_strcpy2(icc.name, method_name, "name"); } if ( type == character_string ) { - text = new char [1 + m_strlen(icc.text)]; - - m_strcpy(text, icc.text, method_name, "text"); + text = m_strcpy2(icc.text, method_name, "text"); } @@ -421,9 +415,7 @@ clear(); type = identifier; -name = new char [1 + m_strlen(Text)]; - -m_strcpy(name, Text, method_name); +name = m_strcpy2(Text, method_name); return; @@ -442,15 +434,9 @@ const char *method_name = "IcodeCell::set_string() -> "; clear(); -const int n = m_strlen(Text); - type = character_string; -text = new char [1 + n]; - -m_strcpy(text, Text, method_name); - -text[n] = 0; +text = m_strcpy2(Text, method_name); return; diff --git a/met/src/libcode/vx_analysis_util/analysis_utils.cc b/met/src/libcode/vx_analysis_util/analysis_utils.cc index 1282aceedf..313b082236 100644 --- a/met/src/libcode/vx_analysis_util/analysis_utils.cc +++ b/met/src/libcode/vx_analysis_util/analysis_utils.cc @@ -29,7 +29,6 @@ StringArray parse_line(const char * line) { -int n; StringArray a; const char * delim = " "; char * c = (char *) 0; @@ -40,13 +39,7 @@ const char *method_name = "parse_line() -> "; // copy the line // -n = m_strlen(line); - -L = new char [1 + n]; - -memset(L, 0, 1 + n); - -m_strcpy(L, line, method_name); +L = m_strcpy2(line, method_name); // // tokenize the line From 7ea619c08e10c9382dab21b5c8b2f11b4be40a86 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 10 Sep 2021 14:45:04 -0600 Subject: [PATCH 186/200] Deleted the commented out code --- met/src/tools/other/lidar2nc/lidar2nc.cc | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/met/src/tools/other/lidar2nc/lidar2nc.cc b/met/src/tools/other/lidar2nc/lidar2nc.cc index 807de07a50..c02dfd2771 100644 --- a/met/src/tools/other/lidar2nc/lidar2nc.cc +++ b/met/src/tools/other/lidar2nc/lidar2nc.cc @@ -395,17 +395,6 @@ nc_point_obs.add_header_strings(hdr_typ_string, na_str); // // populate the obs_qty variable // -/* -memset(buf, 0, buf_size); - -for (j=0; j Date: Fri, 10 Sep 2021 14:48:24 -0600 Subject: [PATCH 187/200] #1903 Calls sizeof instead of m_strlen at m_strcpy --- met/src/basic/vx_log/str_wrappers.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/src/basic/vx_log/str_wrappers.cc b/met/src/basic/vx_log/str_wrappers.cc index 2d6f486d1b..ffff082df5 100644 --- a/met/src/basic/vx_log/str_wrappers.cc +++ b/met/src/basic/vx_log/str_wrappers.cc @@ -32,7 +32,7 @@ int m_strlen(const char *str) { void m_strcpy(char *to_str, const char *from_str, const char *method_name, const char *extra_msg) { - int str_len = m_strlen(to_str); + int str_len = sizeof(to_str); m_strncpy(to_str, from_str, str_len, method_name, extra_msg); } From 8bbe01aa2ca869cfe8f299dac1b1ff9e2ff4d11c Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 10 Sep 2021 14:50:01 -0600 Subject: [PATCH 188/200] #1903 Calls m_strncpy instead of m_strcpy --- met/src/basic/vx_util/string_fxns.cc | 4 ++-- met/src/libcode/vx_data2d_grib/grib_strings.cc | 4 ++-- met/src/libcode/vx_ps/ps_text.cc | 4 ++-- met/src/libcode/vx_statistics/met_stats.cc | 2 +- met/src/tools/core/mode/page_1.cc | 8 ++++---- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/met/src/basic/vx_util/string_fxns.cc b/met/src/basic/vx_util/string_fxns.cc index 3ab58e411c..8817880053 100644 --- a/met/src/basic/vx_util/string_fxns.cc +++ b/met/src/basic/vx_util/string_fxns.cc @@ -297,8 +297,8 @@ int regex_apply(const char* pat, int num_mat, const char* str, char** &mat) for(int i=0; i < num_act; i++){ int mat_len = pmatch[i].rm_eo - pmatch[i].rm_so; mat[i] = new char[mat_len + 1]; - m_strcpy(mat[i], str_dat.substr(pmatch[i].rm_so, mat_len).data(), - method_name, "mat[i]"); + m_strncpy(mat[i], str_dat.substr(pmatch[i].rm_so, mat_len).data(), + mat_len, method_name, "mat[i]"); } mat[num_act] = NULL; diff --git a/met/src/libcode/vx_data2d_grib/grib_strings.cc b/met/src/libcode/vx_data2d_grib/grib_strings.cc index 52ab29462e..d45177e832 100644 --- a/met/src/libcode/vx_data2d_grib/grib_strings.cc +++ b/met/src/libcode/vx_data2d_grib/grib_strings.cc @@ -275,7 +275,7 @@ int str_to_grib_code(const char *c, int &pcode, // PROB(string>lo) // PROB(string') n_gt++; } - m_strcpy(tmp_str, c, method_name); + m_strncpy(tmp_str, c, buf_len, method_name); // Single inequality if(n_lt + n_gt == 1) { diff --git a/met/src/libcode/vx_ps/ps_text.cc b/met/src/libcode/vx_ps/ps_text.cc index 8a3ff0cf25..f92305d78c 100644 --- a/met/src/libcode/vx_ps/ps_text.cc +++ b/met/src/libcode/vx_ps/ps_text.cc @@ -322,7 +322,7 @@ Nalloc = n; // copy the old values, if any // -if ( Text ) m_strcpy(u, Text, method_name, "Text"); +if ( Text ) m_strncpy(u, Text, (n-1), method_name, "Text"); // // toss old, grab new @@ -357,7 +357,7 @@ Nchars = m_strlen(s); extend(Nchars + 2); -if (Text) m_strcpy(Text, s, method_name, "Text"); +if (Text) m_strncpy(Text, s, Nalloc, method_name, "Text"); return; diff --git a/met/src/libcode/vx_statistics/met_stats.cc b/met/src/libcode/vx_statistics/met_stats.cc index 0657e60239..2975b03432 100644 --- a/met/src/libcode/vx_statistics/met_stats.cc +++ b/met/src/libcode/vx_statistics/met_stats.cc @@ -3051,7 +3051,7 @@ int parse_message_type(const char *msg_typ_str, char **&msg_typ_arr) { msg_typ_arr = new char * [n]; // Initialize the temp string for use in tokenizing - m_strcpy(tmp_str, msg_typ_str, method_name); + m_strncpy(tmp_str, msg_typ_str, max_str_len, method_name); // Tokenize the string and store the double values c = strtok(tmp_str, " "); diff --git a/met/src/tools/core/mode/page_1.cc b/met/src/tools/core/mode/page_1.cc index 9b9dc54f63..09ae0ca2da 100644 --- a/met/src/tools/core/mode/page_1.cc +++ b/met/src/tools/core/mode/page_1.cc @@ -413,12 +413,12 @@ text_y -= 2.0*TextSep; // Accumulation time // -m_strcpy(junk, sec_to_hhmmss_colon(eng.fcst_raw->data.accum()).c_str(), - method_name, "fcst_raw->data.accum()"); +m_strncpy(junk, sec_to_hhmmss_colon(eng.fcst_raw->data.accum()).c_str(), + buf_len, method_name, "fcst_raw->data.accum()"); t1.write_xy1_to_cell(9, 1, dx, dy, 0.0, 0.0, junk); -m_strcpy(junk, sec_to_hhmmss_colon(eng.obs_raw->data.accum()).c_str(), - method_name, "obs_raw->data.accum()"); +m_strncpy(junk, sec_to_hhmmss_colon(eng.obs_raw->data.accum()).c_str(), + buf_len, method_name, "obs_raw->data.accum()"); t1.write_xy1_to_cell(9, 2, dx, dy, 0.0, 0.0, junk); nextline(); From 447a7cd8d62e717e9b45b7e483fd846142729bb7 Mon Sep 17 00:00:00 2001 From: Howard Soh Date: Fri, 10 Sep 2021 15:08:03 -0600 Subject: [PATCH 189/200] #1903 Replaced m_strcpy to m_strncpy --- met/src/libcode/vx_nc_obs/nc_point_obs_out.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/met/src/libcode/vx_nc_obs/nc_point_obs_out.cc b/met/src/libcode/vx_nc_obs/nc_point_obs_out.cc index 6d1818e054..69cc374dca 100644 --- a/met/src/libcode/vx_nc_obs/nc_point_obs_out.cc +++ b/met/src/libcode/vx_nc_obs/nc_point_obs_out.cc @@ -216,12 +216,12 @@ void MetNcPointObsOut::init_buffer() { data_buffer.hdr_data_offset = 0; data_buffer.pb_hdr_data_offset = 0; - m_strcpy(data_buffer.prev_hdr_typ_buf, not_defined, - method_name, "data_buffer.prev_hdr_typ_buf"); - m_strcpy(data_buffer.prev_hdr_sid_buf, not_defined, - method_name, "data_buffer.prev_hdr_sid_buf"); - m_strcpy(data_buffer.prev_hdr_vld_buf, not_defined, - method_name, "data_buffer.prev_hdr_vld_buf"); + m_strncpy(data_buffer.prev_hdr_typ_buf, not_defined, + HEADER_STR_LEN2, method_name, "data_buffer.prev_hdr_typ_buf"); + m_strncpy(data_buffer.prev_hdr_sid_buf, not_defined, + HEADER_STR_LEN2, method_name, "data_buffer.prev_hdr_sid_buf"); + m_strncpy(data_buffer.prev_hdr_vld_buf, not_defined, + HEADER_STR_LEN, method_name, "data_buffer.prev_hdr_vld_buf"); for (int index=0; index Date: Mon, 13 Sep 2021 22:29:20 -0600 Subject: [PATCH 190/200] #1903 Do not use sizeof --- met/src/basic/vx_log/str_wrappers.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/met/src/basic/vx_log/str_wrappers.cc b/met/src/basic/vx_log/str_wrappers.cc index ffff082df5..81d707c5a7 100644 --- a/met/src/basic/vx_log/str_wrappers.cc +++ b/met/src/basic/vx_log/str_wrappers.cc @@ -32,7 +32,9 @@ int m_strlen(const char *str) { void m_strcpy(char *to_str, const char *from_str, const char *method_name, const char *extra_msg) { - int str_len = sizeof(to_str); + // Note: recommend to use m_strncpy because there are some cases that + // sizeof(to_str) returns 8 which is not the allocated buffer size. + int str_len = m_strlen(from_str); m_strncpy(to_str, from_str, str_len, method_name, extra_msg); } From ab4c7314f13494fd693f31b35bd9d314246ed7d9 Mon Sep 17 00:00:00 2001 From: johnhg Date: Wed, 15 Sep 2021 10:54:51 -0600 Subject: [PATCH 191/200] Feature 1912 missing (#1915) * Per #1912, update logic of Met2dDataFile::process_data_plane(). Rather than returning bad status for a field of all bad data, print a warning message and continue processing. * Per #1912, fixing typo in error message that I ran into. Doesn't actually apply to this issue. * Per #1912, making an unrelated change here to fix up the MODE-Analysis log output. It was reporting (nul) for the number of lines being read/kept. Simplify the log messages to print the correct numbers. --- met/src/libcode/vx_analysis_util/mode_job.cc | 33 ++++---------------- met/src/libcode/vx_data2d/data_class.cc | 5 ++- met/src/tools/other/ioda2nc/ioda2nc.cc | 2 +- 3 files changed, 9 insertions(+), 31 deletions(-) diff --git a/met/src/libcode/vx_analysis_util/mode_job.cc b/met/src/libcode/vx_analysis_util/mode_job.cc index dea7bee574..077733412a 100644 --- a/met/src/libcode/vx_analysis_util/mode_job.cc +++ b/met/src/libcode/vx_analysis_util/mode_job.cc @@ -535,20 +535,6 @@ for (j=0; jmagic_str() + << "\" contains no valid data!\n\n"; } diff --git a/met/src/tools/other/ioda2nc/ioda2nc.cc b/met/src/tools/other/ioda2nc/ioda2nc.cc index 83b3ae5c81..04c58c0909 100644 --- a/met/src/tools/other/ioda2nc/ioda2nc.cc +++ b/met/src/tools/other/ioda2nc/ioda2nc.cc @@ -913,7 +913,7 @@ void write_netcdf_hdr_data() { // Check for no messages retained if(hdr_cnt <= 0) { mlog << Error << method_name << " -> " - << "No IODA reocrds retained. Nothing to write.\n\n"; + << "No IODA records retained. Nothing to write.\n\n"; // Delete the NetCDF file remove_temp_file(ncfile); exit(1); From bfc8a6312be4f7993b953b0bb8c37582c3838008 Mon Sep 17 00:00:00 2001 From: Julie Prestopnik Date: Wed, 15 Sep 2021 15:18:28 -0600 Subject: [PATCH 192/200] Testing RTD updates --- met/docs/requirements.txt | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/met/docs/requirements.txt b/met/docs/requirements.txt index 14529e46cf..7bdda84b33 100644 --- a/met/docs/requirements.txt +++ b/met/docs/requirements.txt @@ -1,11 +1,2 @@ -sphinx==2.4.4 -sphinx-gallery==0.7.0 -sphinx-rtd-theme==0.4.3 -sphinxcontrib-applehelp==1.0.2 +sphinx-gallery sphinxcontrib-bibtex -sphinxcontrib-devhelp==1.0.2 -sphinxcontrib-htmlhelp==1.0.3 -sphinxcontrib-jsmath==1.0.1 -sphinxcontrib-qthelp==1.0.3 -sphinxcontrib-serializinghtml==1.1.4 -sphinx-panels==0.6.0 From f9c8a9c619542695b82f89d9f3478506858710f7 Mon Sep 17 00:00:00 2001 From: Julie Prestopnik Date: Wed, 15 Sep 2021 15:24:06 -0600 Subject: [PATCH 193/200] Added sphinx-panels --- met/docs/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/met/docs/requirements.txt b/met/docs/requirements.txt index 7bdda84b33..59572ff5a8 100644 --- a/met/docs/requirements.txt +++ b/met/docs/requirements.txt @@ -1,2 +1,3 @@ sphinx-gallery sphinxcontrib-bibtex +sphinx-panels From a62caaa8abbb23cd202fd51a2da7df8db1009982 Mon Sep 17 00:00:00 2001 From: Julie Prestopnik Date: Wed, 15 Sep 2021 16:02:34 -0600 Subject: [PATCH 194/200] Testing double hyphen change to code-block --- met/docs/Users_Guide/installation.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/met/docs/Users_Guide/installation.rst b/met/docs/Users_Guide/installation.rst index ec53e46232..aa3f961b27 100644 --- a/met/docs/Users_Guide/installation.rst +++ b/met/docs/Users_Guide/installation.rst @@ -248,7 +248,9 @@ NOTE: Several compilation warnings may occur which are expected. If any errors o The configure script has command line options to specify where to install MET and which MET utilities to install. Include any of the following options that apply to your system: -**-\\-prefix=PREFIX** +.. code-block:: none + + \--prefix=PREFIX By default, MET will install all the files in "*/usr/local/bin*". You can specify an installation prefix other than "*/usr/local*" using "--prefix", for instance "--prefix=$HOME" or "--prefix=`pwd`". From f3393fdd426992b1826931bb89696520856a55df Mon Sep 17 00:00:00 2001 From: Julie Prestopnik Date: Wed, 15 Sep 2021 16:05:52 -0600 Subject: [PATCH 195/200] Testing double hyphen change to code-block --- met/docs/Users_Guide/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/met/docs/Users_Guide/installation.rst b/met/docs/Users_Guide/installation.rst index aa3f961b27..5ef3c15303 100644 --- a/met/docs/Users_Guide/installation.rst +++ b/met/docs/Users_Guide/installation.rst @@ -250,7 +250,7 @@ The configure script has command line options to specify where to install MET an .. code-block:: none - \--prefix=PREFIX + --prefix=PREFIX By default, MET will install all the files in "*/usr/local/bin*". You can specify an installation prefix other than "*/usr/local*" using "--prefix", for instance "--prefix=$HOME" or "--prefix=`pwd`". From 73ed4460d36bf0724c88981ebc250cfc63ab7622 Mon Sep 17 00:00:00 2001 From: Julie Prestopnik Date: Wed, 15 Sep 2021 16:59:26 -0600 Subject: [PATCH 196/200] Changed bolding of options to code-blocks --- met/docs/Users_Guide/installation.rst | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/met/docs/Users_Guide/installation.rst b/met/docs/Users_Guide/installation.rst index 5ef3c15303..963545ac2f 100644 --- a/met/docs/Users_Guide/installation.rst +++ b/met/docs/Users_Guide/installation.rst @@ -254,31 +254,43 @@ The configure script has command line options to specify where to install MET an By default, MET will install all the files in "*/usr/local/bin*". You can specify an installation prefix other than "*/usr/local*" using "--prefix", for instance "--prefix=$HOME" or "--prefix=`pwd`". -**-\\-enable-grib2** +.. code-block:: none + + --enable-grib2 Enable compilation of utilities using GRIB2. Requires $MET_GRIB2C. -**-\\-enable-python** +.. code-block:: none + + --enable-python Enable compilation of python interface. Requires $MET_PYTHON_CC and $MET_PYTHON_LD. -**-\\-enable-lidar2nc** +.. code-block:: none + --enable-lidar2nc + Enable compilation of utilities using the LIDAR2NC tool. -**-\\-enable-modis** +.. code-block:: none + + --enable-modis Enable compilation of the Modis-Regrid tool. Requires $MET_HDF, $MET_HDFEOSINC, and $MET_HDFEOSLIB. -**-\\-enable-mode_graphics** +.. code-block:: none + + --enable-mode_graphics Enable compilation of the MODE-Graphics tool. Requires $MET_CAIRO and $MET_FREETYPE. -**-\\-disable-block4** +.. code-block:: none + + --disable-block4 Disable use of BLOCK4 in the compilation. Use this if you have trouble using PrepBUFR files. -Run the configure script with the **--help** argument to see the full list of configuration options. +Run the configure script with the **-help** argument to see the full list of configuration options. Make Targets ~~~~~~~~~~~~ From 9998f49bacc1b0f29afb9108e54db990c35c98e9 Mon Sep 17 00:00:00 2001 From: Seth Linden Date: Wed, 15 Sep 2021 18:16:20 -0600 Subject: [PATCH 197/200] Feature 1858 obs quality (#1919) * Per issue #1858: changed parse_conf_obs_qty to parse_conf_obs_qty_inc. Added new function parse_conf_obs_qty_exc. SL * Per issue #1858: changed conf_key_obs_qty to conf_key_obs_qty_inc. Added conf_key_obs_qty_exc. SL * Per issue #1858: modified vx_pd.set_obs_qty_filt() to use parse_conf_obs_qty_inc() instead of parse_conf_obs_qty(). SL * Per issue #1858: added back the original parse_conf_obs_qty() function for backward compatibility. SL * Per issue #1858: added back config_constants.h for backwards compatibility. SL * Per issue #1858: added code to read in obs_qty_inc instead of obs_qty. Also added in code for backwards compatibility to check for obs_qty (obs_quality) and use that for obs_qty_inc. SL * Changed obs_qty_filt to obs_qty_inc_filt. Added obs_qty_exc_filt, including relevant function. SL * Per issue #1858 added vx_pd.set_obs_qty_exc_filt. SL * In add_point_obs() added if block to apply obs_qty_exc_filt. SL * Per issue #1858, in add_point_obs(), cleaned up sections that apply obs_qty_inc and obs_qty_exc filters. Fixed spacing issue. SL * Per issue #1858 in process_config(), cleaned up sections that set obs_qty_inc_filt and obs_qty_exc_filt. Fixed spacing issue. SL * Per issue #1858 in process_obs_file() cleaned up code. SL * Per issue #1858: changed obs_qty_filt to obs_qty_inc_filt. Added obs_qty_exc_filt. Modified add_point_obs() to use obs_qty_exc_filt. SL * Per issue #1858: in process_config(): added code to set_obs_qty_inc_filt and set_obs_qty_exc_filt. Also added code to check if old obs_quality is being used, if so, set it to obs_qty_inc_filt. SL * Per issue #1858: in add_point_obs() modified section that applies the obs_qty_inc and obs_qty_exc filters. Combined the if-blocks into one concise if-block that applies both filters. SL * Per issue #1858: replaced obs_quality with obs_quality_inc and added obs_quality_inc. SL * Per issue #1858: replaced obs_quality with obs_quality_inc and added obs_quality_exc. SL * Per issue #1858: For both the point_stat and ensemble_stat tests: modified tests that use OBS_QTY to use OBS_QTY_INC. Added unit test for OBS_QTY_EXC (obs_quality_exclude). SL * Per issue #1858: just added comment at top of file indicating what changed. SL * Per issue #1858: just added comment at top of file indicating what changed. SL * Per issue #1858: removed parse_conf_obs_qty. Modified parse_conf_obs_qty_inc to check for old 'obs_quality' entry. SL * Per issue #1858: in process_config(), modified section that calls set_obs_qty_inc_filt...this new function can now handle old 'obs_quality' entry as well as the new 'obs_quality_inc'. SL * Modified parse_conf_obs_qty_inc and parse_conf_obs_qty_exc. SL * Per issue #1858: re-updated parse_conf_obs_qty_exc and reverted back to the simplier version of this function. SL * Per issue #1858: replaced obs_quality with obs_quality_inc and added obs_quality_exc. SL * Per issue #1858: replaced obs_quality with obs_quality_inc and added obs_quality_exc. SL * Per issue #1858: replaced obs_quality with obs_quality_inc and added obs_quality_exc. SL * Per issue #1858: replaced obs_quality with obs_quality_inc and added obs_quality_exc. SL * Per issue #1858: replaced obs_quality with obs_quality_inc and added obs_quality_inc. SL * Per issue #1858: replaced obs_quality with obs_quality_inc. Added documentation for obs_quality_exc. SL * Per issue #1858: checking in latest version. Modified section that calls set_obs_qty_inc_filt...this new function can now handle old 'obs_quality' entry as well as the new 'obs_quality_inc'. SL * Per issue #1858: cleaned up some extra line spaces. SL * Per #1858, removed the deprecated obs_quality configuration entry from 3 EnsembleStat and 5 PointStat configuration files. * Per issue #1858: duplicated fcst/obs fields to run/test with both obs_quality_inc and obs_quality_exc. SL * Per issue #1858: duplicated fcst/obs fields to run/test with both obs_quality_inc and obs_quality_exc. SL * Per issue #1858. Deleted these files git repository. These were replaced with: PointStatConfig_qty_inc_exc. SL * Per issue #1858. Deleted these files from the git repository. These were replaced with: EnsembleStatConfig_qty_inc_exc. SL * Per issue #1858. Deleted these files from the git repository. These were replaced with: PointStatConfig_qty_inc_exc. SL * Per issue #1858: Modified: Don't need to run separate tests for obs_quality_inc and obs_quality_exc, these are now combined into one test via the updated config files: PointStatConfig_qty_inc_exc and EnsembleStatConfig_qty_inc_exc. SL * Per #1858, update the logic in parse_conf_obs_qty_inc() to use last_lookup_status(). See forthcoming GitHub issue comment about this. * Per #1858, tweak the warning message. * Per #1858, made the existing unit_quality_filter.xml tests a bit more concise. Call Point-Stat and Ensemble-Stat only once each time. But for each, test 3 things: all qty, obs_quality_inc, and obs_quality_exc. * Per #1858, remove the _ON from the job name since the _OFF has been included in the same configuration. Co-authored-by: Seth Linden Co-authored-by: John Halley Gotway Co-authored-by: John Halley Gotway --- met/data/config/EnsembleStatConfig_default | 3 +- met/data/config/PointStatConfig_default | 3 +- met/docs/Users_Guide/config_options.rst | 25 +++++-- met/docs/Users_Guide/ensemble-stat.rst | 3 +- met/docs/Users_Guide/point-stat.rst | 3 +- met/scripts/config/EnsembleStatConfig | 3 +- met/scripts/config/PointStatConfig | 3 +- met/src/basic/vx_config/config_constants.h | 2 + met/src/basic/vx_config/config_util.cc | 31 +++++++- met/src/basic/vx_config/config_util.h | 3 +- .../vx_statistics/pair_data_ensemble.cc | 36 ++++++---- .../vx_statistics/pair_data_ensemble.h | 10 +-- .../libcode/vx_statistics/pair_data_point.cc | 42 ++++++----- .../libcode/vx_statistics/pair_data_point.h | 10 +-- .../tools/core/ensemble_stat/ensemble_stat.cc | 2 + .../ensemble_stat/ensemble_stat_conf_info.cc | 17 +++-- met/src/tools/core/point_stat/point_stat.cc | 4 +- .../core/point_stat/point_stat_conf_info.cc | 11 +-- test/config/EnsembleStatConfig | 9 +-- test/config/EnsembleStatConfig_MASK_SID | 9 +-- test/config/EnsembleStatConfig_climo | 3 +- test/config/EnsembleStatConfig_grid_weight | 11 +-- test/config/EnsembleStatConfig_one_cdf_bin | 3 +- test/config/EnsembleStatConfig_python | 3 +- ...fig_qty => EnsembleStatConfig_qty_inc_exc} | 30 ++++++-- test/config/PointStatConfig_APCP | 4 +- test/config/PointStatConfig_APCP_HIRA | 2 + test/config/PointStatConfig_GTG_latlon | 2 + test/config/PointStatConfig_GTG_lc | 2 + test/config/PointStatConfig_INTERP_OPTS | 2 + test/config/PointStatConfig_LAND_TOPO_MASK | 2 + test/config/PointStatConfig_MASK_SID | 2 + test/config/PointStatConfig_PHYS | 2 + test/config/PointStatConfig_PHYS_pint | 2 + test/config/PointStatConfig_WINDS | 2 + test/config/PointStatConfig_aeronet | 11 +-- test/config/PointStatConfig_airnow | 3 +- test/config/PointStatConfig_climo | 11 +-- test/config/PointStatConfig_climo_WMO | 3 +- test/config/PointStatConfig_climo_prob | 9 +-- test/config/PointStatConfig_dup | 2 + test/config/PointStatConfig_mpr_thresh | 11 +-- test/config/PointStatConfig_obs_summary | 2 + test/config/PointStatConfig_obs_summary_all | 2 + test/config/PointStatConfig_prob | 2 + test/config/PointStatConfig_python | 3 +- ...Config_qty => PointStatConfig_qty_inc_exc} | 71 ++++++++++++++----- test/config/PointStatConfig_sid_inc_exc | 2 + test/xml/unit_quality_filter.xml | 71 ++++++------------- 49 files changed, 328 insertions(+), 176 deletions(-) rename test/config/{EnsembleStatConfig_qty => EnsembleStatConfig_qty_inc_exc} (87%) rename test/config/{PointStatConfig_qty => PointStatConfig_qty_inc_exc} (64%) diff --git a/met/data/config/EnsembleStatConfig_default b/met/data/config/EnsembleStatConfig_default index e18b258044..ea10765e17 100644 --- a/met/data/config/EnsembleStatConfig_default +++ b/met/data/config/EnsembleStatConfig_default @@ -114,7 +114,8 @@ message_type = [ "ADPUPA" ]; sid_inc = []; sid_exc = []; obs_thresh = [ NA ]; -obs_quality = []; +obs_quality_inc = []; +obs_quality_exc = []; duplicate_flag = NONE; obs_summary = NONE; obs_perc_value = 50; diff --git a/met/data/config/PointStatConfig_default b/met/data/config/PointStatConfig_default index 4cdaefaf6e..558e419726 100644 --- a/met/data/config/PointStatConfig_default +++ b/met/data/config/PointStatConfig_default @@ -97,7 +97,8 @@ obs = fcst; message_type = [ "ADPUPA" ]; sid_inc = []; sid_exc = []; -obs_quality = []; +obs_quality_inc = []; +obs_quality_exc = []; duplicate_flag = NONE; obs_summary = NONE; obs_perc_value = 50; diff --git a/met/docs/Users_Guide/config_options.rst b/met/docs/Users_Guide/config_options.rst index 5c3149b03f..23f67fecda 100644 --- a/met/docs/Users_Guide/config_options.rst +++ b/met/docs/Users_Guide/config_options.rst @@ -1997,20 +1997,37 @@ Percentile value to use when obs_summary = PERC obs_perc_value = 50; -.. _obs_quality: +.. _obs_quality_inc: -:ref:`obs_quality ` +:ref:`obs_quality_inc ` -The "obs_quality" entry specifies the quality flag values that are to be +The "obs_quality_inc" entry specifies the quality flag values that are to be retained and used for verification. An empty list signifies that all point observations should be used, regardless of their quality flag value. The quality flag values will vary depending on the original source of the observations. The quality flag values to retain should be specified as an array of strings, even if the values themselves are numeric. +Note "obs_quality_inc" replaces the older option "obs_quality". .. code-block:: none - obs_quality = [ "1", "2", "3", "9" ]; + obs_quality_inc = [ "1", "2", "3", "9" ]; + + +.. _obs_quality_exc: + +:ref:`obs_quality_exc ` + +The "obs_quality_exc" entry specifies the quality flag values that are to be +ignored and not used for verification. An empty list signifies that all +point observations should be used, regardless of their quality flag value. +The quality flag values will vary depending on the original source of the +observations. The quality flag values to ignore should be specified as +an array of strings, even if the values themselves are numeric. + +.. code-block:: none + + obs_quality_exc = [ "1", "2", "3", "9" ]; .. _met_data_dir: diff --git a/met/docs/Users_Guide/ensemble-stat.rst b/met/docs/Users_Guide/ensemble-stat.rst index d4763fe32f..a39424d289 100644 --- a/met/docs/Users_Guide/ensemble-stat.rst +++ b/met/docs/Users_Guide/ensemble-stat.rst @@ -149,7 +149,8 @@ ____________________ sid_inc = []; sid_exc = []; duplicate_flag = NONE; - obs_quality = []; + obs_quality_inc = []; + obs_quality_exc = []; obs_summary = NONE; obs_perc_value = 50; message_type_group_map = [...]; diff --git a/met/docs/Users_Guide/point-stat.rst b/met/docs/Users_Guide/point-stat.rst index c37c5b06d7..926ad1f0c5 100644 --- a/met/docs/Users_Guide/point-stat.rst +++ b/met/docs/Users_Guide/point-stat.rst @@ -342,7 +342,8 @@ ________________________ sid_inc = []; sid_exc = []; duplicate_flag = NONE; - obs_quality = []; + obs_quality_inc = []; + obs_quality_exc = []; obs_summary = NONE; obs_perc_value = 50; message_type_group_map = [...]; diff --git a/met/scripts/config/EnsembleStatConfig b/met/scripts/config/EnsembleStatConfig index c09cb523e8..91d4cab5d0 100644 --- a/met/scripts/config/EnsembleStatConfig +++ b/met/scripts/config/EnsembleStatConfig @@ -136,7 +136,8 @@ obs = fcst; sid_inc = []; sid_exc = []; obs_thresh = [ NA ]; -obs_quality = []; +obs_quality_inc = []; +obs_quality_exc = []; duplicate_flag = NONE; obs_summary = NONE; obs_perc_value = 50; diff --git a/met/scripts/config/PointStatConfig b/met/scripts/config/PointStatConfig index 513c956ab6..a39a25626e 100644 --- a/met/scripts/config/PointStatConfig +++ b/met/scripts/config/PointStatConfig @@ -77,7 +77,8 @@ obs = fcst; // sid_inc = []; sid_exc = []; -obs_quality = []; +obs_quality_inc = []; +obs_quality_exc = []; duplicate_flag = NONE; obs_summary = NONE; obs_percentile = 50; diff --git a/met/src/basic/vx_config/config_constants.h b/met/src/basic/vx_config/config_constants.h index f70c0863c1..a46559ca02 100644 --- a/met/src/basic/vx_config/config_constants.h +++ b/met/src/basic/vx_config/config_constants.h @@ -535,6 +535,8 @@ static const char conf_key_message_type[] = "message_type"; static const char conf_key_sid_inc[] = "sid_inc"; static const char conf_key_sid_exc[] = "sid_exc"; static const char conf_key_obs_qty[] = "obs_quality"; +static const char conf_key_obs_qty_inc[] = "obs_quality_inc"; +static const char conf_key_obs_qty_exc[] = "obs_quality_exc"; static const char conf_key_convert[] = "convert"; static const char conf_key_censor_thresh[] = "censor_thresh"; static const char conf_key_censor_val[] = "censor_val"; diff --git a/met/src/basic/vx_config/config_util.cc b/met/src/basic/vx_config/config_util.cc index 094e429bb7..934bec72b9 100644 --- a/met/src/basic/vx_config/config_util.cc +++ b/met/src/basic/vx_config/config_util.cc @@ -766,11 +766,36 @@ vector parse_conf_llpnt_mask(Dictionary *dict) { /////////////////////////////////////////////////////////////////////////////// -StringArray parse_conf_obs_qty(Dictionary *dict) { - const char *method_name = "parse_conf_obs_qty() -> "; +StringArray parse_conf_obs_qty_inc(Dictionary *dict) { + StringArray sa; + const char *method_name = "parse_conf_obs_qty_inc() -> "; + + // Check for old "obs_quality" entry + sa = dict->lookup_string_array(conf_key_obs_qty, false); - StringArray sa = parse_conf_string_array(dict, conf_key_obs_qty, method_name); + // Print a warning if the deprecated option was used + if(dict->last_lookup_status()) { + mlog << Warning << "\nparse_conf_obs_qty_inc() -> " + << "Set the \"" << conf_key_obs_qty_inc << "\" value (" + << write_css(sa) << ") from the deprecated \"" + << conf_key_obs_qty << "\" configuration entry.\n" + << "Replace \"" << conf_key_obs_qty << "\" with \"" + << conf_key_obs_qty_inc << "\"!\n\n"; + } + else { + sa = parse_conf_string_array(dict, conf_key_obs_qty_inc, method_name); + } + + return(sa); +} + +/////////////////////////////////////////////////////////////////////////////// +StringArray parse_conf_obs_qty_exc(Dictionary *dict) { + const char *method_name = "parse_conf_obs_qty_exc() -> "; + + StringArray sa = parse_conf_string_array(dict, conf_key_obs_qty_exc, method_name); + return(sa); } diff --git a/met/src/basic/vx_config/config_util.h b/met/src/basic/vx_config/config_util.h index a17d2badd3..5e83b2c6aa 100644 --- a/met/src/basic/vx_config/config_util.h +++ b/met/src/basic/vx_config/config_util.h @@ -40,7 +40,8 @@ extern StringArray parse_conf_sid_list(Dictionary *dict, const char *); extern void parse_sid_mask(const ConcatString &, StringArray &, ConcatString &); extern vector parse_conf_llpnt_mask(Dictionary *dict); -extern StringArray parse_conf_obs_qty(Dictionary *dict); +extern StringArray parse_conf_obs_qty_inc(Dictionary *dict); +extern StringArray parse_conf_obs_qty_exc(Dictionary *dict); extern NumArray parse_conf_ci_alpha(Dictionary *dict); extern NumArray parse_conf_eclv_points(Dictionary *dict); extern ClimoCDFInfo parse_conf_climo_cdf(Dictionary *dict); diff --git a/met/src/libcode/vx_statistics/pair_data_ensemble.cc b/met/src/libcode/vx_statistics/pair_data_ensemble.cc index a305fa64ea..0fcf84fc99 100644 --- a/met/src/libcode/vx_statistics/pair_data_ensemble.cc +++ b/met/src/libcode/vx_statistics/pair_data_ensemble.cc @@ -913,8 +913,9 @@ void VxPairDataEnsemble::clear() { sid_inc_filt.clear(); sid_exc_filt.clear(); - obs_qty_filt.clear(); - + obs_qty_inc_filt.clear(); + obs_qty_exc_filt.clear(); + obs_error_info = (ObsErrorInfo *) 0; fcst_ut = (unixtime) 0; @@ -954,7 +955,8 @@ void VxPairDataEnsemble::assign(const VxPairDataEnsemble &vx_pd) { end_ut = vx_pd.end_ut; sid_inc_filt = vx_pd.sid_inc_filt; sid_exc_filt = vx_pd.sid_exc_filt; - obs_qty_filt = vx_pd.obs_qty_filt; + obs_qty_inc_filt = vx_pd.obs_qty_inc_filt; + obs_qty_exc_filt = vx_pd.obs_qty_exc_filt; obs_error_info = vx_pd.obs_error_info; interp_thresh = vx_pd.interp_thresh; @@ -1132,9 +1134,18 @@ void VxPairDataEnsemble::set_sid_exc_filt(const StringArray sa) { //////////////////////////////////////////////////////////////////////// -void VxPairDataEnsemble::set_obs_qty_filt(const StringArray q) { +void VxPairDataEnsemble::set_obs_qty_inc_filt(const StringArray q) { - obs_qty_filt = q; + obs_qty_inc_filt = q; + + return; +} + +//////////////////////////////////////////////////////////////////////// + +void VxPairDataEnsemble::set_obs_qty_exc_filt(const StringArray q) { + + obs_qty_exc_filt = q; return; } @@ -1368,16 +1379,13 @@ void VxPairDataEnsemble::add_point_obs(float *hdr_arr, int *hdr_typ_arr, else if(obs_info_grib->code() != nint(obs_arr[1])) { return; } - - // Check if the observation quality flag is included in the list - if(obs_qty_filt.n() && strcmp(obs_qty, "")) { - bool qty_match = false; - for(i=0; i 0 && !obs_qty_inc_filt.has(obs_qty)) || + (obs_qty_exc_filt.n() > 0 && obs_qty_exc_filt.has(obs_qty))) { + return; } - + // Check whether the observation time falls within the valid time // window if(hdr_ut < beg_ut || hdr_ut > end_ut) return; diff --git a/met/src/libcode/vx_statistics/pair_data_ensemble.h b/met/src/libcode/vx_statistics/pair_data_ensemble.h index d5bad07d03..84aa45796b 100644 --- a/met/src/libcode/vx_statistics/pair_data_ensemble.h +++ b/met/src/libcode/vx_statistics/pair_data_ensemble.h @@ -205,8 +205,9 @@ class VxPairDataEnsemble { StringArray sid_inc_filt; // Station ID inclusion list StringArray sid_exc_filt; // Station ID exclusion list - StringArray obs_qty_filt; // Observation quality markers - + StringArray obs_qty_inc_filt; // Observation quality include markers + StringArray obs_qty_exc_filt; // Observation quality exclude markers + ////////////////////////////////////////////////////////////////// ObsErrorInfo *obs_error_info; // Pointer for observation error @@ -249,8 +250,9 @@ class VxPairDataEnsemble { void set_sid_inc_filt(const StringArray); void set_sid_exc_filt(const StringArray); - void set_obs_qty_filt(const StringArray); - + void set_obs_qty_inc_filt(const StringArray); + void set_obs_qty_exc_filt(const StringArray); + // Call set_pd_size before set_msg_typ, set_mask_area, and set_interp void set_pd_size(int, int, int); diff --git a/met/src/libcode/vx_statistics/pair_data_point.cc b/met/src/libcode/vx_statistics/pair_data_point.cc index d81b26ad85..a77749abba 100644 --- a/met/src/libcode/vx_statistics/pair_data_point.cc +++ b/met/src/libcode/vx_statistics/pair_data_point.cc @@ -372,7 +372,8 @@ void VxPairDataPoint::clear() { climo_sd_dpa.clear(); sid_inc_filt.clear(); sid_exc_filt.clear(); - obs_qty_filt.clear(); + obs_qty_inc_filt.clear(); + obs_qty_exc_filt.clear(); mpr_column.clear(); mpr_thresh.clear(); @@ -433,7 +434,8 @@ void VxPairDataPoint::assign(const VxPairDataPoint &vx_pd) { sid_inc_filt = vx_pd.sid_inc_filt; sid_exc_filt = vx_pd.sid_exc_filt; - obs_qty_filt = vx_pd.obs_qty_filt; + obs_qty_inc_filt = vx_pd.obs_qty_inc_filt; + obs_qty_exc_filt = vx_pd.obs_qty_exc_filt; mpr_column = vx_pd.mpr_column; mpr_thresh = vx_pd.mpr_thresh; @@ -629,9 +631,18 @@ void VxPairDataPoint::set_sid_exc_filt(const StringArray &sa) { //////////////////////////////////////////////////////////////////////// -void VxPairDataPoint::set_obs_qty_filt(const StringArray &sa) { +void VxPairDataPoint::set_obs_qty_inc_filt(const StringArray &sa) { - obs_qty_filt = sa; + obs_qty_inc_filt = sa; + + return; +} + +//////////////////////////////////////////////////////////////////////// + +void VxPairDataPoint::set_obs_qty_exc_filt(const StringArray &sa) { + + obs_qty_exc_filt = sa; return; } @@ -899,10 +910,10 @@ void VxPairDataPoint::add_point_obs(float *hdr_arr, const char *hdr_typ_str, rej_sid++; return; } - + // Check whether the GRIB code for the observation matches // the specified code - if((var_name != 0) && (0 < m_strlen(var_name))) { + if((var_name != 0) && (0 < strlen(var_name))) { if(var_name != obs_info->name()) { rej_var++; return; @@ -912,19 +923,14 @@ void VxPairDataPoint::add_point_obs(float *hdr_arr, const char *hdr_typ_str, rej_var++; return; } - - // Check if the observation quality flag is included in the list - if(obs_qty_filt.n() && strcmp(obs_qty, "")) { - bool qty_match = false; - for(i=0; i 0 && !obs_qty_inc_filt.has(obs_qty)) || + (obs_qty_exc_filt.n() > 0 && obs_qty_exc_filt.has(obs_qty))) { + rej_qty++; + return; } - + // Check whether the observation time falls within the valid time // window if(hdr_ut < beg_ut || hdr_ut > end_ut) { diff --git a/met/src/libcode/vx_statistics/pair_data_point.h b/met/src/libcode/vx_statistics/pair_data_point.h index 33a090e2dc..9c71c21cca 100644 --- a/met/src/libcode/vx_statistics/pair_data_point.h +++ b/met/src/libcode/vx_statistics/pair_data_point.h @@ -128,8 +128,9 @@ class VxPairDataPoint { StringArray sid_inc_filt; // Station ID inclusion list StringArray sid_exc_filt; // Station ID exclusion list - StringArray obs_qty_filt; // Observation quality markers - + StringArray obs_qty_inc_filt; // Observation quality include markers + StringArray obs_qty_exc_filt; // Observation quality exclude markers + ////////////////////////////////////////////////////////////////// StringArray mpr_column; // Names of MPR columns or diffs of columns @@ -199,8 +200,9 @@ class VxPairDataPoint { void set_sid_inc_filt(const StringArray &); void set_sid_exc_filt(const StringArray &); - void set_obs_qty_filt(const StringArray &); - + void set_obs_qty_inc_filt(const StringArray &); + void set_obs_qty_exc_filt(const StringArray &); + // Call set_pd_size before set_msg_typ, set_mask_area, and set_interp void set_pd_size(int, int, int); diff --git a/met/src/tools/core/ensemble_stat/ensemble_stat.cc b/met/src/tools/core/ensemble_stat/ensemble_stat.cc index eecc5c183f..d87c377bdf 100644 --- a/met/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/met/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -59,6 +59,8 @@ // 029 01/21/20 Halley Gotway Add RPS output line type. // 030 02/19/21 Halley Gotway MET #1450, #1451 Overhaul CRPS // statistics in the ECNT line type. +// 031 09/13/21 Seth Linden Changed obs_qty to obs_qty_inc. +// Added code for obs_qty_exc. // //////////////////////////////////////////////////////////////////////// diff --git a/met/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc b/met/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc index 9dcf7154d3..be4d4b582a 100644 --- a/met/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc +++ b/met/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc @@ -819,19 +819,22 @@ void EnsembleStatVxOpt::process_config(GrdFileType ftype, Dictionary &fdict, << "Observation error for point verification is " << "defined by a table lookup for each observation.\n"; } - + // Conf: desc vx_pd.set_desc(parse_conf_string(&odict, conf_key_desc).c_str()); - + // Conf: sid_inc vx_pd.set_sid_inc_filt(parse_conf_sid_list(&odict, conf_key_sid_inc)); - + // Conf: sid_exc vx_pd.set_sid_exc_filt(parse_conf_sid_list(&odict, conf_key_sid_exc)); - - // Conf: obs_qty - vx_pd.set_obs_qty_filt(parse_conf_obs_qty(&odict)); - + + // Conf: obs_qty_inc + vx_pd.set_obs_qty_inc_filt(parse_conf_obs_qty_inc(&odict)); + + // Conf: obs_qty_exc + vx_pd.set_obs_qty_exc_filt(parse_conf_obs_qty_exc(&odict)); + return; } diff --git a/met/src/tools/core/point_stat/point_stat.cc b/met/src/tools/core/point_stat/point_stat.cc index 36c1a3baf6..5f609feeff 100644 --- a/met/src/tools/core/point_stat/point_stat.cc +++ b/met/src/tools/core/point_stat/point_stat.cc @@ -96,6 +96,8 @@ // filtering options. // 046 05/28/21 Halley Gotway Add MCTS HSS_EC output. // 047 08/23/21 Seth Linden Add ORANK line type for HiRA. +// 048 09/13/21 Seth Linden Changed obs_qty to obs_qty_inc. +// Added code for obs_qty_exc. // //////////////////////////////////////////////////////////////////////// @@ -697,9 +699,7 @@ void process_obs_file(int i_nc) { StringArray obs_qty_array = nc_point_obs.get_qty_data(); if( use_var_id ) var_names = nc_point_obs.get_var_names(); - int buf_size = ((obs_count > BUFFER_SIZE) ? BUFFER_SIZE : (obs_count)); - int obs_qty_idx_block[buf_size]; float obs_arr_block[buf_size][OBS_ARRAY_LEN]; diff --git a/met/src/tools/core/point_stat/point_stat_conf_info.cc b/met/src/tools/core/point_stat/point_stat_conf_info.cc index dd0d13dee1..87183cb5d0 100644 --- a/met/src/tools/core/point_stat/point_stat_conf_info.cc +++ b/met/src/tools/core/point_stat/point_stat_conf_info.cc @@ -915,10 +915,13 @@ void PointStatVxOpt::process_config(GrdFileType ftype, // Conf: sid_exc vx_pd.set_sid_exc_filt(parse_conf_sid_list(&odict, conf_key_sid_exc)); - - // Conf: obs_qty - vx_pd.set_obs_qty_filt(parse_conf_obs_qty(&odict)); - + + // Conf: obs_qty_inc + vx_pd.set_obs_qty_inc_filt(parse_conf_obs_qty_inc(&odict)); + + // Conf: obs_qty_exc + vx_pd.set_obs_qty_exc_filt(parse_conf_obs_qty_exc(&odict)); + return; } diff --git a/test/config/EnsembleStatConfig b/test/config/EnsembleStatConfig index be1bae6735..c99f8da963 100644 --- a/test/config/EnsembleStatConfig +++ b/test/config/EnsembleStatConfig @@ -89,9 +89,11 @@ nmep_smooth = { // Forecast and observation fields to be verified // fcst = { - message_type = [ "ADPSFC" ]; - sid_inc = []; - sid_exc = []; + message_type = [ "ADPSFC" ]; + sid_inc = []; + sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; field = [ { @@ -118,7 +120,6 @@ obs = fcst; // May be set separately in each "obs.field" entry // obs_thresh = [ NA ]; -obs_quality = []; duplicate_flag = NONE; obs_summary = NONE; obs_perc_value = 50; diff --git a/test/config/EnsembleStatConfig_MASK_SID b/test/config/EnsembleStatConfig_MASK_SID index 6dd857db76..d33e7d9bd9 100644 --- a/test/config/EnsembleStatConfig_MASK_SID +++ b/test/config/EnsembleStatConfig_MASK_SID @@ -86,9 +86,11 @@ nmep_smooth = { // Forecast and observation fields to be verified // fcst = { - message_type = [ "ADPSFC" ]; - sid_inc = []; - sid_exc = []; + message_type = [ "ADPSFC" ]; + sid_inc = []; + sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; field = [ { @@ -108,7 +110,6 @@ obs = fcst; // May be set separately in each "obs.field" entry // obs_thresh = [ NA ]; -obs_quality = []; duplicate_flag = NONE; obs_summary = NONE; obs_perc_value = 50; diff --git a/test/config/EnsembleStatConfig_climo b/test/config/EnsembleStatConfig_climo index d209f009c9..1656128df9 100644 --- a/test/config/EnsembleStatConfig_climo +++ b/test/config/EnsembleStatConfig_climo @@ -128,7 +128,8 @@ climo_cdf = { // May be set separately in each "obs.field" entry // obs_thresh = [ NA ]; -obs_quality = []; +obs_quality_inc = []; +obs_quality_exc = []; duplicate_flag = NONE; obs_summary = NONE; obs_perc_value = 50; diff --git a/test/config/EnsembleStatConfig_grid_weight b/test/config/EnsembleStatConfig_grid_weight index 3a40783171..da710a73e5 100644 --- a/test/config/EnsembleStatConfig_grid_weight +++ b/test/config/EnsembleStatConfig_grid_weight @@ -80,10 +80,12 @@ nmep_smooth = { // Forecast and observation fields to be verified // fcst = { - message_type = [ "APDSFC" ]; - sid_inc = []; - sid_exc = []; - field = tmp_field; + message_type = [ "APDSFC" ]; + sid_inc = []; + sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; + field = tmp_field; } obs = fcst; @@ -94,7 +96,6 @@ obs = fcst; // May be set separately in each "obs.field" entry // obs_thresh = [ NA ]; -obs_quality = []; duplicate_flag = NONE; obs_summary = NONE; obs_perc_value = 50; diff --git a/test/config/EnsembleStatConfig_one_cdf_bin b/test/config/EnsembleStatConfig_one_cdf_bin index 3343bb6a2e..7e19af2b80 100644 --- a/test/config/EnsembleStatConfig_one_cdf_bin +++ b/test/config/EnsembleStatConfig_one_cdf_bin @@ -123,7 +123,8 @@ climo_cdf = { // May be set separately in each "obs.field" entry // obs_thresh = [ NA ]; -obs_quality = []; +obs_quality_inc = []; +obs_quality_exc = []; duplicate_flag = NONE; obs_summary = NONE; obs_perc_value = 50; diff --git a/test/config/EnsembleStatConfig_python b/test/config/EnsembleStatConfig_python index 48eef201c6..de502a7250 100644 --- a/test/config/EnsembleStatConfig_python +++ b/test/config/EnsembleStatConfig_python @@ -104,7 +104,8 @@ message_type = []; sid_inc = []; sid_exc = []; obs_thresh = [ NA ]; -obs_quality = []; +obs_quality_inc = []; +obs_quality_exc = []; duplicate_flag = NONE; obs_summary = NONE; obs_perc_value = 50; diff --git a/test/config/EnsembleStatConfig_qty b/test/config/EnsembleStatConfig_qty_inc_exc similarity index 87% rename from test/config/EnsembleStatConfig_qty rename to test/config/EnsembleStatConfig_qty_inc_exc index 83ecacdbb1..17009a61a0 100644 --- a/test/config/EnsembleStatConfig_qty +++ b/test/config/EnsembleStatConfig_qty_inc_exc @@ -90,9 +90,27 @@ fcst = { field = [ { - name = "TMP"; - level = [ "Z2" ]; - obs_quality = [ ${OBS_QUALITY} ]; + name = "TMP"; + level = [ "Z2" ]; + obs_quality_inc = []; + obs_quality_exc = []; + desc = "ALL_QTY"; + }, + + { + name = "TMP"; + level = [ "Z2" ]; + obs_quality_inc = [ ${OBS_QUALITY_INC} ]; + obs_quality_exc = []; + desc = "QTY_INC"; + }, + + { + name = "TMP"; + level = [ "Z2" ]; + obs_quality_inc = []; + obs_quality_exc = [ ${OBS_QUALITY_EXC} ]; + desc = "QTY_EXC"; } ]; } @@ -186,10 +204,10 @@ output_flag = { ecnt = BOTH; rps = NONE; rhist = BOTH; - phist = BOTH; + phist = NONE; orank = BOTH; - ssvar = BOTH; - relp = BOTH; + ssvar = NONE; + relp = NONE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/config/PointStatConfig_APCP b/test/config/PointStatConfig_APCP index ea8b55a5b4..002e33aa49 100644 --- a/test/config/PointStatConfig_APCP +++ b/test/config/PointStatConfig_APCP @@ -42,7 +42,9 @@ eclv_points = 0.05; fcst = { sid_inc = []; sid_exc = []; - + obs_quality_inc = []; + obs_quality_exc = []; + field = [ { name = "${FCST_FIELD_NAME}"; diff --git a/test/config/PointStatConfig_APCP_HIRA b/test/config/PointStatConfig_APCP_HIRA index 412d2d8fe7..1972bec64b 100644 --- a/test/config/PointStatConfig_APCP_HIRA +++ b/test/config/PointStatConfig_APCP_HIRA @@ -42,6 +42,8 @@ eclv_points = 0.05; cat_thresh = [ >0.254, >2.540 ]; sid_inc = []; sid_exc = []; +obs_quality_inc = []; +obs_quality_exc = []; fcst = { field = [ diff --git a/test/config/PointStatConfig_GTG_latlon b/test/config/PointStatConfig_GTG_latlon index 1ac24d927e..a7fc58e970 100644 --- a/test/config/PointStatConfig_GTG_latlon +++ b/test/config/PointStatConfig_GTG_latlon @@ -60,6 +60,8 @@ obs = { message_type = [ "MEDEDR", "MAXEDR" ]; sid_inc = []; sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; field = [ { diff --git a/test/config/PointStatConfig_GTG_lc b/test/config/PointStatConfig_GTG_lc index 5efd47662c..a9dab3da7a 100644 --- a/test/config/PointStatConfig_GTG_lc +++ b/test/config/PointStatConfig_GTG_lc @@ -65,6 +65,8 @@ obs = { message_type = [ "MEDEDR", "MAXEDR" ]; sid_inc = []; sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; field = [ { diff --git a/test/config/PointStatConfig_INTERP_OPTS b/test/config/PointStatConfig_INTERP_OPTS index c255c5b565..7898e9e17e 100644 --- a/test/config/PointStatConfig_INTERP_OPTS +++ b/test/config/PointStatConfig_INTERP_OPTS @@ -43,6 +43,8 @@ eclv_points = 0.05; fcst = { sid_inc = []; sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; field = [ { name = "TMP"; level = "Z2"; message_type = "ADPSFC"; } diff --git a/test/config/PointStatConfig_LAND_TOPO_MASK b/test/config/PointStatConfig_LAND_TOPO_MASK index 4d1ab530fc..c03318bcf6 100644 --- a/test/config/PointStatConfig_LAND_TOPO_MASK +++ b/test/config/PointStatConfig_LAND_TOPO_MASK @@ -42,6 +42,8 @@ eclv_points = 0.05; fcst = { sid_inc = []; sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; name = "TMP"; level = "Z2"; diff --git a/test/config/PointStatConfig_MASK_SID b/test/config/PointStatConfig_MASK_SID index e4174e9e9a..30f427d627 100644 --- a/test/config/PointStatConfig_MASK_SID +++ b/test/config/PointStatConfig_MASK_SID @@ -42,6 +42,8 @@ eclv_points = 0.05; fcst = { sid_inc = []; sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; field = [ { name = "TMP"; level = "Z2"; cat_thresh = [ <=273, >273 ]; message_type = "ADPSFC"; }, diff --git a/test/config/PointStatConfig_PHYS b/test/config/PointStatConfig_PHYS index 7a767a54da..2e227a74b3 100644 --- a/test/config/PointStatConfig_PHYS +++ b/test/config/PointStatConfig_PHYS @@ -42,6 +42,8 @@ eclv_points = 0.05; fcst = { sid_inc = []; sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; field = [ { name = "TMP"; level = "Z2"; message_type = "ADPSFC"; cat_thresh = [ <=273, >273 ]; diff --git a/test/config/PointStatConfig_PHYS_pint b/test/config/PointStatConfig_PHYS_pint index 4149345038..9ca75701a8 100644 --- a/test/config/PointStatConfig_PHYS_pint +++ b/test/config/PointStatConfig_PHYS_pint @@ -50,6 +50,8 @@ fcst = { obs = { sid_inc = []; sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; field = [ { name = "TMP"; level = "Z2"; cat_thresh = [ <=273, >273 ]; message_type = "ADPSFC"; }, diff --git a/test/config/PointStatConfig_WINDS b/test/config/PointStatConfig_WINDS index 2b3ff9988e..8156066edb 100644 --- a/test/config/PointStatConfig_WINDS +++ b/test/config/PointStatConfig_WINDS @@ -55,6 +55,8 @@ message_type_group_map = [ fcst = { sid_inc = []; sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; message_type = [ "ADPSFC", "SFCSHP", "USERSF" ]; wind_thresh = [ NA, >=3, >=5 ]; diff --git a/test/config/PointStatConfig_aeronet b/test/config/PointStatConfig_aeronet index 58579bdf68..69799ede63 100644 --- a/test/config/PointStatConfig_aeronet +++ b/test/config/PointStatConfig_aeronet @@ -54,10 +54,12 @@ fcst = { } obs = { - message_type = [ "AERONET_AOD_MEAN_010000" ]; - sid_inc = []; - sid_exc = []; - + message_type = [ "AERONET_AOD_MEAN_010000" ]; + sid_inc = []; + sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; + field = [ { name = "AOD"; @@ -201,7 +203,6 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// -obs_quality = []; duplicate_flag = NONE; rank_corr_flag = TRUE; tmp_dir = "/tmp"; diff --git a/test/config/PointStatConfig_airnow b/test/config/PointStatConfig_airnow index 7420b10455..80df21807a 100644 --- a/test/config/PointStatConfig_airnow +++ b/test/config/PointStatConfig_airnow @@ -74,7 +74,8 @@ obs = { // sid_inc = []; sid_exc = []; -obs_quality = []; +obs_quality_inc = []; +obs_quality_exc = []; duplicate_flag = NONE; obs_summary = NONE; obs_perc_value = 50; diff --git a/test/config/PointStatConfig_climo b/test/config/PointStatConfig_climo index cb6eaea84b..041642d1a6 100644 --- a/test/config/PointStatConfig_climo +++ b/test/config/PointStatConfig_climo @@ -44,10 +44,12 @@ eclv_points = 0.05; // Forecast and observation fields to be verified // fcst = { - sid_inc = []; - sid_exc = []; - cat_thresh = []; - message_type = [ "ADPSFC" ]; + sid_inc = []; + sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; + cat_thresh = []; + message_type = [ "ADPSFC" ]; field = [ { @@ -270,7 +272,6 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// -obs_quality = []; duplicate_flag = NONE; rank_corr_flag = TRUE; tmp_dir = "/tmp"; diff --git a/test/config/PointStatConfig_climo_WMO b/test/config/PointStatConfig_climo_WMO index 201e794890..599797cde3 100644 --- a/test/config/PointStatConfig_climo_WMO +++ b/test/config/PointStatConfig_climo_WMO @@ -42,6 +42,8 @@ eclv_points = 0.05; message_type = [ "ADPUPA" ]; sid_inc = []; sid_exc = []; +obs_quality_inc = []; +obs_quality_exc = []; // // Forecast and observation fields to be verified @@ -218,7 +220,6 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// -obs_quality = []; duplicate_flag = NONE; rank_corr_flag = TRUE; tmp_dir = "/tmp"; diff --git a/test/config/PointStatConfig_climo_prob b/test/config/PointStatConfig_climo_prob index 2447701f95..e57f5e003f 100644 --- a/test/config/PointStatConfig_climo_prob +++ b/test/config/PointStatConfig_climo_prob @@ -65,9 +65,11 @@ fcst = { } obs = { - sid_inc = []; - sid_exc = []; - message_type = [ "ADPSFC" ]; + sid_inc = []; + sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; + message_type = [ "ADPSFC" ]; field = [ { @@ -220,7 +222,6 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// -obs_quality = []; duplicate_flag = NONE; rank_corr_flag = TRUE; tmp_dir = "/tmp"; diff --git a/test/config/PointStatConfig_dup b/test/config/PointStatConfig_dup index 9298bb58ec..9e8b6a68c7 100644 --- a/test/config/PointStatConfig_dup +++ b/test/config/PointStatConfig_dup @@ -45,6 +45,8 @@ fcst = { message_type = [ "ADPSFC" ]; sid_inc = []; sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; field = [ { diff --git a/test/config/PointStatConfig_mpr_thresh b/test/config/PointStatConfig_mpr_thresh index 66bde341ef..6da3ee7c63 100644 --- a/test/config/PointStatConfig_mpr_thresh +++ b/test/config/PointStatConfig_mpr_thresh @@ -44,10 +44,12 @@ eclv_points = 0.05; // Forecast and observation fields to be verified // fcst = { - sid_inc = []; - sid_exc = []; - cat_thresh = []; - message_type = [ "ADPSFC" ]; + sid_inc = []; + sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; + cat_thresh = []; + message_type = [ "ADPSFC" ]; name = "TMP"; level = "Z2"; @@ -212,7 +214,6 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// -obs_quality = []; duplicate_flag = NONE; rank_corr_flag = TRUE; tmp_dir = "/tmp"; diff --git a/test/config/PointStatConfig_obs_summary b/test/config/PointStatConfig_obs_summary index b8129521ec..8530672ab9 100644 --- a/test/config/PointStatConfig_obs_summary +++ b/test/config/PointStatConfig_obs_summary @@ -48,6 +48,8 @@ fcst = { message_type = [ "ADPSFC" ]; sid_inc = []; sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; field = [ { diff --git a/test/config/PointStatConfig_obs_summary_all b/test/config/PointStatConfig_obs_summary_all index 080ba56dff..0d868dd519 100644 --- a/test/config/PointStatConfig_obs_summary_all +++ b/test/config/PointStatConfig_obs_summary_all @@ -48,6 +48,8 @@ fcst = { message_type = [ "ADPSFC" ]; sid_inc = []; sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; field = [ { diff --git a/test/config/PointStatConfig_prob b/test/config/PointStatConfig_prob index e2ed42b77f..c576eb31f5 100644 --- a/test/config/PointStatConfig_prob +++ b/test/config/PointStatConfig_prob @@ -55,6 +55,8 @@ fcst = { obs = { sid_inc = []; sid_exc = []; + obs_quality_inc = []; + obs_quality_exc = []; field = [ { diff --git a/test/config/PointStatConfig_python b/test/config/PointStatConfig_python index 752fb7a928..2e97f43f29 100644 --- a/test/config/PointStatConfig_python +++ b/test/config/PointStatConfig_python @@ -72,7 +72,8 @@ obs = { message_type = [ "ADPSFC" ]; sid_inc = []; sid_exc = []; -obs_quality = []; +obs_quality_inc = []; +obs_quality_exc = []; duplicate_flag = NONE; obs_summary = NONE; obs_perc_value = 50; diff --git a/test/config/PointStatConfig_qty b/test/config/PointStatConfig_qty_inc_exc similarity index 64% rename from test/config/PointStatConfig_qty rename to test/config/PointStatConfig_qty_inc_exc index 6f7db1b826..6e4f88509a 100644 --- a/test/config/PointStatConfig_qty +++ b/test/config/PointStatConfig_qty_inc_exc @@ -40,24 +40,63 @@ eclv_points = 0.05; // Forecast and observation fields to be verified // fcst = { - sid_inc = []; - sid_exc = []; + sid_inc = []; + sid_exc = []; + cat_thresh = [ <=273, >273 ]; field = [ { - name = "TMP"; - level = [ "Z2" ]; - cat_thresh = [ <=273, >273 ]; - message_type = [ "ADPSFC" ]; - obs_quality = [ ${OBS_QUALITY_SFC} ]; + name = "TMP"; + level = [ "Z2" ]; + message_type = [ "ADPSFC" ]; + obs_quality_inc = []; + obs_quality_exc = []; + desc = "ALL_QTY"; }, { - name = "TMP"; - level = [ "P500" ]; - cat_thresh = [ <=273, >273 ]; - message_type = [ "ADPUPA" ]; - obs_quality = [ ${OBS_QUALITY_UPA} ]; + name = "TMP"; + level = [ "P500" ]; + message_type = [ "ADPUPA" ]; + obs_quality_inc = []; + obs_quality_exc = []; + desc = "ALL_QTY"; + }, + + { + name = "TMP"; + level = [ "Z2" ]; + message_type = [ "ADPSFC" ]; + obs_quality_inc = [ ${OBS_QUALITY_INC_SFC} ]; + obs_quality_exc = []; + desc = "QTY_INC_SFC"; + }, + + { + name = "TMP"; + level = [ "P500" ]; + message_type = [ "ADPUPA" ]; + obs_quality_inc = [ ${OBS_QUALITY_INC_UPA} ]; + obs_quality_exc = []; + desc = "QTY_INC_UPA"; + }, + + { + name = "TMP"; + level = [ "Z2" ]; + message_type = [ "ADPSFC" ]; + obs_quality_inc = []; + obs_quality_exc = [ ${OBS_QUALITY_EXC_SFC} ]; + desc = "QTY_EXC_SFC"; + }, + + { + name = "TMP"; + level = [ "P500" ]; + message_type = [ "ADPUPA" ]; + obs_quality_inc = []; + obs_quality_exc = [ ${OBS_QUALITY_EXC_UPA} ]; + desc = "QTY_EXC_UPA"; } ]; @@ -137,12 +176,12 @@ hira = { // Statistical output types // output_flag = { - fho = BOTH; + fho = NONE; ctc = BOTH; - cts = BOTH; + cts = NONE; mctc = NONE; mcts = NONE; - cnt = BOTH; + cnt = NONE; sl1l2 = BOTH; sal1l2 = NONE; vl1l2 = NONE; @@ -155,7 +194,7 @@ output_flag = { ecnt = NONE; orank = NONE; rps = NONE; - eclv = BOTH; + eclv = NONE; mpr = BOTH; } diff --git a/test/config/PointStatConfig_sid_inc_exc b/test/config/PointStatConfig_sid_inc_exc index 9dc3e7fdcf..7ae01d3238 100644 --- a/test/config/PointStatConfig_sid_inc_exc +++ b/test/config/PointStatConfig_sid_inc_exc @@ -42,6 +42,8 @@ wind_logic = UNION; eclv_points = 0.05; sid_inc = []; sid_exc = []; +obs_quality_inc = []; +obs_quality_exc = []; fcst = { diff --git a/test/xml/unit_quality_filter.xml b/test/xml/unit_quality_filter.xml index 5fcd30625d..912f52bda3 100644 --- a/test/xml/unit_quality_filter.xml +++ b/test/xml/unit_quality_filter.xml @@ -20,77 +20,52 @@ - + &MET_BIN;/point_stat - OBS_QUALITY_SFC "8" - OBS_QUALITY_UPA "2" - OUTPUT_PREFIX QTY_PB + OBS_QUALITY_INC_SFC "8" + OBS_QUALITY_INC_UPA "2" + OBS_QUALITY_EXC_SFC "9" + OBS_QUALITY_EXC_UPA "9" + OUTPUT_PREFIX QTY_INC_EXC_PB \ &DATA_DIR_MODEL;/grib1/nam/nam_2012040900_F012.grib \ &OUTPUT_DIR;/pb2nc/gdas1.20120409.t12z.prepbufr.nc \ - &CONFIG_DIR;/PointStatConfig_qty \ + &CONFIG_DIR;/PointStatConfig_qty_inc_exc \ -outdir &OUTPUT_DIR;/point_stat -v 3 - &OUTPUT_DIR;/point_stat/point_stat_QTY_PB_120000L_20120409_120000V.stat - &OUTPUT_DIR;/point_stat/point_stat_QTY_PB_120000L_20120409_120000V_fho.txt - &OUTPUT_DIR;/point_stat/point_stat_QTY_PB_120000L_20120409_120000V_ctc.txt - &OUTPUT_DIR;/point_stat/point_stat_QTY_PB_120000L_20120409_120000V_cts.txt - &OUTPUT_DIR;/point_stat/point_stat_QTY_PB_120000L_20120409_120000V_cnt.txt - &OUTPUT_DIR;/point_stat/point_stat_QTY_PB_120000L_20120409_120000V_sl1l2.txt - &OUTPUT_DIR;/point_stat/point_stat_QTY_PB_120000L_20120409_120000V_mpr.txt + &OUTPUT_DIR;/point_stat/point_stat_QTY_INC_EXC_PB_120000L_20120409_120000V.stat + &OUTPUT_DIR;/point_stat/point_stat_QTY_INC_EXC_PB_120000L_20120409_120000V_ctc.txt + &OUTPUT_DIR;/point_stat/point_stat_QTY_INC_EXC_PB_120000L_20120409_120000V_sl1l2.txt + &OUTPUT_DIR;/point_stat/point_stat_QTY_INC_EXC_PB_120000L_20120409_120000V_mpr.txt - - - &MET_BIN;/point_stat - - OBS_QUALITY_SFC - OBS_QUALITY_UPA - OUTPUT_PREFIX QTY_PB - - \ - &DATA_DIR_MODEL;/grib1/nam/nam_2012040900_F012.grib \ - &OUTPUT_DIR;/pb2nc/gdas1.20120409.t12z.prepbufr.nc \ - &CONFIG_DIR;/PointStatConfig_qty \ - -outdir &OUTPUT_DIR;/point_stat -v 3 - - - &OUTPUT_DIR;/point_stat/point_stat_QTY_PB_120000L_20120409_120000V.stat - &OUTPUT_DIR;/point_stat/point_stat_QTY_PB_120000L_20120409_120000V_fho.txt - &OUTPUT_DIR;/point_stat/point_stat_QTY_PB_120000L_20120409_120000V_ctc.txt - &OUTPUT_DIR;/point_stat/point_stat_QTY_PB_120000L_20120409_120000V_cts.txt - &OUTPUT_DIR;/point_stat/point_stat_QTY_PB_120000L_20120409_120000V_cnt.txt - &OUTPUT_DIR;/point_stat/point_stat_QTY_PB_120000L_20120409_120000V_sl1l2.txt - &OUTPUT_DIR;/point_stat/point_stat_QTY_PB_120000L_20120409_120000V_mpr.txt - - - - + + &MET_BIN;/ensemble_stat - OBS_QUALITY "V", "G", "S" - OUTPUT_PREFIX QTY_MADIS_VGS + OBS_QUALITY_INC "V", "G", "S" + OBS_QUALITY_EXC "C" + OUTPUT_PREFIX QTY_INC_EXC_MADIS_VGS \ 3 \ &DATA_DIR_MODEL;/grib1/arw-fer-gep1/arw-fer-gep1_2012040900_F012.grib \ &DATA_DIR_MODEL;/grib1/arw-sch-gep2/arw-sch-gep2_2012040900_F012.grib \ &DATA_DIR_MODEL;/grib1/arw-tom-gep3/arw-tom-gep3_2012040900_F012.grib \ - &CONFIG_DIR;/EnsembleStatConfig_qty \ + &CONFIG_DIR;/EnsembleStatConfig_qty_inc_exc \ -point_obs &OUTPUT_DIR;/madis2nc/metar_2012040912_F000.nc \ -outdir &OUTPUT_DIR;/ensemble_stat -v 3 - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_QTY_MADIS_VGS_20120409_120000V.stat - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_QTY_MADIS_VGS_20120409_120000V_ecnt.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_QTY_MADIS_VGS_20120409_120000V_rhist.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_QTY_MADIS_VGS_20120409_120000V_phist.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_QTY_MADIS_VGS_20120409_120000V_orank.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_QTY_MADIS_VGS_20120409_120000V_ens.nc + &OUTPUT_DIR;/ensemble_stat/ensemble_stat_QTY_INC_EXC_MADIS_VGS_20120409_120000V.stat + &OUTPUT_DIR;/ensemble_stat/ensemble_stat_QTY_INC_EXC_MADIS_VGS_20120409_120000V_ecnt.txt + &OUTPUT_DIR;/ensemble_stat/ensemble_stat_QTY_INC_EXC_MADIS_VGS_20120409_120000V_rhist.txt + &OUTPUT_DIR;/ensemble_stat/ensemble_stat_QTY_INC_EXC_MADIS_VGS_20120409_120000V_orank.txt + &OUTPUT_DIR;/ensemble_stat/ensemble_stat_QTY_INC_EXC_MADIS_VGS_20120409_120000V_ens.nc - + From 054fe2cac7b016a0037302c8b3f586fb3a607288 Mon Sep 17 00:00:00 2001 From: hsoh-u Date: Wed, 15 Sep 2021 18:16:59 -0600 Subject: [PATCH 198/200] Feature 1894 pb2nc var all (#1917) * #1894 Added station ID 14008 to pb2nc_NDAS_var_all unit test * #1894 Check the existance of the valid data up to 16 levels Co-authored-by: Howard Soh --- met/src/tools/other/pb2nc/pb2nc.cc | 24 +++++++++++++++--------- test/xml/unit_pb2nc.xml | 2 +- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/met/src/tools/other/pb2nc/pb2nc.cc b/met/src/tools/other/pb2nc/pb2nc.cc index e0c0416670..2b2c715518 100644 --- a/met/src/tools/other/pb2nc/pb2nc.cc +++ b/met/src/tools/other/pb2nc/pb2nc.cc @@ -130,8 +130,7 @@ static const int mxr8vt = 6; static const int mxr8nm = 8; // Maximum number of BUFR variable types -// Length of the "YYYYMMDD_HHMMSS" string -static const int COUNT_THRESHOLD = 5; +static const int COUNT_THRESHOLD = 16; // File unit number for opening the PrepBufr file static const int file_unit = 11; @@ -2004,7 +2003,7 @@ void process_pbfile_metadata(int i_pb) { int lv, var_index; int debug_threshold = 10; - int tmp_nlev_max_req = mxr8lv_small; + int nlev_max_req; bool check_all = do_all_vars || collect_metadata; char hdr_typ[max_str_len]; StringArray tmp_bufr_obs_name_arr; @@ -2110,6 +2109,8 @@ void process_pbfile_metadata(int i_pb) { int length; bool is_prepbufr_hdr = false; bool showed_progress = false; + + nlev_max_req = (mxr8lv_small > COUNT_THRESHOLD) ? COUNT_THRESHOLD : mxr8lv_small; // Loop through the PrepBufr messages from the input file for(i_read=0; i_read=0; vIdx--) { - int nlev2, buf_nlev; + int nlev2, count; bool has_valid_data; ConcatString var_name = unchecked_var_list[vIdx]; int var_name_len = var_name.length(); - readpbint_(&unit, &i_ret, &nlev2, bufr_obs, (char*)var_name.c_str(), &var_name_len, &tmp_nlev_max_req); + readpbint_(&unit, &i_ret, &nlev2, bufr_obs, (char*)var_name.c_str(), &var_name_len, &nlev_max_req); if (0 >= nlev2) continue; - // Checks the first level intread of searching through the vertical levels - lv = 0; - has_valid_data = (bufr_obs[lv][0] < r8bfms); + // Search through the vertical levels + has_valid_data = false; + for(lv=0; lv &MET_BIN;/pb2nc - STATION_ID "72364","72265","72274","72426","72489" + STATION_ID "72364","72265","72274","72426","72489","14008" MASK_GRID MASK_POLY QUALITY_MARK_THRESH 2 From c104425f720365d797ab07b97545d1cc09f7a990 Mon Sep 17 00:00:00 2001 From: hsoh-u Date: Wed, 15 Sep 2021 18:17:39 -0600 Subject: [PATCH 199/200] Feature 1913 MAX_PBL (#1916) * #1913 Changed MAX_PBL to 10000. Filter out if the PBL input data is invalid * #1912 Replaced is_eq to is_bad_data * #1913 Changed is_eq to is_bad_data Co-authored-by: Howard Soh --- met/src/tools/other/pb2nc/pb2nc.cc | 96 +++++++++++--------- met/src/tools/other/point2grid/point2grid.cc | 22 ++--- 2 files changed, 62 insertions(+), 56 deletions(-) diff --git a/met/src/tools/other/pb2nc/pb2nc.cc b/met/src/tools/other/pb2nc/pb2nc.cc index 2b2c715518..ec8372b0f8 100644 --- a/met/src/tools/other/pb2nc/pb2nc.cc +++ b/met/src/tools/other/pb2nc/pb2nc.cc @@ -166,7 +166,7 @@ static float static_dummy_200[MAX_CAPE_LEVEL]; static float static_dummy_201[MAX_CAPE_LEVEL+1]; #define ROG 287.04 -#define MAX_PBL 5000 +#define MAX_PBL 10000 #define MAX_PBL_LEVEL 256 #define PBL_DEBUG_LEVEL 8 static bool IGNORE_Q_PBL = true; @@ -374,6 +374,7 @@ static void insert_pbl(float *obs_arr, const float pbl_value, const int pbl_co const ConcatString &hdr_typ, const ConcatString &hdr_sid); static int interpolate_by_pressure(int length, float *pres_data, float *var_data); static void interpolate_pqtzuv(float*, float*, float*); +static bool is_valid_pb_data(float pb_value); static void log_merged_tqz_uv(map pqtzuv_map_tq, map pqtzuv_map_uv, map &pqtzuv_map_merged, @@ -1562,35 +1563,36 @@ void process_pbfile(int i_pb) { if (cal_cape) { if (cape_member_cnt >= 3) cape_level++; } - if (do_pbl && !is_eq(pqtzuv[0], bad_data_float)) { - // Allocated memory is deleted after all observations are processed - float *tmp_pqtzuv = new float [mxr8vt]; - - for(kk=0; kk 0) { + bool has_uv = is_valid_pb_data(pqtzuv[4]) && is_valid_pb_data(pqtzuv[5]); + bool has_tq = is_valid_pb_data(pqtzuv[2]) && + (IGNORE_Q_PBL || is_valid_pb_data(pqtzuv[1])) && + (IGNORE_Z_PBL || is_valid_pb_data(pqtzuv[3])); + if (has_tq || has_uv) { + // Allocated memory is deleted after all observations are processed + float *tmp_pqtzuv = new float [mxr8vt]; + + for(kk=0; kk r8bfms) { + if (is_bad_data(quality_code) || quality_mark > r8bfms) { obs_qty.add("NA"); } else { @@ -2833,7 +2835,7 @@ void display_bufr_variables(const StringArray &all_vars, const StringArray &all_ void copy_pqtzuv(float *to_pqtzuv, float *from_pqtzuv, bool copy_all) { int start_idx = (copy_all ? 0 : 1); for (int index = start_idx; index < mxr8vt; index++) { - if (copy_all || !is_eq(from_pqtzuv[index], bad_data_float)) + if (copy_all || !is_bad_data(from_pqtzuv[index])) to_pqtzuv[index] = from_pqtzuv[index]; } } @@ -3007,8 +3009,8 @@ float compute_pbl(map pqtzuv_map_tq, pbl_data_hgt[index] = pqtzuv[3]; pbl_data_ugrd[index] = pqtzuv[4]; pbl_data_vgrd[index] = pqtzuv[5]; - if (!is_eq(pbl_data_spfh[index], bad_data_float)) spfh_cnt++; - if (!is_eq(pbl_data_hgt[index], bad_data_float)) hgt_cnt++; + if (is_valid_pb_data(pbl_data_spfh[index])) spfh_cnt++; + if (is_valid_pb_data(pbl_data_hgt[index])) hgt_cnt++; selected_levels.add(nint(it->first)); } @@ -3028,7 +3030,7 @@ float compute_pbl(map pqtzuv_map_tq, break; } } - if (!is_eq(highest_pressure, bad_data_float)) { + if (!is_bad_data(highest_pressure)) { index = MAX_PBL_LEVEL - 1; for (; it!=pqtzuv_map_tq.end(); ++it) { int pres_level = nint(it->first); @@ -3080,7 +3082,7 @@ float compute_pbl(map pqtzuv_map_tq, //SUBROUTINE CALPBL(T,Q,P,Z,U,V,MZBL,HPBL,jpbl) calpbl_(pbl_data_temp, pbl_data_spfh, pbl_data_pres, pbl_data_hgt, pbl_data_ugrd, pbl_data_vgrd, &mzbl, &hpbl, &jpbl); - if (is_eq(hpbl, bad_data_float)) + if (!is_valid_pb_data(hpbl)) mlog << Debug(5) << method_name << " fail to compute PBL. TQ records: " << tq_count << " UV records: " << uv_count << " merged records: " << pqtzuv_map_merged.size() << "\n"; @@ -3100,8 +3102,8 @@ void insert_pbl(float *obs_arr, const float pbl_value, const int pbl_code, ConcatString hdr_info; hdr_info << unix_to_yyyymmdd_hhmmss(hdr_vld_ut) << " " << hdr_typ << " " << hdr_sid; - if (is_eq(pbl_value, bad_data_float)) { - mlog << Warning << "\nFailed to compute PBL " << hdr_info << "\n\n"; + if (is_bad_data(pbl_value)) { + mlog << Warning << "\nFailed to compute PBL " << pbl_value << " (" << hdr_info << ")\n\n"; } else if (pbl_value < hdr_elv) { mlog << Warning << "\nNot saved because the computed PBL (" << pbl_value @@ -3118,14 +3120,12 @@ void insert_pbl(float *obs_arr, const float pbl_value, const int pbl_code, << " lat: " << hdr_lat << ", lon: " << hdr_lon << ", elv: " << hdr_elv << " " << hdr_info << "\n\n"; if (obs_arr[4] > MAX_PBL) { - mlog << Warning << "\nComputed PBL (" << obs_arr[4] << " from " - << pbl_value << ") is too high, Reset to " << MAX_PBL - << " " << hdr_info<< "\n\n"; - obs_arr[4] = MAX_PBL; + mlog << Warning << "\nNot saved the computed PBL (" << obs_arr[4] << " from " + << pbl_value << ") because of the MAX PBL " << MAX_PBL + << " (" << hdr_info<< ")\n\n"; } - - addObservation(obs_arr, (string)hdr_typ, (string)hdr_sid, hdr_vld_ut, - hdr_lat, hdr_lon, hdr_elv, pbl_qm, OBS_BUFFER_SIZE); + else addObservation(obs_arr, (string)hdr_typ, (string)hdr_sid, hdr_vld_ut, + hdr_lat, hdr_lon, hdr_elv, pbl_qm, OBS_BUFFER_SIZE); } } @@ -3142,7 +3142,7 @@ int interpolate_by_pressure(int length, float *pres_data, float *var_data) { skip_missing = false; count_interpolated = 0; for (idx=0; idx pqtzuv_map_pivot, map pqtzuv_map_aux, map &pqtzuv_map_merged) { diff --git a/met/src/tools/other/point2grid/point2grid.cc b/met/src/tools/other/point2grid/point2grid.cc index 9dd321221d..7b840f08d9 100644 --- a/met/src/tools/other/point2grid/point2grid.cc +++ b/met/src/tools/other/point2grid/point2grid.cc @@ -787,8 +787,8 @@ void process_point_file(NcFile *nc_in, MetConfig &config, VarInfo *vinfo, requested_valid_time = valid_time; if (0 < valid_time) { valid_beg_ut = valid_end_ut = valid_time; - if (!is_eq(bad_data_int, conf_info.beg_ds)) valid_beg_ut += conf_info.beg_ds; - if (!is_eq(bad_data_int, conf_info.end_ds)) valid_end_ut += conf_info.end_ds; + if (!is_bad_data(conf_info.beg_ds)) valid_beg_ut += conf_info.beg_ds; + if (!is_bad_data(conf_info.end_ds)) valid_end_ut += conf_info.end_ds; for(idx=0; idx= 4) { if (from_min_value > data_value) from_min_value = data_value; @@ -1134,8 +1134,8 @@ void process_point_nccf_file(NcFile *nc_in, MetConfig &config, unixtime ref_ut = (unixtime) 0; unixtime tmp_time; if( conf_info.valid_time > 0 ) { - if (!is_eq(bad_data_int, conf_info.beg_ds)) valid_beg_ut += conf_info.beg_ds; - if (!is_eq(bad_data_int, conf_info.end_ds)) valid_end_ut += conf_info.end_ds; + if (!is_bad_data(conf_info.beg_ds)) valid_beg_ut += conf_info.beg_ds; + if (!is_bad_data(conf_info.end_ds)) valid_end_ut += conf_info.end_ds; ref_ut = get_reference_unixtime(&time_var, sec_per_unit, no_leap_year); } for (int i=0; i= to_size ) { mlog << Error << "\n" << method_name << "the mapped cell is out of range: " @@ -1978,7 +1978,7 @@ static unixtime find_valid_time(NcVar time_var) { } } - if (valid_time == bad_data_int) { + if (is_bad_data(valid_time)) { mlog << Error << "\n" << method_name << "trouble finding time variable from \"" << InputFilename << "\"\n\n"; @@ -2401,7 +2401,7 @@ void regrid_goes_variable(NcFile *nc_in, VarInfo *vinfo, for (int dIdx=0; dIdx Date: Thu, 16 Sep 2021 10:18:52 -0600 Subject: [PATCH 200/200] Add bolding the MET version 10.1.0 beta2 release notes to indicate emphasis prior to the METplus Governance meeting. --- met/docs/Users_Guide/release-notes.rst | 61 +++++++++++++++----------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/met/docs/Users_Guide/release-notes.rst b/met/docs/Users_Guide/release-notes.rst index 8404a82d8c..fc43b53c72 100644 --- a/met/docs/Users_Guide/release-notes.rst +++ b/met/docs/Users_Guide/release-notes.rst @@ -7,36 +7,47 @@ describes the bugfix, enhancement, or new feature: MET Version 10.1.0-beta2 release notes (|release_date|) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* Fix the findings from SonarQube (`#1855 `_). -* Fix gen_vx_mask so that the -input_field and -mask_field options are processed independently (`#1891 `_). -* Enhance Stat-Analysis to write the GO Index and CBS Index into a new STAT line type (`#1788 `_). -* Enhance MET to compute the CBS Index (`#1031 `_). -* Fix integer overflow in Grid-Diag (`#1886 `_). -* Fix failure of Ensemble-Stat when verifying against gridded ECMWF GRIB1 files (`#1879 `_). -* Fix consumption of too much memory by Stat-Analysis (`#1875 `_). -* Fix failure in plot_tcmpr.R script when a directory is passed in with -lookin (`#1872 `_). -* Enable TC-Pairs to only write output for a configurable list of valid times (`#1870 `_). -* Add check for the start offset and data count are valid before calling NetCDF API (`#1852 `_). -* Add new column, Scatter Index, for CNT line type (`#1843 `_). -* Enable point2grid to support double type latitude/longitude variables (`#1838 `_). -* Treat warnings from the documentation as errors to facilitate continuous integration with GHA (`#1819 `_). -* Fix the output of point2grid which is flipped and rotated with lat/lon to lat/lon conversion (`#1817 `_). -* Add ORANK line type to the HiRA output from Point-Stat (`#1764 `_). -* Make the specification of a binary threshold in Wavelet-Stat optional (`#1746 `_). -* Document the statistics from the RPS line type in Appendix C (`#1853 `_). -* Fix broken URLs in default MET config files (`#1864 `_). -* Add G and G-Beta to the DMAP line type from Grid-Stat (`#1673 `_). -* Create and publish a PDF of the MET User's Guide (`#1453 `_). -* Update documentation to reference GitHub Discussions instead of MET Help (`#1833 `_). -* Update FAQ in User's Guide with info from webpage FAQ (`#1834 `_). - + +* New output: + + * **Enhance MET to compute the CBS Index** (`#1031 `_). + * **Enhance Stat-Analysis to write the GO Index and CBS Index into a new SSIDX STAT line type** (`#1788 `_). + * **Add Scatter Index to the CNT line type** (`#1843 `_). + * **Add ORANK line type to the HiRA output from Point-Stat** (`#1764 `_). + * **Add G and G-Beta to the DMAP line type from Grid-Stat** (`#1673 `_). + +* Configuration: + + * **Make the specification of a binary threshold in Wavelet-Stat optional** (`#1746 `_). + * **Enable TC-Pairs to only write output for a configurable list of valid times** (`#1870 `_). + * Fix broken URLs in default MET config files (`#1864 `_). + +* Bugfixes: + + * **Fix the findings from SonarQube** (`#1855 `_). + * Fix integer overflow in Grid-Diag (`#1886 `_). + * Fix Gen-Vx-Mask so that the -input_field and -mask_field options are processed independently (`#1891 `_). + * Enable Point2Grid to support double type latitude/longitude variables (`#1838 `_). + * Fix the output of Point2Grid which is flipped and rotated with lat/lon to lat/lon conversion (`#1817 `_). + * Fix failure of Ensemble-Stat when verifying against gridded ECMWF GRIB1 files (`#1879 `_). + * Fix consumption of too much memory by Stat-Analysis (`#1875 `_). + * Add check for the start offset and data count are valid before calling NetCDF API (`#1852 `_). + * Fix failure in plot_tcmpr.R script when a directory is passed in with -lookin (`#1872 `_). + +* Documentation: + + * **Create and publish a PDF of the MET User's Guide** (`#1453 `_). + * Document the statistics from the RPS line type in Appendix C (`#1853 `_). + * Treat warnings from the documentation as errors to facilitate continuous integration with GHA (`#1819 `_). + * Update documentation to reference GitHub Discussions instead of MET Help (`#1833 `_). + * 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 `_). -* Change -type for gen_vx_mask from an optional argument to a required one (`#1792 `_). +* Change -type for Gen-Vx-Mask from an optional argument to a required one (`#1792 `_). * Fix python embedding when using a named grid with MET_PYTHON_EXE set (`#1798 `_). * Fix Fortify High finding for src/libcode/vx_data2d_nccf/nccf_file.cc (`#1795 `_). * Modify plot_tcmpr.R script to support plotting of extra-tropical cyclone tracks not verified against BEST tracks (`#1801 `_). @@ -148,7 +159,7 @@ MET Version 10.0.0 release notes (20210510) * **Support additional NetCDF point observation data sources** (`#1345 `_, `#1509 `_, and `#1511 `_). * Support the 2-dimensional time variable in Himawari data files (`#1580 `_). * Create empty output files for zero input observations instead of erroring out (`#1630 `_). - * Improve the point2grid runtime performance (`#1421 `_). + * Improve the Point2Grid runtime performance (`#1421 `_). * Process point observations by variable name instead of GRIB code (`#1408 `_). * GIS Tools: