Skip to content

Commit

Permalink
Black reformatting.
Browse files Browse the repository at this point in the history
  • Loading branch information
5tefan committed Feb 25, 2020
1 parent 3a1dd11 commit b6f5d99
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 94 deletions.
49 changes: 38 additions & 11 deletions ncflag/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,69 @@
except pkg_resources.DistributionNotFound:
version = "unknown"


def show_flags(ctx, param, ncfile):
if not ncfile or ctx.resilient_parsing:
return
valid_flags = []
with nc.Dataset(ncfile) as nc_in: # type: nc.Dataset
for k, v in nc_in.variables.items():
if hasattr(v, "flag_values") and hasattr(v, "flag_meanings") and len(v.dimensions) == 1:
if (
hasattr(v, "flag_values")
and hasattr(v, "flag_meanings")
and len(v.dimensions) == 1
):
valid_flags.append(k)
click.echo("Inspectable flags: %s" % map(str, valid_flags))
ctx.exit()


@click.command()
@click.version_option(version, "-v", "--version")
@click.option("--show_flags", callback=show_flags, expose_value=False, is_eager=True,
type=click.Path(exists=True, dir_okay=False), help="Print the flags this tool can inspect.")
@click.option(
"--show_flags",
callback=show_flags,
expose_value=False,
is_eager=True,
type=click.Path(exists=True, dir_okay=False),
help="Print the flags this tool can inspect.",
)
@click.argument("ncfile", type=click.Path(exists=True, dir_okay=False))
@click.argument("flag", type=click.STRING)
@click.option("--use_time_var", type=click.STRING, default=None)
@click.option("-l", help="log level", type=click.Choice(['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']),
default="WARNING")
@click.option(
"-l",
help="log level",
type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]),
default="WARNING",
)
def cli(ncfile, flag, use_time_var, l):
logging.getLogger().setLevel(l)
with nc.Dataset(ncfile) as nc_in: # type: nc.Dataset
# initial checks
v = nc_in.variables[flag] # type: nc.Variable
assert hasattr(v, "flag_values"), "%s is not CF compliant flag, missing flag_values" % flag
assert hasattr(v, "flag_meanings"), "%s is not CF compliant flag, missing flag_meanings" % flag
assert len(v.dimensions) == 1, "multidimensional flags are not supported, see docs and use ipython instead"
assert hasattr(v, "flag_values"), (
"%s is not CF compliant flag, missing flag_values" % flag
)
assert hasattr(v, "flag_meanings"), (
"%s is not CF compliant flag, missing flag_meanings" % flag
)
assert (
len(v.dimensions) == 1
), "multidimensional flags are not supported, see docs and use ipython instead"
w = FlagWrap.init_from_netcdf(v)
if use_time_var is not None:
t = nc_in.variables[use_time_var] # type: nc.Variable
assert t.dimensions == v.dimensions, "To print flags by time, time flag must share dimensions"
assert hasattr(t, "units"), "did not find units on time flag %s" % use_time_var
assert (
t.dimensions == v.dimensions
), "To print flags by time, time flag must share dimensions"
assert hasattr(t, "units"), (
"did not find units on time flag %s" % use_time_var
)
for i, dt in enumerate(nc.num2date(t[:], t.units)):
out_time = dt.isoformat() if dt is not None else "__________________________"
out_time = (
dt.isoformat() if dt is not None else "__________________________"
)
click.echo("%s: %s" % (out_time, w.get_flags_set_at_index(i)))
else:
for i in range(v.size):
Expand Down
52 changes: 36 additions & 16 deletions ncflag/flag_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,27 @@ def __init__(self, flags, flag_meanings, flag_values, flag_masks=None):
if isinstance(flag_meanings, string_types):
self._flag_meanings = flag_meanings.split() # split on spaces
else:
assert isinstance(flag_meanings, list), \
"expected flag_meanings as either list of flag_meanings, or space separated string of flag_meanings"
assert isinstance(
flag_meanings, list
), "expected flag_meanings as either list of flag_meanings, or space separated string of flag_meanings"
self._flag_meanings = flag_meanings

self._flag_values = np.array(flag_values).astype(self.flags.dtype)
assert len(self._flag_values) == len(self._flag_meanings), \
"flag_meanings vs flag_values length mismatch: found {} and {}".format(len(self._flag_meanings),
len(self._flag_values))
assert len(self._flag_values) == len(
self._flag_meanings
), "flag_meanings vs flag_values length mismatch: found {} and {}".format(
len(self._flag_meanings), len(self._flag_values)
)

if flag_masks is None:
self._flag_masks = np.full_like(self._flag_values, -1)
else:
self._flag_masks = np.array(flag_masks).astype(self.flags.dtype)
assert len(self._flag_masks) == len(self._flag_meanings), \
"flag_meanings vs flag_masks length mismatch: found {} and {}".format(len(self._flag_meanings),
len(self._flag_masks))
assert len(self._flag_masks) == len(
self._flag_meanings
), "flag_meanings vs flag_masks length mismatch: found {} and {}".format(
len(self._flag_meanings), len(self._flag_masks)
)

# This is only for use with init_from_netcdf to hold the reference to nc_var so that
# the caller doesn't have to associate the write_to_netcdf call with an nc_var if it's the same as
Expand All @@ -76,9 +81,19 @@ def init_from_netcdf(cls, nc_var, shape=None, fill=None):
"""
if shape is not None and fill is not None:
flags = np.full(shape, fill, dtype=nc_var.dtype)
instance = cls(flags, nc_var.flag_meanings, nc_var.flag_values, getattr(nc_var, "flag_masks", None))
instance = cls(
flags,
nc_var.flag_meanings,
nc_var.flag_values,
getattr(nc_var, "flag_masks", None),
)
else:
instance = cls(nc_var[:], nc_var.flag_meanings, nc_var.flag_values, getattr(nc_var, "flag_masks", None))
instance = cls(
nc_var[:],
nc_var.flag_meanings,
nc_var.flag_values,
getattr(nc_var, "flag_masks", None),
)

instance._nc_var = nc_var

Expand All @@ -95,13 +110,17 @@ def write_to_netcdf(self, nc_var=None):
if nc_var is None and self._nc_var is not None:
nc_var = self._nc_var
elif nc_var is None:
raise RuntimeError("write_to_netcdf called w/o target nc_var and appears not to be init from an nc_var.")
raise RuntimeError(
"write_to_netcdf called w/o target nc_var and appears not to be init from an nc_var."
)

nc_var[:] = self.flags
nc_var.flag_meanings = " ".join(self._flag_meanings)
nc_var.flag_values = self._flag_values
if (not np.all(self._flag_masks == np.full_like(self._flag_values, -1)) or
getattr(nc_var, "flag_masks", None) is not None):
if (
not np.all(self._flag_masks == np.full_like(self._flag_values, -1))
or getattr(nc_var, "flag_masks", None) is not None
):
# only write masks if they aren't the default all bits 1 or somethign existed before
nc_var.flag_masks = self._flag_masks

Expand Down Expand Up @@ -129,7 +148,9 @@ def get(meaning):
mask = ~np.ma.getmask(self.flags)

# only the booleans to True potentially only where flags are not masked in the first place.
default[mask] = (self.flags[mask] & self._flag_masks[index]) == self._flag_values[index]
default[mask] = (
self.flags[mask] & self._flag_masks[index]
) == self._flag_values[index]
return default

if isinstance(flag_meaning, (list, tuple)):
Expand Down Expand Up @@ -161,7 +182,7 @@ def reduce(self, exclude_mask=0, axis=-1):
np.ma.bitwise_or.reduce(self.flags, axis=axis) & ~exclude_mask,
self._flag_meanings,
self._flag_values,
self._flag_masks
self._flag_masks,
)

def get_flag_at_index(self, flag_meaning, i):
Expand Down Expand Up @@ -325,4 +346,3 @@ def get_mask_for_meaning(self, flag_meaning):
"""
index = self._flag_meanings.index(flag_meaning)
return self._flag_masks[index]

18 changes: 7 additions & 11 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,19 @@
from pypandoc import convert_file

setup(
name='ncflag',
version='0.2.5',
name="ncflag",
version="0.2.5",
description="Utility and library to interface with CF-Compliant NetCDF flag variables.",
author="Stefan Codrescu",
author_email="[email protected]",
url="https://github.com/5tefan/ncflag",
packages=["ncflag"],
long_description=convert_file('README.md', 'rst'),
install_requires=[
'Click',
'numpy',
'netCDF4'
],
entry_points='''
long_description=convert_file("README.md", "rst"),
install_requires=["Click", "numpy", "netCDF4"],
entry_points="""
[console_scripts]
ncflag=ncflag.cli:cli
''',
""",
include_package_data=False,
classifiers=[
"Development Status :: 4 - Beta",
Expand All @@ -27,5 +23,5 @@
"Programming Language :: Python :: 3.6",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
]
],
)
30 changes: 21 additions & 9 deletions test/test_real_netcdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
import netCDF4 as nc
import os


def get_dataset():
datafile = os.path.join(os.path.dirname(__file__), "data/ops_exis-l1b-sfxr_g16_d20180402_v0-0-0.nc")
datafile = os.path.join(
os.path.dirname(__file__), "data/ops_exis-l1b-sfxr_g16_d20180402_v0-0-0.nc"
)
return nc.Dataset(datafile, "r")


Expand Down Expand Up @@ -38,20 +41,29 @@ def test_misc_consistency(self):
self.assertEqual(f.get_value_for_meaning("good_quality_qf"), 0)
# similarly, the masking being first in the list is easy to see..
self.assertEqual(f.get_mask_for_meaning("good_quality_qf"), 524287)

# this particular file has degraded_due_to_XRS-A_solar_maximum_channel_signal_near_zero_qf set
# at index 0:
original_flags = f.get_flags_set_at_index(0)
self.assertIn("degraded_due_to_XRS-A_solar_maximum_channel_signal_near_zero_qf", original_flags)
self.assertIn(
"degraded_due_to_XRS-A_solar_maximum_channel_signal_near_zero_qf",
original_flags,
)

# set a new flag... make sure it wasn't there orignally, and is there now.
f.set_flag_at_index("degraded_due_to_insufficient_number_of_integrations_after_XRS_reset_qf", 0)
self.assertNotIn("degraded_due_to_insufficient_number_of_integrations_after_XRS_reset_qf", original_flags)
self.assertIn("degraded_due_to_insufficient_number_of_integrations_after_XRS_reset_qf", f.get_flags_set_at_index(0))

f.set_flag_at_index(
"degraded_due_to_insufficient_number_of_integrations_after_XRS_reset_qf", 0
)
self.assertNotIn(
"degraded_due_to_insufficient_number_of_integrations_after_XRS_reset_qf",
original_flags,
)
self.assertIn(
"degraded_due_to_insufficient_number_of_integrations_after_XRS_reset_qf",
f.get_flags_set_at_index(0),
)

# try to set good_quality_qf at index 0... make sure it is now set. Setting good_quality_qf should
# also implicitly unset all the other flags based on the way it's defined.... the assertEqual covers this.
f.set_flag_at_index("good_quality_qf", 0)
self.assertEqual(["good_quality_qf"], f.get_flags_set_at_index(0))


Loading

0 comments on commit b6f5d99

Please sign in to comment.