diff --git a/Makefile.am b/Makefile.am index a1e75367dd..f3c2b7a83a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,7 +18,7 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = data src scripts/Rscripts scripts/python +SUBDIRS = data src scripts/Rscripts scripts/python scripts/utility if ENABLE_DEVELOPMENT SUBDIRS += internal/test_util diff --git a/Makefile.in b/Makefile.in index 3efec7b13c..e1277cbbcd 100644 --- a/Makefile.in +++ b/Makefile.in @@ -158,7 +158,7 @@ ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = data src scripts/Rscripts scripts/python \ - internal/test_util + scripts/utility internal/test_util am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in INSTALL \ compile config.guess config.sub depcomp install-sh missing \ ylwrap @@ -349,7 +349,8 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = data src scripts/Rscripts scripts/python $(am__append_1) +SUBDIRS = data src scripts/Rscripts scripts/python scripts/utility \ + $(am__append_1) MAINTAINERCLEANFILES = \ Makefile.in \ aclocal.m4 \ diff --git a/configure b/configure index 0713ecf0df..cb89948353 100755 --- a/configure +++ b/configure @@ -8848,7 +8848,7 @@ done # Create configured files -ac_config_files="$ac_config_files Makefile scripts/Rscripts/Makefile scripts/Rscripts/include/Makefile scripts/python/Makefile data/Makefile data/climo/Makefile data/climo/seeps/Makefile data/colortables/Makefile data/colortables/NCL_colortables/Makefile data/config/Makefile data/map/Makefile data/map/admin_by_country/Makefile data/poly/Makefile data/poly/HMT_masks/Makefile data/poly/NCEP_masks/Makefile data/wrappers/Makefile data/ps/Makefile data/table_files/Makefile data/tc_data/Makefile src/Makefile src/basic/Makefile src/basic/enum_to_string/Makefile src/basic/vx_cal/Makefile src/basic/vx_config/Makefile src/basic/vx_log/Makefile src/basic/vx_math/Makefile src/basic/vx_util/Makefile src/basic/vx_util_math/Makefile src/libcode/Makefile src/libcode/vx_afm/Makefile src/libcode/vx_analysis_util/Makefile src/libcode/vx_color/Makefile src/libcode/vx_data2d/Makefile src/libcode/vx_data2d_factory/Makefile src/libcode/vx_data2d_grib/Makefile src/libcode/vx_data2d_grib2/Makefile src/libcode/vx_data2d_nc_met/Makefile src/libcode/vx_data2d_nc_pinterp/Makefile src/libcode/vx_data2d_nccf/Makefile src/libcode/vx_geodesy/Makefile src/libcode/vx_gis/Makefile src/libcode/vx_gnomon/Makefile src/libcode/vx_grid/Makefile src/libcode/vx_gsl_prob/Makefile src/libcode/vx_nav/Makefile src/libcode/vx_solar/Makefile src/libcode/vx_nc_obs/Makefile src/libcode/vx_nc_util/Makefile src/libcode/vx_pb_util/Makefile src/libcode/vx_plot_util/Makefile src/libcode/vx_ps/Makefile src/libcode/vx_pxm/Makefile src/libcode/vx_render/Makefile src/libcode/vx_shapedata/Makefile src/libcode/vx_stat_out/Makefile src/libcode/vx_statistics/Makefile src/libcode/vx_time_series/Makefile src/libcode/vx_physics/Makefile src/libcode/vx_series_data/Makefile src/libcode/vx_regrid/Makefile src/libcode/vx_tc_util/Makefile src/libcode/vx_summary/Makefile src/libcode/vx_python3_utils/Makefile src/libcode/vx_data2d_python/Makefile src/libcode/vx_bool_calc/Makefile src/libcode/vx_pointdata_python/Makefile src/libcode/vx_seeps/Makefile src/tools/Makefile src/tools/core/Makefile src/tools/core/ensemble_stat/Makefile src/tools/core/grid_stat/Makefile src/tools/core/mode/Makefile src/tools/core/mode_analysis/Makefile src/tools/core/pcp_combine/Makefile src/tools/core/point_stat/Makefile src/tools/core/series_analysis/Makefile src/tools/core/stat_analysis/Makefile src/tools/core/wavelet_stat/Makefile src/tools/other/Makefile src/tools/other/ascii2nc/Makefile src/tools/other/lidar2nc/Makefile src/tools/other/gen_ens_prod/Makefile src/tools/other/gen_vx_mask/Makefile src/tools/other/gis_utils/Makefile src/tools/other/ioda2nc/Makefile src/tools/other/madis2nc/Makefile src/tools/other/mode_graphics/Makefile src/tools/other/modis_regrid/Makefile src/tools/other/pb2nc/Makefile src/tools/other/plot_data_plane/Makefile src/tools/other/plot_point_obs/Makefile src/tools/other/wwmca_tool/Makefile src/tools/other/gsi_tools/Makefile src/tools/other/regrid_data_plane/Makefile src/tools/other/point2grid/Makefile src/tools/other/shift_data_plane/Makefile src/tools/other/mode_time_domain/Makefile src/tools/other/grid_diag/Makefile src/tools/tc_utils/Makefile src/tools/tc_utils/tc_dland/Makefile src/tools/tc_utils/tc_pairs/Makefile src/tools/tc_utils/tc_stat/Makefile src/tools/tc_utils/tc_gen/Makefile src/tools/tc_utils/rmw_analysis/Makefile src/tools/tc_utils/tc_rmw/Makefile" +ac_config_files="$ac_config_files Makefile scripts/Rscripts/Makefile scripts/Rscripts/include/Makefile scripts/python/Makefile scripts/utility/Makefile data/Makefile data/climo/Makefile data/climo/seeps/Makefile data/colortables/Makefile data/colortables/NCL_colortables/Makefile data/config/Makefile data/map/Makefile data/map/admin_by_country/Makefile data/poly/Makefile data/poly/HMT_masks/Makefile data/poly/NCEP_masks/Makefile data/wrappers/Makefile data/ps/Makefile data/table_files/Makefile data/tc_data/Makefile src/Makefile src/basic/Makefile src/basic/enum_to_string/Makefile src/basic/vx_cal/Makefile src/basic/vx_config/Makefile src/basic/vx_log/Makefile src/basic/vx_math/Makefile src/basic/vx_util/Makefile src/basic/vx_util_math/Makefile src/libcode/Makefile src/libcode/vx_afm/Makefile src/libcode/vx_analysis_util/Makefile src/libcode/vx_color/Makefile src/libcode/vx_data2d/Makefile src/libcode/vx_data2d_factory/Makefile src/libcode/vx_data2d_grib/Makefile src/libcode/vx_data2d_grib2/Makefile src/libcode/vx_data2d_nc_met/Makefile src/libcode/vx_data2d_nc_pinterp/Makefile src/libcode/vx_data2d_nccf/Makefile src/libcode/vx_geodesy/Makefile src/libcode/vx_gis/Makefile src/libcode/vx_gnomon/Makefile src/libcode/vx_grid/Makefile src/libcode/vx_gsl_prob/Makefile src/libcode/vx_nav/Makefile src/libcode/vx_solar/Makefile src/libcode/vx_nc_obs/Makefile src/libcode/vx_nc_util/Makefile src/libcode/vx_pb_util/Makefile src/libcode/vx_plot_util/Makefile src/libcode/vx_ps/Makefile src/libcode/vx_pxm/Makefile src/libcode/vx_render/Makefile src/libcode/vx_shapedata/Makefile src/libcode/vx_stat_out/Makefile src/libcode/vx_statistics/Makefile src/libcode/vx_time_series/Makefile src/libcode/vx_physics/Makefile src/libcode/vx_series_data/Makefile src/libcode/vx_regrid/Makefile src/libcode/vx_tc_util/Makefile src/libcode/vx_summary/Makefile src/libcode/vx_python3_utils/Makefile src/libcode/vx_data2d_python/Makefile src/libcode/vx_bool_calc/Makefile src/libcode/vx_pointdata_python/Makefile src/libcode/vx_seeps/Makefile src/tools/Makefile src/tools/core/Makefile src/tools/core/ensemble_stat/Makefile src/tools/core/grid_stat/Makefile src/tools/core/mode/Makefile src/tools/core/mode_analysis/Makefile src/tools/core/pcp_combine/Makefile src/tools/core/point_stat/Makefile src/tools/core/series_analysis/Makefile src/tools/core/stat_analysis/Makefile src/tools/core/wavelet_stat/Makefile src/tools/other/Makefile src/tools/other/ascii2nc/Makefile src/tools/other/lidar2nc/Makefile src/tools/other/gen_ens_prod/Makefile src/tools/other/gen_vx_mask/Makefile src/tools/other/gis_utils/Makefile src/tools/other/ioda2nc/Makefile src/tools/other/madis2nc/Makefile src/tools/other/mode_graphics/Makefile src/tools/other/modis_regrid/Makefile src/tools/other/pb2nc/Makefile src/tools/other/plot_data_plane/Makefile src/tools/other/plot_point_obs/Makefile src/tools/other/wwmca_tool/Makefile src/tools/other/gsi_tools/Makefile src/tools/other/regrid_data_plane/Makefile src/tools/other/point2grid/Makefile src/tools/other/shift_data_plane/Makefile src/tools/other/mode_time_domain/Makefile src/tools/other/grid_diag/Makefile src/tools/tc_utils/Makefile src/tools/tc_utils/tc_dland/Makefile src/tools/tc_utils/tc_pairs/Makefile src/tools/tc_utils/tc_stat/Makefile src/tools/tc_utils/tc_gen/Makefile src/tools/tc_utils/rmw_analysis/Makefile src/tools/tc_utils/tc_rmw/Makefile" if test -n "$MET_DEVELOPMENT"; then @@ -9736,6 +9736,7 @@ do "scripts/Rscripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Rscripts/Makefile" ;; "scripts/Rscripts/include/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Rscripts/include/Makefile" ;; "scripts/python/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/python/Makefile" ;; + "scripts/utility/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/utility/Makefile" ;; "data/Makefile") CONFIG_FILES="$CONFIG_FILES data/Makefile" ;; "data/climo/Makefile") CONFIG_FILES="$CONFIG_FILES data/climo/Makefile" ;; "data/climo/seeps/Makefile") CONFIG_FILES="$CONFIG_FILES data/climo/seeps/Makefile" ;; diff --git a/configure.ac b/configure.ac index 5414db8913..efd3aaf7bc 100644 --- a/configure.ac +++ b/configure.ac @@ -1183,6 +1183,7 @@ AC_CONFIG_FILES([Makefile scripts/Rscripts/Makefile scripts/Rscripts/include/Makefile scripts/python/Makefile + scripts/utility/Makefile data/Makefile data/climo/Makefile data/climo/seeps/Makefile diff --git a/docs/Users_Guide/reformat_point.rst b/docs/Users_Guide/reformat_point.rst index d1b0cabd6e..b7670bc393 100644 --- a/docs/Users_Guide/reformat_point.rst +++ b/docs/Users_Guide/reformat_point.rst @@ -1171,4 +1171,19 @@ The configuration option listed above is common to many MET tools and are descri This entry is an array of dictionaries, each containing a **GRIB code** string and mathcing **variable name** string which define a mapping of GRIB code to the output variable names. +Point NetCDF to ASCII Python Utility +==================================== +As a tool for debugging, a utility script called print_pointnc2ascii.py is included for users. This script reads the MET point NetCDF file format and returns an ASCII representation to the screen, with either space or comma delimiting. Optionally, the user can request that the output be written to a file. + +The script can be found at: + +.. code-block:: none + + MET_BASE/shared/met/utility/print_pointnc2ascii.py + +For how to use the script, issue the command: + +.. code-block:: none + + python3 MET_BASE/shared/met/utility/print_pointnc2ascii.py -h diff --git a/scripts/Rscripts/Makefile.am b/scripts/Rscripts/Makefile.am index 63b994a755..c76c511d9c 100644 --- a/scripts/Rscripts/Makefile.am +++ b/scripts/Rscripts/Makefile.am @@ -39,7 +39,6 @@ rscripts_DATA = \ plot_ensemble.R \ plot_probri.R \ plot_tcmpr.R \ - pntnc2ascii.R \ trmm2nc.R \ trmmbin2nc.R diff --git a/scripts/Rscripts/Makefile.in b/scripts/Rscripts/Makefile.in index 2ecc562b96..cb53537961 100644 --- a/scripts/Rscripts/Makefile.in +++ b/scripts/Rscripts/Makefile.in @@ -365,7 +365,6 @@ rscripts_DATA = \ plot_ensemble.R \ plot_probri.R \ plot_tcmpr.R \ - pntnc2ascii.R \ trmm2nc.R \ trmmbin2nc.R diff --git a/scripts/Rscripts/pntnc2ascii.R b/scripts/Rscripts/pntnc2ascii.R deleted file mode 100644 index 6a9940f1fe..0000000000 --- a/scripts/Rscripts/pntnc2ascii.R +++ /dev/null @@ -1,176 +0,0 @@ -library(ncdf4); - -usage = function(){ - cat("\nUsage: pntnc2ascii\n", - " [-sid name]\n", - " [-msg_type name]\n", - " [-obs_var name]\n", - " nc_file\n\n", - " where \"-sid name\" prints only observations for that station id (optional).\n", - " \"-msg_typ name\" prints only observations for that message type (optional).\n", - " \"-obs_var name\" prints only observations for that observation variable or GRIB code (optional).\n", - " \"nc_file\" is the netCDF point observation file (required).\n\n", - sep=""); -} - -# parse and verify command line arguments -strSid = ""; strMsg = ""; strObs = ""; -listArgs = commandArgs(TRUE); -if( 1 > length(listArgs) ){ usage(); q(); } -if( 1 < length(listArgs) ){ - for( i in seq(1, length(listArgs) - 1, by=2) ){ - if ( "-sid" == listArgs[i] ){ - strSid = listArgs[i+1]; - } else if( "-msg_typ" == listArgs[i] || "-msg_type" == listArgs[i] ){ - strMsg = listArgs[i+1]; - } else if( "-obs_var" == listArgs[i] ){ - strObs = listArgs[i+1]; - } else { - cat("ERROR: unrecognized input argument '", listArgs[i], "'\n", sep=""); - usage(); q(status=1); - } - } - #cat(" INFO: strSid: [", strSid, "]", " strSid: [", strMsg, "]", " strObs: [", strObs, "]\n", sep=""); -} - - -# open the input NetCDF file -strPntNc = listArgs[ length(listArgs) ]; -ncPnt = nc_open(c(strPntNc), write=F); - -# build the header data frame -use_index = F; -if( 0 < length(ncPnt$var[["hdr_lat"]]) ) { - use_index = T; - dfHdr = data.frame( - typ = ncvar_get(ncPnt, ncPnt$var[["hdr_typ"]]), - sid = ncvar_get(ncPnt, ncPnt$var[["hdr_sid"]]), - vld = ncvar_get(ncPnt, ncPnt$var[["hdr_vld"]]), - lat = ncvar_get(ncPnt, ncPnt$var[["hdr_lat"]]), - lon = ncvar_get(ncPnt, ncPnt$var[["hdr_lon"]]), - elv = ncvar_get(ncPnt, ncPnt$var[["hdr_elv"]]) - ); - if( strSid != "" ) { - sid_list = ncvar_get(ncPnt, ncPnt$var[["hdr_sid_table"]]); - if( 0 < length(sid_list)){ - strSid = which(sid_list == strSid); - if (strSid > 0) strSid = strSid - 1; - } - }; - if( strMsg != "") { - msg_list = ncvar_get(ncPnt, ncPnt$var[["hdr_typ_table"]]); - if (0 < length(msg_list)){ - strMsg = which(msg_list == strMsg); - if (strMsg > 0) strMsg = strMsg - 1; - } - }; -} else { - dfHdr = data.frame( - typ = ncvar_get(ncPnt, ncPnt$var[["hdr_typ"]]), - sid = ncvar_get(ncPnt, ncPnt$var[["hdr_sid"]]), - vld = ncvar_get(ncPnt, ncPnt$var[["hdr_vld"]]), - lat = ncvar_get(ncPnt, ncPnt$var[["hdr_arr"]])[1,], - lon = ncvar_get(ncPnt, ncPnt$var[["hdr_arr"]])[2,], - elv = ncvar_get(ncPnt, ncPnt$var[["hdr_arr"]])[3,] - ); -} -dfHdr$hdr_id = seq(0,nrow(dfHdr)-1); - -# replace empty SID strings with NA -if( ! use_index ) { - dfHdr$sid[dfHdr$sid == ""] = NA; -} - -# check for the obs_qty variable -if( 0 < length(ncPnt$var[["obs_qty"]]) ) { - ObsQty = ncvar_get(ncPnt, ncPnt$var[["obs_qty"]]); - if( 0 < length(ncPnt$var[["obs_qty_table"]]) ) { - ObsQtyList = ncvar_get(ncPnt, ncPnt$var[["obs_qty_table"]]); - ObsQty = ObsQtyList[ObsQty+1]; - } -} else { - ObsQty = rep(-9999, ncPnt$dim[["nobs"]]$len); -} - -# build the observation data frame -if( 0 < length(ncPnt$var[["obs_val"]]) ) { - if( 0 < length(ncPnt$var[["obs_vid"]]) ) { - vid_or_gc = ncvar_get(ncPnt, ncPnt$var[["obs_vid"]]) - } else { - vid_or_gc = ncvar_get(ncPnt, ncPnt$var[["obs_gc"]]) - } - dfObs = data.frame( - hdr_id = ncvar_get(ncPnt, ncPnt$var[["obs_hid"]]), - var = vid_or_gc, - lvl = ncvar_get(ncPnt, ncPnt$var[["obs_lvl"]]), - hgt = ncvar_get(ncPnt, ncPnt$var[["obs_hgt"]]), - qty = ObsQty, - ob = signif(ncvar_get(ncPnt, ncPnt$var[["obs_val"]]), 5) - ); -} else { - dfObs = data.frame( - hdr_id = ncvar_get(ncPnt, ncPnt$var[["obs_arr"]])[1,], - var = ncvar_get(ncPnt, ncPnt$var[["obs_arr"]])[2,], - lvl = ncvar_get(ncPnt, ncPnt$var[["obs_arr"]])[3,], - hgt = ncvar_get(ncPnt, ncPnt$var[["obs_arr"]])[4,], - qty = ObsQty, - ob = signif(ncvar_get(ncPnt, ncPnt$var[["obs_arr"]])[5,], 5) - ); -} - -# check for the obs_var variable and update dfObs$var -if( 0 < length(ncPnt$var[["obs_var"]]) ) { - ObsVar = ncvar_get(ncPnt, ncPnt$var[["obs_var"]]); - dfObs$var = ObsVar[dfObs$var+1]; -} - -# apply the filtering criteria and merge the headers and obs -if( strSid != "" ){ dfHdr = dfHdr[dfHdr$sid == strSid,]; } -if( strMsg != "" ){ dfHdr = dfHdr[dfHdr$typ == strMsg,]; } -if( strObs != "" ){ dfObs = dfObs[dfObs$var == strObs,]; } - -if( use_index ) { - if( 0 < length(ncPnt$var[["hdr_typ_table"]]) ) { - HdrTypList = ncvar_get(ncPnt, ncPnt$var[["hdr_typ_table"]]); - dfHdr$typ = HdrTypList[dfHdr$typ+1]; - } - if( 0 < length(ncPnt$var[["hdr_sid_table"]]) ) { - HdrSidList = ncvar_get(ncPnt, ncPnt$var[["hdr_sid_table"]]); - dfHdr$sid = HdrSidList[dfHdr$sid+1]; - } - if( 0 < length(ncPnt$var[["hdr_vld_table"]]) ) { - HdrVldList = ncvar_get(ncPnt, ncPnt$var[["hdr_vld_table"]]); - dfHdr$vld = HdrVldList[dfHdr$vld+1]; - } -} - -dfSid = merge(dfHdr, dfObs); - -# format level column to HHMMSS for accumulation intervals -ind_accum = ( dfSid$var == 61 | dfSid$var == "APCP" | - dfSid$var == 62 | dfSid$var == "NCPCP" | - dfSid$var == 63 | dfSid$var == "ACPCP" ) & ( dfSid$lvl != -9999 ); -dfSid$lvl[ind_accum] = format(.POSIXct(dfSid$lvl[ind_accum], tz="GMT"), "%H%M%S"); - -# print the formatted observations -options(scipen=20, digits=6); -apply(dfSid[,2:12], 1, function(d){ cat(d,"\n") }) - -# better formatting, but very slow... -#for(i in 1:nrow(dfSid)){ -# cat( sprintf("%-8s%-8s%-15s%11.5f%11.5f%6d%5d%10.2f%14.5f%12.5f\n", -# dfSid[i,]$typ, -# dfSid[i,]$sid, -# dfSid[i,]$vld, -# dfSid[i,]$lat, -# dfSid[i,]$lon, -# dfSid[i,]$elv, -# dfSid[i,]$gc, -# dfSid[i,]$lvl, -# dfSid[i,]$hgt, -# dfSid[i,]$ob -# ), sep=""); -#} - -# close the input NetCDF file -nc_close(ncPnt); diff --git a/scripts/utility/Makefile.am b/scripts/utility/Makefile.am new file mode 100644 index 0000000000..6e22a33e2b --- /dev/null +++ b/scripts/utility/Makefile.am @@ -0,0 +1,33 @@ +## Makefile.am -- Process this file with automake to produce Makefile.in +## Copyright (C) 2000, 2006 Gary V. Vaughan +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2, or (at your option) +## any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +## MA 02110-1301, USA. + +# SUBDIRS = include + + +## Example of how to Install outside of $(pkgdatadir) +## scriptsrootdir = $(prefix)/share/scripts +## pythonutilitydir = ${scriptsrootdir}/utility + +pythonutilitydir = $(pkgdatadir)/utility + +pythonutility_DATA = \ + print_pointnc2ascii.py + +EXTRA_DIST = ${pythonutility_DATA} + +MAINTAINERCLEANFILES = Makefile.in diff --git a/scripts/utility/Makefile.in b/scripts/utility/Makefile.in new file mode 100644 index 0000000000..c8a3703b34 --- /dev/null +++ b/scripts/utility/Makefile.in @@ -0,0 +1,520 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# SUBDIRS = include + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = scripts/utility +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pythonutilitydir)" +DATA = $(pythonutility_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUFRLIB_NAME = @BUFRLIB_NAME@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FC_LIBS = @FC_LIBS@ +FFLAGS = @FFLAGS@ +FLIBS = @FLIBS@ +GREP = @GREP@ +GRIB2CLIB_NAME = @GRIB2CLIB_NAME@ +GRIB2_LIBS = @GRIB2_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MET_BUFR = @MET_BUFR@ +MET_BUFRLIB = @MET_BUFRLIB@ +MET_CAIRO = @MET_CAIRO@ +MET_CAIROINC = @MET_CAIROINC@ +MET_CAIROLIB = @MET_CAIROLIB@ +MET_FREETYPE = @MET_FREETYPE@ +MET_FREETYPEINC = @MET_FREETYPEINC@ +MET_FREETYPELIB = @MET_FREETYPELIB@ +MET_GRIB2C = @MET_GRIB2C@ +MET_GRIB2CINC = @MET_GRIB2CINC@ +MET_GRIB2CLIB = @MET_GRIB2CLIB@ +MET_GSL = @MET_GSL@ +MET_GSLINC = @MET_GSLINC@ +MET_GSLLIB = @MET_GSLLIB@ +MET_HDF = @MET_HDF@ +MET_HDF5 = @MET_HDF5@ +MET_HDF5INC = @MET_HDF5INC@ +MET_HDF5LIB = @MET_HDF5LIB@ +MET_HDFEOS = @MET_HDFEOS@ +MET_HDFEOSINC = @MET_HDFEOSINC@ +MET_HDFEOSLIB = @MET_HDFEOSLIB@ +MET_HDFINC = @MET_HDFINC@ +MET_HDFLIB = @MET_HDFLIB@ +MET_NETCDF = @MET_NETCDF@ +MET_NETCDFINC = @MET_NETCDFINC@ +MET_NETCDFLIB = @MET_NETCDFLIB@ +MET_PYTHON_CC = @MET_PYTHON_CC@ +MET_PYTHON_LD = @MET_PYTHON_LD@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +OPENMP_CFLAGS = @OPENMP_CFLAGS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PYTHON_LIBS = @PYTHON_LIBS@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +pythonutilitydir = $(pkgdatadir)/utility +pythonutility_DATA = \ + print_pointnc2ascii.py + +EXTRA_DIST = ${pythonutility_DATA} +MAINTAINERCLEANFILES = Makefile.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign scripts/utility/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign scripts/utility/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-pythonutilityDATA: $(pythonutility_DATA) + @$(NORMAL_INSTALL) + @list='$(pythonutility_DATA)'; test -n "$(pythonutilitydir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pythonutilitydir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pythonutilitydir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pythonutilitydir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pythonutilitydir)" || exit $$?; \ + done + +uninstall-pythonutilityDATA: + @$(NORMAL_UNINSTALL) + @list='$(pythonutility_DATA)'; test -n "$(pythonutilitydir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pythonutilitydir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(pythonutilitydir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pythonutilityDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pythonutilityDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic cscopelist-am \ + ctags-am distclean distclean-generic distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-pythonutilityDATA \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-pythonutilityDATA + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/scripts/utility/print_pointnc2ascii.py b/scripts/utility/print_pointnc2ascii.py new file mode 100755 index 0000000000..e637eb3361 --- /dev/null +++ b/scripts/utility/print_pointnc2ascii.py @@ -0,0 +1,305 @@ +#!/usr/bin/env python3 + +''' +Created on Oct 14, 2022 + +@author: hsoh + +The script reads the point observation NetCDF which is generated by MET tools and prints out the text. +The header which begins with "#" can be added with "--add-header" option. + +''' + +from os import path +from optparse import OptionParser + +import numpy as np +from netCDF4 import Dataset + +def usage(): + print(f'Usage: python3 print_nc2ascii.py MET_point_obs_nc <--hide-header> <--use-comma> <--out=out_filename>') + print(f' MET_point_obs_nc: NetCDF filename to read (required)') + print(f' --add-header: to add the header (optional, default: not included)') + print(f' --use-comma: use the "comma" as separator for comma separated output (optional, default: use spaces)"') + print(f' --out=out_filename: save the text into the file (optional, default: display to the screen)"') + print(f' Note: <> indicates optional arguments') + +def create_parser_options(parser): + parser.add_option("--add-header", "--add_header", dest="add_header", + action="store_true", default=False, help=" Add header (default: not include header)") + parser.add_option("--use-comma", "--use_comma", dest="use_comma", + action="store_true", default=False, help=" Use comma as separator (default: False)") + parser.add_option("-o", "--out", dest="out_file", + default=None, help=" Save the text into the file (default: False)") + return parser.parse_args() + + +class nc_tools(): + + @staticmethod + def get_num_array(nc_group, var_name): + nc_var = nc_group.variables.get(var_name, None) + return [] if nc_var is None else nc_var[:] + + @staticmethod + def get_ncbyte_array_to_str(nc_var): + nc_str_data = nc_var[:] + if nc_var.datatype.name == 'bytes8': + nc_str_data = [ str(s.compressed(),"utf-8") for s in nc_var[:] ] + return nc_str_data + + @staticmethod + def get_string_array(nc_group, var_name): + nc_var = nc_group.variables.get(var_name, None) + return [] if nc_var is None else nc_tools.get_ncbyte_array_to_str(nc_var) + + +class met_nc_point_obs(): + + #EPSILON = 0.00001 + EPSILON_L = 0.000000001 + EPSILON_U = 0.000000009 + + EPSILON2_L = 0.0025 + EPSILON2_U = 0.9996 + + def dump(self, out_handler, show_header=True, use_comma=False): + hdr_typ = self.hdr_zero if 0 == self.nhdr_typ else self.hdr_typ + hdr_sid = self.hdr_zero if 0 == self.nhdr_sid else self.hdr_sid + hdr_lat, hdr_lat_len = self.formated_num_array(self.hdr_lat, use_comma) + hdr_lon, hdr_lon_len = self.formated_num_array(self.hdr_lon, use_comma) + hdr_elv, hdr_elv_len = self.formated_num_array(self.hdr_elv, use_comma) + headers = [list(i) for i in zip(hdr_typ, hdr_sid, self.hdr_vld, hdr_lat, hdr_lon, hdr_elv)] + + obs_lvl, obs_lvl_len = self.formated_num_array(self.obs_lvl, use_comma) + obs_hgt, obs_hgt_len = self.formated_num_array(self.obs_hgt, use_comma) + if use_comma: + obs_qty = [ '"NA"' if np.ma.is_masked(i) else f'"{self.obs_qty_table[i]}"' for i in self.obs_qty ] + obs_vid = [ f'"{self.obs_var_table[i]}"' if self.use_var_id else f'"{i}"' for i in self.obs_vid ] + else: + obs_qty = [ 'NA' if np.ma.is_masked(i) else f'{self.obs_qty_table[i]}' for i in self.obs_qty ] + obs_vid = [ f'{self.obs_var_table[i]}' if self.use_var_id else f'{i:3}' for i in self.obs_vid ] + + if self.is_all_int(self.obs_val): + obs_val = [ f'{i:.0f}' for i in self.obs_val ] + else: + obs_precision = self.get_precision(self.obs_val) + obs_val = [ f'{i:.1f}' if abs((i*10)-int(i*10)) < 0.000001 else + f'{i:.1f}' if abs((i*10)-int(i*10)) > 0.999998 else + f'{i:.2f}' if abs((i*100)-int(i*100)) < 0.000001 else + f'{i:.2f}' if abs((i*100)-int(i*100)) > 0.999998 else + f'{i:.3f}' if abs((i*1000)-int(i*1000)) < 0.000001 else + f'{i:.3f}' if abs((i*1000)-int(i*1000)) > 0.999998 else + f'{i:.{obs_precision}f}' for i in self.obs_val ] + + for i in range(0, len(obs_val)): + v = obs_val[i] + v1 = v.split('.') + if len(v1) > 1: + pad_len = obs_precision - len(v1[-1]) + obs_val[i] = self.pad(v, pad_len) + + hdr_typ_len = self.get_max_string_length(self.hdr_typ_table) + hdr_sid_len = self.get_max_string_length(self.hdr_sid_table) + obs_val_len = self.get_max_string_length(obs_val) + obs_qty_len = self.get_max_string_length(self.obs_qty_table) + var_name_len = self.get_max_string_length(self.obs_var_table) + + if show_header: + if use_comma: + self.out_data(out_handler, f'#msg_type,station_id,valid_time,lat,lon,elv,var_name/gc,level,height,qty,value') + else: + self.out_data(out_handler, f'#msg_type s_id valid_time lat lon elv var_name/gc level height qty value') + + for obs_data in [list(i) for i in zip(obs_vid, obs_lvl, obs_hgt, obs_qty, obs_val, self.obs_hid)]: + header_arr = headers[obs_data[-1]] + if use_comma: + self.out_data(out_handler, + f'"{self.hdr_typ_table[header_arr[0]]}",' + f'"{self.hdr_sid_table[header_arr[1]]}",' + f'"{self.hdr_vld_table[header_arr[2]]}",' + f'{header_arr[3]},{header_arr[4]},{header_arr[5]},' + f'{obs_data[0]},{obs_data[1]},{obs_data[2]},{obs_data[3]},{obs_data[4]}') + else: + self.out_data(out_handler, + f'{self.hdr_typ_table[header_arr[0]]:<{hdr_typ_len}s} ' + f'{self.hdr_sid_table[header_arr[1]]:<{hdr_sid_len}s} ' + f'{self.hdr_vld_table[header_arr[2]]} ' + f'{header_arr[3]:>{hdr_lat_len}s} {header_arr[4]:>{hdr_lon_len}s} {header_arr[5]:>{hdr_elv_len}s} ' + f'{obs_data[0]:<{var_name_len}s} {obs_data[1]:>{obs_lvl_len}s} ' + f'{obs_data[2]:>{obs_hgt_len}s} {obs_data[3]:>{obs_qty_len}s} {obs_data[4]:>{obs_val_len}s}') + + def formated_num_array(self, value_array, use_comma): + if self.is_all_int(value_array): + str_array = [ f'{i:.0f}' for i in value_array ] + else: + na_str = '"NA"' if use_comma else 'NA' + format_digits = 2 if self.is_2_digit_precision(value_array) else 4 + str_array = [ na_str if np.ma.is_masked(i) else f'{i:.{format_digits}f}' for i in value_array ] + max_len = self.get_max_string_length(str_array) + return str_array, max_len + + def get_dim_size(self, nc_group, dim_name): + nc_dim = nc_group.dimensions.get(dim_name, None) + return 0 if nc_dim is None else nc_dim.size + + def get_max_string_length(self, str_list): + str_len = 0; + for str_value in str_list: + if len(str_value) > str_len: + str_len = len(str_value) + return str_len + + def get_nc_var_string_data(self, nc_group, var_name): + nc_var = nc_group.variables.get(var_name, None) + return ['NA'] if nc_var is None else nc_tools.get_string_array(nc_group, var_name) + + def get_precision(self, data_list): + precision = 0 + for v in data_list: + if abs((v*10)-int(v*10)) < 0.000001 or abs((v*10)-int(v*10)) > 0.999998: + if precision < 1: + precision = 1 + elif abs((v*100)-int(v*100)) < 0.000001 or abs((v*100)-int(v*100)) > 0.999998: + if precision < 2: + precision = 2 + elif abs((v*1000)-int(v*1000)) < 0.000001 or abs((v*1000)-int(v*1000)) > 0.999998: + if precision < 3: + precision = 3 + elif abs(v*100000000-int(v*100000000)) > 0.: + precision = 8 + break + elif abs(v*10000000-int(v*10000000)) > 0.: + if precision < 7: + precision = 7 + elif abs(v*1000000-int(v*1000000)) > 0.: + if precision < 6: + precision = 6 + elif abs(v*100000-int(v*100000)) > 0.: + if precision < 5: + precision = 5 + elif abs(v*10000-int(v*10000)) > 0.: + if precision < 4: + precision = 4 + elif abs(v*1000-int(v*1000)) > 0.: + if precision < 3: + precision = 3 + elif abs(v*100-int(v*100)) > 0.: + if precision < 2: + precision = 2 + return precision + + def is_2_digit_precision(self, value_array): + result = True + for a_value in value_array: + if np.ma.is_masked(a_value): + continue + if self.EPSILON2_L < abs(a_value*100-int(a_value*100)) < self.EPSILON2_U: + if abs(a_value*10-int(a_value*10)) < self.EPSILON2_U: # to filter x.x9996 + result = False + break + return result + + def is_all_int(self, value_array): + all_int = True + for a_value in value_array: + if np.ma.is_masked(a_value) or not self.is_integer(a_value): + all_int = False + break + return all_int + + def is_integer(self, value): + return (abs(value - int(value)) < self.EPSILON_L) or (abs(value - int(value)) < self.EPSILON_U) + + def out_data(self, out_filehandler, line_buf): + if out_filehandler is not None: + out_filehandler.write(line_buf) + out_filehandler.write('\n') + else: + print(line_buf) + + def pad(self, v, pad_len): + if pad_len == 1: + v = f'{v}0' + elif pad_len == 2: + v = f'{v}00' + elif pad_len == 3: + v = f'{v}000' + elif pad_len == 4: + v = f'{v}0000' + elif pad_len == 5: + v = f'{v}00000' + elif pad_len == 6: + v = f'{v}000000' + elif pad_len == 7: + v = f'{v}0000000' + return v + + def read_data(self, met_nc_name): + nc_group = Dataset(met_nc_name, "r") + self.use_var_id = False + if 'use_var_id' in nc_group.ncattrs(): + self.use_var_id = nc_group.use_var_id.lower() == "true" + + self.nhdr = self.get_dim_size(nc_group, 'nhdr') + self.hdr_zero = [ 0 for _ in range(0, self.nhdr)] + self.nhdr_typ = self.get_dim_size(nc_group, 'nhdr_typ') # type table + self.nhdr_sid = self.get_dim_size(nc_group, 'nhdr_sid') # station_id table + self.nhdr_vld = self.get_dim_size(nc_group, 'nhdr_vld') # valid time strings + + self.hdr_typ = nc_tools.get_num_array(nc_group, 'hdr_typ') # (nhdr) integer + self.hdr_sid = nc_tools.get_num_array(nc_group, 'hdr_sid') # (nhdr) integer + self.hdr_vld = nc_tools.get_num_array(nc_group, 'hdr_vld') # (nhdr) integer + self.hdr_lat = nc_tools.get_num_array(nc_group, 'hdr_lat') # (nhdr) float + self.hdr_lon = nc_tools.get_num_array(nc_group, 'hdr_lon') # (nhdr) float + self.hdr_elv = nc_tools.get_num_array(nc_group, 'hdr_elv') # (nhdr) float + self.hdr_typ_table = self.get_nc_var_string_data(nc_group, 'hdr_typ_table') # (nhdr_typ, mxstr2) string + self.hdr_sid_table = self.get_nc_var_string_data(nc_group, 'hdr_sid_table') # (nhdr_sid, mxstr2) string + self.hdr_vld_table = self.get_nc_var_string_data(nc_group, 'hdr_vld_table') # (nhdr_vld, mxstr) string + + #Observation data + self.nobs = self.get_dim_size(nc_group, 'nobs') + self.nobs_qty = self.get_dim_size(nc_group, 'nobs_qty') + self.nobs_var = self.get_dim_size(nc_group, 'nobs_var') + + self.obs_qty = nc_tools.get_num_array(nc_group, 'obs_qty') # (nobs_qty) integer, index of self.obs_qty_table + self.obs_hid = nc_tools.get_num_array(nc_group, 'obs_hid') # (nobs) integer + self.obs_vid = nc_tools.get_num_array(nc_group, 'obs_vid') # (nobs) integer, veriable index from self.obs_var_table or GRIB code + if 0 == len(self.obs_vid): + self.obs_vid = nc_tools.get_num_array(nc_group, 'obs_gc' ) # (nobs) integer, veriable index from self.obs_var_table or GRIB code + self.obs_lvl = nc_tools.get_num_array(nc_group, 'obs_lvl') # (nobs) float + self.obs_hgt = nc_tools.get_num_array(nc_group, 'obs_hgt') # (nobs) float + self.obs_val = nc_tools.get_num_array(nc_group, 'obs_val') # (nobs) float + self.obs_qty_table = self.get_nc_var_string_data(nc_group, 'obs_qty_table') # (nobs_qty, mxstr) string + self.obs_var_table = self.get_nc_var_string_data(nc_group, 'obs_var') # (nobs_var, mxstr2) string, required if self.use_var_id is True + + +if __name__ == '__main__': + usage_str = "%prog [options]" + parser = OptionParser(usage = usage_str) + options, args = create_parser_options(parser) + + if 0 == len(args): + print(' == INFO == Missing input NetCDF filename') + usage() + else: + if options.out_file is not None: + out_handler = open(options.out_file, 'w') + else: + out_handler = None + met_nc_data = met_nc_point_obs() + for nc_name in args: + if not path.exists(nc_name): + if nc_name.startswith('#'): + print(f' == INFO == ignore "{nc_name}" option') + else: + print(f' == INFO == The input file {nc_name} does not exist') + continue + + met_nc_data.read_data(nc_name) + met_nc_data.dump(out_handler, options.add_header, options.use_comma) + print() + + if out_handler is not None: + out_handler.close() + print(f'Saved to {options.out_file}')