From c722bdc075dcc3ea328de424ff2a962d412ac945 Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Wed, 24 Apr 2024 09:27:19 -0600 Subject: [PATCH 01/12] Per #2781, added function to convert MET NetCDF point observation data to pandas so it can be read and modified in a python embedding script. Added example python embedding script --- .../python/examples/pyembed_met_point_nc.py | 43 +++++++++++++++++++ scripts/python/met/point_nc.py | 18 ++++++++ 2 files changed, 61 insertions(+) create mode 100644 scripts/python/examples/pyembed_met_point_nc.py diff --git a/scripts/python/examples/pyembed_met_point_nc.py b/scripts/python/examples/pyembed_met_point_nc.py new file mode 100644 index 0000000000..f1a97abab7 --- /dev/null +++ b/scripts/python/examples/pyembed_met_point_nc.py @@ -0,0 +1,43 @@ +import os +import sys + +from met.point_nc import nc_point_obs + +print(f"Python Script:\t{sys.argv[0]}") + +arg_cnt = len(sys.argv) +if len(sys.argv) != 2: + print("ERROR: read_met_point.py -> Specify only 1 input file") + sys.exit(1) + +# Read the input file as the first argument +input_file = os.path.expandvars(sys.argv[1]) +try: + print("Input File:\t" + repr(input_file)) + + # Read and format the input 11-column observations: + # (1) string: Message_Type + # (2) string: Station_ID + # (3) string: Valid_Time(YYYYMMDD_HHMMSS) + # (4) numeric: Lat(Deg North) + # (5) numeric: Lon(Deg East) + # (6) numeric: Elevation(msl) + # (7) string: Var_Name(or GRIB_Code) + # (8) numeric: Level + # (9) numeric: Height(msl or agl) + # (10) string: QC_String + # (11) numeric: Observation_Value + + # Read 11 column text input data by using pandas package + point_obs = nc_point_obs() + if not point_obs.read_data(input_file): + print(f"ERROR: Could not read MET point data file {input_file}") + sys.exit(1) + + df = point_obs.to_pandas() + point_data = df.values.tolist() + print(f" point_data: Data Length:\t{len(point_data)}") + print(f" point_data: Data Type:\t{type(point_data)}") +except FileNotFoundError: + print(f"The input file {input_file} does not exist") + sys.exit(1) diff --git a/scripts/python/met/point_nc.py b/scripts/python/met/point_nc.py index 37063bdb0d..9e720947b8 100644 --- a/scripts/python/met/point_nc.py +++ b/scripts/python/met/point_nc.py @@ -8,10 +8,12 @@ ''' +import sys import os import numpy as np import netCDF4 as nc +import pandas as pd from met.point import met_point_obs, met_point_tools @@ -274,6 +276,22 @@ def write_nc_data(nc_dataset, point_obs): print(f' === ERROR at {method_name} type(nc_dataset)={type(nc_dataset)} type(point_obs)={type(point_obs)}') raise + def to_pandas(self): + return pd.DataFrame({ + 'typ': [self.hdr_typ_table[i] for i in self.hdr_typ], + 'sid': [self.hdr_sid_table[i] for i in self.hdr_sid], + 'vld': [self.hdr_vld_table[i] for i in self.hdr_vld], + 'lat': self.hdr_lat, + 'lon': self.hdr_lon, + 'elv': self.hdr_elv, + 'var': [self.obs_var_table[i] if self.use_var_id else f'{i}' + for i in self.obs_vid], + 'lvl': self.obs_lvl, + 'hgt': self.obs_hgt, + 'qc': [np.nan if np.ma.is_masked(i) else self.obs_qty_table[i] + for i in self.obs_qty], + 'obs': self.obs_val, + }) def main(argv): if len(argv) != 1 and argv[1] != ARG_PRINT_DATA: From 6ed91b3e5cc60125b17b36079eba2cabd8f979d0 Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Wed, 24 Apr 2024 09:27:33 -0600 Subject: [PATCH 02/12] ignore python cache files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index d26e2e4a32..bbd21255b1 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,5 @@ make.log make_install.log .idea cmake-build-debug + +__pycache__ \ No newline at end of file From f6cf1c0c52c2444f0ccbebae835e8b9b30001d33 Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Wed, 24 Apr 2024 09:28:02 -0600 Subject: [PATCH 03/12] fixed function call --- scripts/python/met/point.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/python/met/point.py b/scripts/python/met/point.py index eb85c3711d..05e3054ba3 100644 --- a/scripts/python/met/point.py +++ b/scripts/python/met/point.py @@ -185,7 +185,7 @@ def check_point_data(self): # return met_point_tools.convert_to_ndarray(value_list) def dump(self): - met_base_point.print_point_data(self.get_point_data()) + met_point_tools.print_point_data(self.get_point_data()) def get_count_string(self): return f' nobs={self.nobs} nhdr={self.nhdr} ntyp={self.nhdr_typ} nsid={self.nhdr_sid} nvld={self.nhdr_vld} nqty={self.nobs_qty} nvar={self.nobs_var}' From b08518ade0d58c4110a0cd05f478246fec11dd48 Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Wed, 24 Apr 2024 09:29:04 -0600 Subject: [PATCH 04/12] reduce cognitive complexity to satisfy SonarQube and add boolean return value to catch if function fails to read data --- scripts/python/met/point_nc.py | 109 +++++++++++++++++---------------- 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/scripts/python/met/point_nc.py b/scripts/python/met/point_nc.py index 9e720947b8..2bb7ce3388 100644 --- a/scripts/python/met/point_nc.py +++ b/scripts/python/met/point_nc.py @@ -71,60 +71,63 @@ def read_data(self, nc_filename): method_name = f"{self.__class__.__name__}.read_data()" if nc_filename is None: self.log_error_msg(f"{method_name} The input NetCDF filename is missing") - elif not os.path.exists(nc_filename): + return False + if not os.path.exists(nc_filename): self.log_error_msg(f"{method_name} input NetCDF file ({nc_filename}) does not exist") + return False + + dataset = nc.Dataset(nc_filename, 'r') + + attr_name = 'use_var_id' + use_var_id_str = dataset.getncattr(attr_name) if attr_name in dataset.ncattrs() else "false" + self.use_var_id = use_var_id_str.lower() == 'true' + + # Header + self.hdr_typ = dataset['hdr_typ'][:] + self.hdr_sid = dataset['hdr_sid'][:] + self.hdr_vld = dataset['hdr_vld'][:] + self.hdr_lat = dataset['hdr_lat'][:] + self.hdr_lon = dataset['hdr_lon'][:] + self.hdr_elv = dataset['hdr_elv'][:] + self.hdr_typ_table = met_point_nc_tools.get_string_array(dataset, 'hdr_typ_table') + self.hdr_sid_table = met_point_nc_tools.get_string_array(dataset, 'hdr_sid_table') + self.hdr_vld_table = met_point_nc_tools.get_string_array(dataset, 'hdr_vld_table') + + nc_var = dataset.variables.get('obs_unit', None) + if nc_var: + self.obs_var_unit = nc_var[:] + nc_var = dataset.variables.get('obs_desc', None) + if nc_var: + self.obs_var_desc = nc_var[:] + + nc_var = dataset.variables.get('hdr_prpt_typ', None) + if nc_var: + self.hdr_prpt_typ = nc_var[:] + nc_var = dataset.variables.get('hdr_irpt_typ', None) + if nc_var: + self.hdr_irpt_typ = nc_var[:] + nc_var = dataset.variables.get('hdr_inst_typ', None) + if nc_var: + self.hdr_inst_typ =nc_var[:] + + #Observation data + self.hdr_sid = dataset['hdr_sid'][:] + self.obs_qty = np.array(dataset['obs_qty'][:]) + self.obs_hid = np.array(dataset['obs_hid'][:]) + self.obs_lvl = np.array(dataset['obs_lvl'][:]) + self.obs_hgt = np.array(dataset['obs_hgt'][:]) + self.obs_val = np.array(dataset['obs_val'][:]) + nc_var = dataset.variables.get('obs_vid', None) + if nc_var is None: + self.use_var_id = False + nc_var = dataset.variables.get('obs_gc', None) else: - dataset = nc.Dataset(nc_filename, 'r') - - attr_name = 'use_var_id' - use_var_id_str = dataset.getncattr(attr_name) if attr_name in dataset.ncattrs() else "false" - self.use_var_id = use_var_id_str.lower() == 'true' - - # Header - self.hdr_typ = dataset['hdr_typ'][:] - self.hdr_sid = dataset['hdr_sid'][:] - self.hdr_vld = dataset['hdr_vld'][:] - self.hdr_lat = dataset['hdr_lat'][:] - self.hdr_lon = dataset['hdr_lon'][:] - self.hdr_elv = dataset['hdr_elv'][:] - self.hdr_typ_table = met_point_nc_tools.get_string_array(dataset, 'hdr_typ_table') - self.hdr_sid_table = met_point_nc_tools.get_string_array(dataset, 'hdr_sid_table') - self.hdr_vld_table = met_point_nc_tools.get_string_array(dataset, 'hdr_vld_table') - - nc_var = dataset.variables.get('obs_unit', None) - if nc_var: - self.obs_var_unit = nc_var[:] - nc_var = dataset.variables.get('obs_desc', None) - if nc_var: - self.obs_var_desc = nc_var[:] - - nc_var = dataset.variables.get('hdr_prpt_typ', None) - if nc_var: - self.hdr_prpt_typ = nc_var[:] - nc_var = dataset.variables.get('hdr_irpt_typ', None) - if nc_var: - self.hdr_irpt_typ = nc_var[:] - nc_var = dataset.variables.get('hdr_inst_typ', None) - if nc_var: - self.hdr_inst_typ =nc_var[:] - - #Observation data - self.hdr_sid = dataset['hdr_sid'][:] - self.obs_qty = np.array(dataset['obs_qty'][:]) - self.obs_hid = np.array(dataset['obs_hid'][:]) - self.obs_lvl = np.array(dataset['obs_lvl'][:]) - self.obs_hgt = np.array(dataset['obs_hgt'][:]) - self.obs_val = np.array(dataset['obs_val'][:]) - nc_var = dataset.variables.get('obs_vid', None) - if nc_var is None: - self.use_var_id = False - nc_var = dataset.variables.get('obs_gc', None) - else: - self.obs_var_table = met_point_nc_tools.get_string_array(dataset, 'obs_var') - if nc_var: - self.obs_vid = np.array(nc_var[:]) - - self.obs_qty_table = met_point_nc_tools.get_string_array(dataset, 'obs_qty_table') + self.obs_var_table = met_point_nc_tools.get_string_array(dataset, 'obs_var') + if nc_var: + self.obs_vid = np.array(nc_var[:]) + + self.obs_qty_table = met_point_nc_tools.get_string_array(dataset, 'obs_qty_table') + return True def save_ncfile(self, nc_filename): met_data = self.get_point_data() @@ -307,5 +310,5 @@ def main(argv): point_obs_data.print_point_data(met_point_data) if __name__ == '__main__': - main() + main(sys.argv) print('Done python script') From 62bc92067bf4e2bee652993d7767b2c76a45ead8 Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Wed, 24 Apr 2024 09:47:59 -0600 Subject: [PATCH 05/12] clean up script and add comments --- .../python/examples/pyembed_met_point_nc.py | 68 +++++++++++-------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/scripts/python/examples/pyembed_met_point_nc.py b/scripts/python/examples/pyembed_met_point_nc.py index f1a97abab7..51613ae3b6 100644 --- a/scripts/python/examples/pyembed_met_point_nc.py +++ b/scripts/python/examples/pyembed_met_point_nc.py @@ -3,41 +3,49 @@ from met.point_nc import nc_point_obs +# Description: Reads a point observation NetCDF file created by MET and passes +# the data to another MET tool via Python Embedding. This script can be copied +# to perform modifications to the data before it is passed to MET. +# Example: plot_point_obs "PYTHON_NUMPY=pyembed_met_point_nc.py in.nc" out.ps +# Contact: George McCabe + +# Read and format the input 11-column observations: +# (1) string: Message_Type +# (2) string: Station_ID +# (3) string: Valid_Time(YYYYMMDD_HHMMSS) +# (4) numeric: Lat(Deg North) +# (5) numeric: Lon(Deg East) +# (6) numeric: Elevation(msl) +# (7) string: Var_Name(or GRIB_Code) +# (8) numeric: Level +# (9) numeric: Height(msl or agl) +# (10) string: QC_String +# (11) numeric: Observation_Value + print(f"Python Script:\t{sys.argv[0]}") -arg_cnt = len(sys.argv) if len(sys.argv) != 2: - print("ERROR: read_met_point.py -> Specify only 1 input file") + print("ERROR: pyembed_met_point_nc.py -> Specify only 1 input file") sys.exit(1) # Read the input file as the first argument input_file = os.path.expandvars(sys.argv[1]) -try: - print("Input File:\t" + repr(input_file)) - - # Read and format the input 11-column observations: - # (1) string: Message_Type - # (2) string: Station_ID - # (3) string: Valid_Time(YYYYMMDD_HHMMSS) - # (4) numeric: Lat(Deg North) - # (5) numeric: Lon(Deg East) - # (6) numeric: Elevation(msl) - # (7) string: Var_Name(or GRIB_Code) - # (8) numeric: Level - # (9) numeric: Height(msl or agl) - # (10) string: QC_String - # (11) numeric: Observation_Value - - # Read 11 column text input data by using pandas package - point_obs = nc_point_obs() - if not point_obs.read_data(input_file): - print(f"ERROR: Could not read MET point data file {input_file}") - sys.exit(1) - - df = point_obs.to_pandas() - point_data = df.values.tolist() - print(f" point_data: Data Length:\t{len(point_data)}") - print(f" point_data: Data Type:\t{type(point_data)}") -except FileNotFoundError: - print(f"The input file {input_file} does not exist") +print("Input File:\t" + repr(input_file)) + +# Read MET point observation NetCDF file +point_obs = nc_point_obs() +if not point_obs.read_data(input_file): + print(f"ERROR: Could not read MET point data file {input_file}") sys.exit(1) + +# convert point observation data to a pandas DataFrame +df = point_obs.to_pandas() + +################################################## +# perform any modifications to the data here # +################################################## + +# convert pandas DataFrame to list format that is expected by MET +point_data = df.values.tolist() +print(f" point_data: Data Length:\t{len(point_data)}") +print(f" point_data: Data Type:\t{type(point_data)}") From 284aba7ad6e462debfafdf5c56fcd5e16127c43d Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Wed, 24 Apr 2024 09:48:58 -0600 Subject: [PATCH 06/12] replace call to object function that doesn't exist, handle exception when file passed to script cannot be read by the NetCDF library --- scripts/python/met/point_nc.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/python/met/point_nc.py b/scripts/python/met/point_nc.py index 2bb7ce3388..062b5cbbdd 100644 --- a/scripts/python/met/point_nc.py +++ b/scripts/python/met/point_nc.py @@ -69,14 +69,18 @@ def get_nc_filename(self, args): def read_data(self, nc_filename): method_name = f"{self.__class__.__name__}.read_data()" - if nc_filename is None: - self.log_error_msg(f"{method_name} The input NetCDF filename is missing") + if not nc_filename: + print(f"ERROR: {method_name} The input NetCDF filename is missing") return False if not os.path.exists(nc_filename): - self.log_error_msg(f"{method_name} input NetCDF file ({nc_filename}) does not exist") + print(f"ERROR: {method_name} input NetCDF file ({nc_filename}) does not exist") return False - dataset = nc.Dataset(nc_filename, 'r') + try: + dataset = nc.Dataset(nc_filename, 'r') + except OSError: + print(f"ERROR: {method_name} Could not open NetCDF file ({nc_filename}") + return False attr_name = 'use_var_id' use_var_id_str = dataset.getncattr(attr_name) if attr_name in dataset.ncattrs() else "false" From ae1791b5cc213925b98b61593f9ab69888159eee Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Mon, 29 Apr 2024 17:46:53 +0000 Subject: [PATCH 07/12] rename example script --- .../{pyembed_met_point_nc.py => read_met_point_obs_pandas.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/python/examples/{pyembed_met_point_nc.py => read_met_point_obs_pandas.py} (100%) diff --git a/scripts/python/examples/pyembed_met_point_nc.py b/scripts/python/examples/read_met_point_obs_pandas.py similarity index 100% rename from scripts/python/examples/pyembed_met_point_nc.py rename to scripts/python/examples/read_met_point_obs_pandas.py From 2d974bf7a8bc6b0d51d8e5dd9028d0ac0b32f961 Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Thu, 2 May 2024 19:32:08 +0000 Subject: [PATCH 08/12] add new example script to makefiles --- scripts/python/examples/Makefile.am | 3 ++- scripts/python/examples/Makefile.in | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/python/examples/Makefile.am b/scripts/python/examples/Makefile.am index e0461a3564..f1712318a6 100644 --- a/scripts/python/examples/Makefile.am +++ b/scripts/python/examples/Makefile.am @@ -32,7 +32,8 @@ pythonexamples_DATA = \ read_ascii_numpy.py \ read_ascii_point.py \ read_ascii_xarray.py \ - read_met_point_obs.py + read_met_point_obs.py \ + read_met_point_obs_pandas.py EXTRA_DIST = ${pythonexamples_DATA} diff --git a/scripts/python/examples/Makefile.in b/scripts/python/examples/Makefile.in index 1d4a58cadf..b994ccfd57 100644 --- a/scripts/python/examples/Makefile.in +++ b/scripts/python/examples/Makefile.in @@ -317,7 +317,8 @@ pythonexamples_DATA = \ read_ascii_numpy.py \ read_ascii_point.py \ read_ascii_xarray.py \ - read_met_point_obs.py + read_met_point_obs.py \ + read_met_point_obs_pandas.py EXTRA_DIST = ${pythonexamples_DATA} MAINTAINERCLEANFILES = Makefile.in From b71160f73bd3fd5df01c9fc26763a6c098d2e90b Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Thu, 2 May 2024 20:08:41 +0000 Subject: [PATCH 09/12] fix logic to build pandas DataFrame to properly get header information from observation header IDs --- scripts/python/met/point_nc.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/python/met/point_nc.py b/scripts/python/met/point_nc.py index 062b5cbbdd..d3dfc4220c 100644 --- a/scripts/python/met/point_nc.py +++ b/scripts/python/met/point_nc.py @@ -285,12 +285,12 @@ def write_nc_data(nc_dataset, point_obs): def to_pandas(self): return pd.DataFrame({ - 'typ': [self.hdr_typ_table[i] for i in self.hdr_typ], - 'sid': [self.hdr_sid_table[i] for i in self.hdr_sid], - 'vld': [self.hdr_vld_table[i] for i in self.hdr_vld], - 'lat': self.hdr_lat, - 'lon': self.hdr_lon, - 'elv': self.hdr_elv, + 'typ': [self.hdr_typ_table[self.hdr_typ[i]] for i in self.obs_hid], + 'sid': [self.hdr_sid_table[self.hdr_sid[i]] for i in self.obs_hid], + 'vld': [self.hdr_vld_table[self.hdr_vld[i]] for i in self.obs_hid], + 'lat': [self.hdr_lat[i] for i in self.obs_hid], + 'lon': [self.hdr_lon[i] for i in self.obs_hid], + 'elv': [self.hdr_elv[i] for i in self.obs_hid], 'var': [self.obs_var_table[i] if self.use_var_id else f'{i}' for i in self.obs_vid], 'lvl': self.obs_lvl, From 2c9d22055dea974a1974fae7222fe2e140839900 Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Thu, 2 May 2024 20:09:36 +0000 Subject: [PATCH 10/12] Per #2781, add unit test to demonstrate python embedding script that reads MET NetCDF point observation file and converts it to a pandas DataFrame --- internal/test_unit/xml/unit_python.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/internal/test_unit/xml/unit_python.xml b/internal/test_unit/xml/unit_python.xml index af782db022..0640aafd74 100644 --- a/internal/test_unit/xml/unit_python.xml +++ b/internal/test_unit/xml/unit_python.xml @@ -557,6 +557,20 @@ + + &MET_BIN;/plot_point_obs + \ + 'PYTHON_NUMPY=&MET_BASE;/python/examples/read_met_point_obs_pandas.py &OUTPUT_DIR;/pb2nc/ndas.20120409.t12z.prepbufr.tm00.nc' \ + &OUTPUT_DIR;/python/ndas.20120409.t12z.prepbufr.tm00.nr_met_nc_to_pandas.ps \ + -data_file &DATA_DIR_MODEL;/grib2/nam/nam_2012040900_F012.grib2 \ + -dotsize 2.0 \ + -v 1 + + + &OUTPUT_DIR;/python/ndas.20120409.t12z.prepbufr.tm00.nr_met_nc_to_pandas.ps + + + echo "&DATA_DIR_MODEL;/grib1/arw-fer-gep1/arw-fer-gep1_2012040912_F024.grib \ &DATA_DIR_MODEL;/grib1/arw-fer-gep5/arw-fer-gep5_2012040912_F024.grib \ From 51db09f88008cf2676cb250ef1a8efccf047502f Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Wed, 8 May 2024 15:44:35 +0000 Subject: [PATCH 11/12] Per #2781, added init function for nc_point_obs to take an input filename. Also raise TypeError exception from nc_point_obs.read_data() if input file cannot be read --- .../python/examples/read_met_point_obs_pandas.py | 5 +++-- scripts/python/met/point_nc.py | 16 ++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/scripts/python/examples/read_met_point_obs_pandas.py b/scripts/python/examples/read_met_point_obs_pandas.py index 51613ae3b6..bf7bb5527b 100644 --- a/scripts/python/examples/read_met_point_obs_pandas.py +++ b/scripts/python/examples/read_met_point_obs_pandas.py @@ -33,8 +33,9 @@ print("Input File:\t" + repr(input_file)) # Read MET point observation NetCDF file -point_obs = nc_point_obs() -if not point_obs.read_data(input_file): +try: + point_obs = nc_point_obs(input_file) +except TypeError: print(f"ERROR: Could not read MET point data file {input_file}") sys.exit(1) diff --git a/scripts/python/met/point_nc.py b/scripts/python/met/point_nc.py index d3dfc4220c..c0773e65f7 100644 --- a/scripts/python/met/point_nc.py +++ b/scripts/python/met/point_nc.py @@ -55,6 +55,10 @@ def get_string_array(nc_group, var_name): class nc_point_obs(met_point_obs): + def __init__(self, nc_filename=None): + if nc_filename: + self.read_data(nc_filename) + # args should be string, list, or dictionary def get_nc_filename(self, args): nc_filename = None @@ -70,17 +74,14 @@ def get_nc_filename(self, args): def read_data(self, nc_filename): method_name = f"{self.__class__.__name__}.read_data()" if not nc_filename: - print(f"ERROR: {method_name} The input NetCDF filename is missing") - return False + raise TypeError(f"{method_name} The input NetCDF filename is missing") if not os.path.exists(nc_filename): - print(f"ERROR: {method_name} input NetCDF file ({nc_filename}) does not exist") - return False + raise TypeError(f"{method_name} input NetCDF file ({nc_filename}) does not exist") try: - dataset = nc.Dataset(nc_filename, 'r') + dataset = nc.Dataset(nc_filename, 'r') except OSError: - print(f"ERROR: {method_name} Could not open NetCDF file ({nc_filename}") - return False + raise TypeError(f"{method_name} Could not open NetCDF file ({nc_filename}") attr_name = 'use_var_id' use_var_id_str = dataset.getncattr(attr_name) if attr_name in dataset.ncattrs() else "false" @@ -131,7 +132,6 @@ def read_data(self, nc_filename): self.obs_vid = np.array(nc_var[:]) self.obs_qty_table = met_point_nc_tools.get_string_array(dataset, 'obs_qty_table') - return True def save_ncfile(self, nc_filename): met_data = self.get_point_data() From 7e9cef947771577e642927d2b54fb2adfe9963fb Mon Sep 17 00:00:00 2001 From: George McCabe <23407799+georgemccabe@users.noreply.github.com> Date: Wed, 8 May 2024 17:04:48 +0000 Subject: [PATCH 12/12] call parent class init function to properly initialize nc_point_obs --- scripts/python/met/point_nc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/python/met/point_nc.py b/scripts/python/met/point_nc.py index c0773e65f7..db73d8fae4 100644 --- a/scripts/python/met/point_nc.py +++ b/scripts/python/met/point_nc.py @@ -56,6 +56,7 @@ def get_string_array(nc_group, var_name): class nc_point_obs(met_point_obs): def __init__(self, nc_filename=None): + super().__init__() if nc_filename: self.read_data(nc_filename)