Commit f178ebb8 authored by Thibault Hallouin's avatar Thibault Hallouin
Browse files

enforce ndarray as input data type to be able to check array ranks

otherwise it is not very easy from the error message to deduce the
problem is due to a mismatch in number of dimensions
1 merge request!1release v0.1.0.0
Pipeline #43916 passed with stage
in 3 minutes and 51 seconds
Showing with 61 additions and 20 deletions
+61 -20
from typing import List, Dict
from numpy import dtype
from numpy.typing import NDArray, ArrayLike
from numpy.typing import NDArray
try:
from ._evalhyd import _evald
......@@ -15,9 +15,9 @@ def evald(q_obs: NDArray[dtype('float64')],
exponent: float = None,
epsilon: float = None,
t_msk: NDArray[dtype('bool')] = None,
m_cdt: ArrayLike = None,
m_cdt: NDArray[dtype('|S32')] = None,
bootstrap: Dict[str, int] = None,
dts: ArrayLike = None,
dts: NDArray[dtype('|S32')] = None,
seed: int = None) -> List[NDArray[dtype('float64')]]:
"""Function to evaluate deterministic streamflow predictions"""
......@@ -47,4 +47,22 @@ def evald(q_obs: NDArray[dtype('float64')],
if seed is not None:
kwargs['seed'] = seed
# check array ranks
_expected = {
'q_obs': 2,
'q_prd': 2,
't_msk': 3,
'm_cdt': 2,
'dts': 1
}
for arg, val in _expected.items():
try:
if kwargs[arg].ndim != val:
raise RuntimeError(
f"'{arg}' must feature {val} {'axis' if val == 1 else 'axes'}"
)
except KeyError:
pass
return _evald(**kwargs)
from typing import List, Dict
from numpy import dtype
from numpy.typing import NDArray, ArrayLike
from numpy.typing import NDArray
try:
from ._evalhyd import _evalp
......@@ -15,9 +15,9 @@ def evalp(q_obs: NDArray[dtype('float64')],
events: str = None,
c_lvl: NDArray[dtype('float64')] = None,
t_msk: NDArray[dtype('bool')] = None,
m_cdt: ArrayLike = None,
m_cdt: NDArray[dtype('|S32')] = None,
bootstrap: Dict[str, int] = None,
dts: ArrayLike = None,
dts: NDArray[dtype('|S32')] = None,
seed: int = None) -> List[NDArray[dtype('float64')]]:
"""Function to evaluate probabilistic streamflow predictions"""
......@@ -46,4 +46,24 @@ def evalp(q_obs: NDArray[dtype('float64')],
if seed is not None:
kwargs['seed'] = seed
# check array ranks
_expected = {
'q_obs': 2,
'q_prd': 4,
'q_thr': 2,
'c_lvl': 1,
't_msk': 4,
'm_cdt': 2,
'dts': 1
}
for arg, val in _expected.items():
try:
if kwargs[arg].ndim != val:
raise RuntimeError(
f"'{arg}' must feature {val} {'axis' if val == 1 else 'axes'}"
)
except KeyError:
pass
return _evalp(**kwargs)
......@@ -131,10 +131,11 @@ class TestMetrics(unittest.TestCase):
)
def test_intervals_metrics(self):
lvl = numpy.array([30., 80.])
for metric in self.expected_itv.keys():
with self.subTest(metric=metric):
numpy.testing.assert_almost_equal(
evalhyd.evalp(_obs, _prd, [metric], c_lvl=[30., 80.])[0],
evalhyd.evalp(_obs, _prd, [metric], c_lvl=lvl)[0],
self.expected_itv[metric]
)
......@@ -176,7 +177,7 @@ class TestMasking(unittest.TestCase):
def test_conditions(self):
with self.subTest(conditions="observed streamflow values"):
cdt = numpy.array([["q_obs{<2000,>3000}"]], dtype='|S32')
cdt = numpy.array([["q_obs{<2000,>3000}"]])
msk = (_obs[0] < 2000) | (_obs[0] > 3000)
......@@ -215,28 +216,29 @@ class TestMissingData(unittest.TestCase):
continue
with self.subTest(metric=metric):
lvl = numpy.array([30., 80.])
numpy.testing.assert_almost_equal(
# missing data flagged as NaN
evalhyd.evalp(
[[4.7, numpy.nan, 5.5, 2.7, 4.1]],
[[[[5.3, 4.2, 5.7, 2.3, numpy.nan],
[4.3, 4.2, 4.7, 4.3, numpy.nan],
[5.3, 5.2, 5.7, 2.3, numpy.nan]]]],
numpy.array([[4.7, numpy.nan, 5.5, 2.7, 4.1]]),
numpy.array([[[[5.3, 4.2, 5.7, 2.3, numpy.nan],
[4.3, 4.2, 4.7, 4.3, numpy.nan],
[5.3, 5.2, 5.7, 2.3, numpy.nan]]]]),
[metric],
thr,
"high",
[30., 80.]
lvl
)[0],
# missing data pairwise deleted from series
evalhyd.evalp(
[[4.7, 5.5, 2.7]],
[[[[5.3, 5.7, 2.3],
[4.3, 4.7, 4.3],
[5.3, 5.7, 2.3]]]],
numpy.array([[4.7, 5.5, 2.7]]),
numpy.array([[[[5.3, 5.7, 2.3],
[4.3, 4.7, 4.3],
[5.3, 5.7, 2.3]]]]),
[metric],
thr,
"high",
[30., 80.]
lvl
)[0]
)
......@@ -265,6 +267,7 @@ class TestUncertainty(unittest.TestCase):
continue
with self.subTest(metric=metric):
lvl = numpy.array([30., 80.])
numpy.testing.assert_almost_equal(
# bootstrap with only one year of data
# (compare last sample only to have matching dimensions)
......@@ -278,7 +281,7 @@ class TestUncertainty(unittest.TestCase):
"n_samples": 10, "len_sample": 3, "summary": 0
},
dts=dts_1yr,
c_lvl=[30., 80.]
c_lvl=lvl
)[0][:, :, :, [0]],
# repeat year of data three times to correspond to a
# bootstrap sample of length 3
......@@ -288,7 +291,7 @@ class TestUncertainty(unittest.TestCase):
[metric],
q_thr=thr,
events="high",
c_lvl=[30., 80.]
c_lvl=lvl
)[0]
)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment