Source code for pywatershed.utils.control
import pathlib as pl
from typing import Union
from warnings import warn
import numpy as np
from .prms5_file_util import PrmsFile
fileish = Union[str, pl.PosixPath, dict]
listish = Union[str, list, tuple]
[docs]
class ControlVariables:
"""PRMS control file class
Args:
control_dict: control variable dictionary
"""
[docs]
def __init__(self, control_dict: dict) -> "ControlVariables":
self.control = control_dict["control"]
[docs]
def get_variables(self, keys: listish) -> "ControlVariables":
"""Get a subset of keys in the control variable dictionary
Args:
keys: keys to retrieve from the full PRMS control variable object
Returns:
ControlVariables : subset of full control variable dictionary
Passed keys that do not exist in the full control variable
dictionary are skipped.
"""
if isinstance(keys, str):
keys = [keys]
return ControlVariables(
{
key: self.control.get(key)
for key in keys
if key in self.control.keys()
}
)
[docs]
@staticmethod
def load(control_file: fileish) -> "ControlVariables":
"""Load variables from a PRMS control file
Args:
control_file: control file path
Returns:
ControlVariables: full PRMS control variable dictionary
"""
return ControlVariables(
PrmsFile(control_file, file_type="control").get_data()
)
def compare_control_files(file0, file1, silent=False):
"""Compare the contents of two control files.
Args:
file0: str or pathlib.Path for the first PRMS control file
file1: str or pathlib.Path for the second PRMS control file
silent: suppress informative warnings (if you only want the return
value)
Returns:
A bash-style integer where zero indicates the files are identical and
all other values indicate the files are not identical and the total
number of keys with differences.
"""
return_code = 0
ctl0 = ControlVariables.load(file0).control
ctl1 = ControlVariables.load(file1).control
ctl0_keys_only = set(ctl0.keys()) - set(ctl1.keys())
ctl1_keys_only = set(ctl1.keys()) - set(ctl0.keys())
if len(ctl0_keys_only):
return_code = len(ctl0_keys_only)
if not silent:
warn(f"Keys only in control file0: {sorted(ctl0_keys_only)}")
if len(ctl1_keys_only):
return_code = len(ctl1_keys_only)
if not silent:
warn(f"Keys only in control file1: {sorted(ctl1_keys_only)}")
common_keys = set(ctl0.keys()).intersection(set(ctl1.keys()))
for ck in common_keys:
try:
np.testing.assert_equal(ctl0[ck], ctl1[ck])
except AssertionError:
return_code += 1
if not silent:
msg = (
f"Keys '{ck}' differ\n"
f"file0: {ctl0[ck]}\n"
f"file1: {ctl1[ck]}\n"
)
warn(msg)
return return_code