Skip to content

Commit

Permalink
Adding keyword options to notify user when the unit conversion has a …
Browse files Browse the repository at this point in the history
…problem.
  • Loading branch information
kenkehoe committed Jan 26, 2024
1 parent 8853680 commit d05cca6
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 5 deletions.
16 changes: 14 additions & 2 deletions act/utils/data_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ def __init__(self, ds):
self._ds = ds

def change_units(
self, variables=None, desired_unit=None, skip_variables=None, skip_standard=True
self, variables=None, desired_unit=None, skip_variables=None, skip_standard=True,
verbose=False, raise_error=False
):
"""
Parameters
Expand All @@ -51,6 +52,13 @@ def change_units(
Flag indicating the QC variables that will not need changing are
skipped. Makes the processing faster when processing all variables
in dataset.
verbose : boolean
Option to print statement when an attempted conversion fails. Set to False
as default because many units strings are not udunits complient and when
trying to convert all varialbes of a type of units (eg temperature) the code
can print a lot of unecessary information.
raise_error : boolean
Raise an error if conversion is not successful.
Returns
-------
Expand Down Expand Up @@ -102,7 +110,11 @@ def change_units(
pint.errors.UndefinedUnitError,
np.core._exceptions.UFuncTypeError,
):
continue
if raise_error:
raise ValueError(f"Unable to convert '{var_name}' to units of '{desired_unit}'.")
elif verbose:
print(f"\n Unable to convert '{var_name}' to units of '{desired_unit}'. "
f"Skipping unit converstion for '{var_name}'.\n")

return self._ds

Expand Down
30 changes: 27 additions & 3 deletions tests/utils/test_data_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import pytest
import xarray as xr
from numpy.testing import assert_almost_equal
from contextlib import redirect_stdout
from io import StringIO

import act
from act.utils.data_utils import DatastreamParserARM as DatastreamParser
Expand Down Expand Up @@ -93,10 +95,13 @@ def test_convert_units():
data = act.utils.data_utils.convert_units(r_data, 'K', 'C')
assert np.ceil(data[0]) == 12

try:
# try:
# ds.utils.change_units()
# except ValueError as error:
# assert str(error) == "Need to provide 'desired_unit' keyword for .change_units() method"

with np.testing.assert_raises(ValueError):
ds.utils.change_units()
except ValueError as error:
assert str(error) == "Need to provide 'desired_unit' keyword for .change_units() method"

desired_unit = 'degF'
skip_vars = [ii for ii in ds.data_vars if ii.startswith('qc_')]
Expand Down Expand Up @@ -138,6 +143,25 @@ def test_convert_units():
ds.close()
del ds

# Test if exception or print statement is issued when an error occurs with units string
ds = act.io.arm.read_arm_netcdf(act.tests.sample_files.EXAMPLE_EBBR1)
with np.testing.assert_raises(ValueError):
ds.utils.change_units('home_signal_15', 'not_a_real_unit_string', raise_error=True)

with np.testing.assert_raises(ValueError):
ds.utils.change_units('not_a_real_variable_name', 'degC', raise_error=True)

f = StringIO()
var_name = 'home_signal_15'
unit = 'not_a_real_unit_string'
with redirect_stdout(f):
ds.utils.change_units('home_signal_15', 'not_a_real_unit_string', verbose=True)
s = f.getvalue()
assert s.strip() == f"Unable to convert '{var_name}' to units of '{unit}'. Skipping unit converstion for '{var_name}'."

ds.close()
del ds


def test_ts_weighted_average():
ds = act.io.arm.read_arm_netcdf(act.tests.sample_files.EXAMPLE_MET_WILDCARD)
Expand Down

0 comments on commit d05cca6

Please sign in to comment.