Skip to content

Commit

Permalink
fix raises, best practices, docs
Browse files Browse the repository at this point in the history
  • Loading branch information
richardarsenault committed Jan 16, 2024
1 parent b32ec6f commit 92f75c5
Show file tree
Hide file tree
Showing 6 changed files with 649 additions and 383 deletions.
42 changes: 21 additions & 21 deletions tests/test_calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def test_spotpy_calibration():
model_config = {
"precip": np.array([10, 11, 12, 13, 14, 15]),
"temperature": np.array([10, 3, -5, 1, 15, 0]),
"Qobs": np.array([120, 130, 140, 150, 160, 170]),
"qobs": np.array([120, 130, 140, 150, 160, 170]),
"drainage_area": np.array([10]),
"model_name": "Dummy",
}
Expand All @@ -39,7 +39,7 @@ def test_spotpy_calibration():

# Test that the objective function is calculated correctly
objfun = get_objective_function(
model_config["Qobs"],
model_config["qobs"],
best_simulation,
obj_func="mae",
mask=mask,
Expand All @@ -49,8 +49,8 @@ def test_spotpy_calibration():

# Test dummy model response
model_config["parameters"] = [5, 5, 5]
Qsim = dummy_model(model_config)
assert Qsim[3] == 3500.00
qsim = dummy_model(model_config)
assert qsim["qsim"].values[3] == 3500.00

# Also test to ensure SCEUA and take_minimize is required.
best_parameters_sceua, best_simulation, best_objfun = perform_calibration(
Expand Down Expand Up @@ -98,11 +98,11 @@ def test_calibration_failure_mode_unknown_optimizer():
model_config = {
"precip": np.array([10, 11, 12, 13, 14, 15]),
"temperature": np.array([10, 3, -5, 1, 15, 0]),
"Qobs": np.array([120, 130, 140, 150, 160, 170]),
"qobs": np.array([120, 130, 140, 150, 160, 170]),
"drainage_area": np.array([10]),
"model_name": "Dummy",
}
with pytest.raises(SystemExit) as pytest_wrapped_e:
with pytest.raises(NotImplementedError) as pytest_wrapped_e:
best_parameters_transform, best_simulation, best_objfun = perform_calibration(
model_config,
"nse",
Expand All @@ -111,27 +111,27 @@ def test_calibration_failure_mode_unknown_optimizer():
evaluations=10,
algorithm="OTHER",
)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.type == NotImplementedError


def test_transform():
"""Test the flow transformer"""
Qsim = np.array([10, 10, 10])
Qobs = np.array([5, 5, 5])
qsim = np.array([10, 10, 10])
qobs = np.array([5, 5, 5])

Qsim_r, Qobs_r = transform_flows(Qsim, Qobs, transform="inv", epsilon=0.01)
np.testing.assert_array_almost_equal(Qsim_r[1], 0.0995024, 6)
np.testing.assert_array_almost_equal(Qobs_r[1], 0.1980198, 6)
qsim_r, qobs_r = transform_flows(qsim, qobs, transform="inv", epsilon=0.01)
np.testing.assert_array_almost_equal(qsim_r[1], 0.0995024, 6)
np.testing.assert_array_almost_equal(qobs_r[1], 0.1980198, 6)

Qsim_r, Qobs_r = transform_flows(Qsim, Qobs, transform="sqrt")
np.testing.assert_array_almost_equal(Qsim_r[1], 3.1622776, 6)
np.testing.assert_array_almost_equal(Qobs_r[1], 2.2360679, 6)
qsim_r, qobs_r = transform_flows(qsim, qobs, transform="sqrt")
np.testing.assert_array_almost_equal(qsim_r[1], 3.1622776, 6)
np.testing.assert_array_almost_equal(qobs_r[1], 2.2360679, 6)

Qsim_r, Qobs_r = transform_flows(Qsim, Qobs, transform="log", epsilon=0.01)
np.testing.assert_array_almost_equal(Qsim_r[1], 2.3075726, 6)
np.testing.assert_array_almost_equal(Qobs_r[1], 1.6193882, 6)
qsim_r, qobs_r = transform_flows(qsim, qobs, transform="log", epsilon=0.01)
np.testing.assert_array_almost_equal(qsim_r[1], 2.3075726, 6)
np.testing.assert_array_almost_equal(qobs_r[1], 1.6193882, 6)

# Test Qobs different length than Qsim
with pytest.raises(SystemExit) as pytest_wrapped_e:
Qobs_r, Qobs_r = transform_flows(Qsim, Qobs, transform="a", epsilon=0.01)
assert pytest_wrapped_e.type == SystemExit
with pytest.raises(NotImplementedError) as pytest_wrapped_e:
qobs_r, qobs_r = transform_flows(qsim, qobs, transform="a", epsilon=0.01)
assert pytest_wrapped_e.type == NotImplementedError
14 changes: 7 additions & 7 deletions tests/test_hydrological_modelling.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import numpy as np
import pytest

from xhydro.modelling.hydrological_modelling import hydrological_model_selector
from xhydro.modelling.hydrological_modelling import run_hydrological_model


def test_hydrological_modelling():
Expand All @@ -11,23 +11,23 @@ def test_hydrological_modelling():
model_config = {
"precip": np.array([10, 11, 12, 13, 14, 15]),
"temperature": np.array([10, 3, -5, 1, 15, 0]),
"Qobs": np.array([120, 130, 140, 150, 160, 170]),
"qobs": np.array([120, 130, 140, 150, 160, 170]),
"drainage_area": np.array([10]),
"model_name": "Dummy",
"parameters": np.array([5, 5, 5]),
}
Qsim = hydrological_model_selector(model_config)
assert Qsim[3] == 3500.00
qsim = run_hydrological_model(model_config)
assert qsim["qsim"].values[3] == 3500.00

# Test the exceptions for new models
model_config.update(model_name="ADD_OTHER_HERE")
Qsim = hydrological_model_selector(model_config)
assert Qsim == 0
qsim = run_hydrological_model(model_config)
assert qsim == 0


def test_import_unknown_model():
"""Test for unknown model"""
with pytest.raises(NotImplementedError) as pytest_wrapped_e:
model_config = {"model_name": "fake_model"}
_ = hydrological_model_selector(model_config)
_ = run_hydrological_model(model_config)
assert pytest_wrapped_e.type == NotImplementedError
76 changes: 38 additions & 38 deletions tests/test_objective_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,150 +10,150 @@

def test_obj_funcs():
"""Series of tests to test all objective functions with fast test data"""
Qobs = np.array([120, 130, 140, 150, 160, 170])
Qsim = np.array([120, 125, 145, 140, 140, 180])
qobs = np.array([120, 130, 140, 150, 160, 170])
qsim = np.array([120, 125, 145, 140, 140, 180])

# Test that the objective function is calculated correctly
objfun = get_objective_function(Qobs, Qsim, obj_func="abs_bias")
objfun = get_objective_function(qobs, qsim, obj_func="abs_bias")
np.testing.assert_array_almost_equal(objfun, 3.3333333333333335, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="abs_pbias")
objfun = get_objective_function(qobs, qsim, obj_func="abs_pbias")
np.testing.assert_array_almost_equal(objfun, 2.2988505747126435, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="abs_volume_error")
objfun = get_objective_function(qobs, qsim, obj_func="abs_volume_error")
np.testing.assert_array_almost_equal(objfun, 0.022988505747126436, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="agreement_index")
objfun = get_objective_function(qobs, qsim, obj_func="agreement_index")
np.testing.assert_array_almost_equal(objfun, 0.9171974522292994, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="bias")
objfun = get_objective_function(qobs, qsim, obj_func="bias")
np.testing.assert_array_almost_equal(objfun, -3.3333333333333335, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="correlation_coeff")
objfun = get_objective_function(qobs, qsim, obj_func="correlation_coeff")
np.testing.assert_array_almost_equal(objfun, 0.8599102447336393, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="kge")
objfun = get_objective_function(qobs, qsim, obj_func="kge")
np.testing.assert_array_almost_equal(objfun, 0.8077187696552522, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="kge_mod")
objfun = get_objective_function(qobs, qsim, obj_func="kge_mod")
np.testing.assert_array_almost_equal(objfun, 0.7888769531580001, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="mae")
objfun = get_objective_function(qobs, qsim, obj_func="mae")
np.testing.assert_array_almost_equal(objfun, 8.333333333333334, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="mare")
objfun = get_objective_function(qobs, qsim, obj_func="mare")
np.testing.assert_array_almost_equal(objfun, 0.05747126436781609, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="mse")
objfun = get_objective_function(qobs, qsim, obj_func="mse")
np.testing.assert_array_almost_equal(objfun, 108.33333333333333, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="nse")
objfun = get_objective_function(qobs, qsim, obj_func="nse")
np.testing.assert_array_almost_equal(objfun, 0.6285714285714286, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="pbias")
objfun = get_objective_function(qobs, qsim, obj_func="pbias")
np.testing.assert_array_almost_equal(objfun, -2.2988505747126435, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="r2")
objfun = get_objective_function(qobs, qsim, obj_func="r2")
np.testing.assert_array_almost_equal(objfun, 0.7394456289978675, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="rmse")
objfun = get_objective_function(qobs, qsim, obj_func="rmse")
np.testing.assert_array_almost_equal(objfun, 10.408329997330663, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="rrmse")
objfun = get_objective_function(qobs, qsim, obj_func="rrmse")
np.testing.assert_array_almost_equal(objfun, 0.07178158618848733, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="rsr")
objfun = get_objective_function(qobs, qsim, obj_func="rsr")
np.testing.assert_array_almost_equal(objfun, 0.6094494002200439, 8)

objfun = get_objective_function(Qobs, Qsim, obj_func="volume_error")
objfun = get_objective_function(qobs, qsim, obj_func="volume_error")
np.testing.assert_array_almost_equal(objfun, -0.022988505747126436, 8)


def test_objective_function_failure_data_length():
"""Test for the objective function calculation failure mode:
Qobs and Qsim length are different
qobs and qsim length are different
"""
with pytest.raises(SystemExit) as pytest_wrapped_e:
with pytest.raises(ValueError) as pytest_wrapped_e:
_ = get_objective_function(
np.array([100, 110]),
np.array([100, 110, 120]),
obj_func="mae",
)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.type == ValueError


def test_objective_function_failure_mask_length():
"""Test for the objective function calculation failure mode:
Qobs and mask length are different
qobs and mask length are different
"""
with pytest.raises(SystemExit) as pytest_wrapped_e:
with pytest.raises(ValueError) as pytest_wrapped_e:
_ = get_objective_function(
np.array([100, 100, 100]),
np.array([100, 110, 120]),
obj_func="mae",
mask=np.array([0, 1, 0, 0]),
)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.type == ValueError


def test_objective_function_failure_unknown_objfun():
"""Test for the objective function calculation failure mode:
Objective function is unknown
"""
with pytest.raises(SystemExit) as pytest_wrapped_e:
with pytest.raises(ValueError) as pytest_wrapped_e:
_ = get_objective_function(
np.array([100, 100, 100]),
np.array([100, 110, 120]),
obj_func="fake",
)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.type == ValueError


def test_objective_function_failure_mask_contents():
"""Test for the objective function calculation failure mode:
Mask contains other than 0 and 1
"""
with pytest.raises(SystemExit) as pytest_wrapped_e:
with pytest.raises(ValueError) as pytest_wrapped_e:
_ = get_objective_function(
np.array([100, 100, 100]),
np.array([100, 110, 120]),
obj_func="mae",
mask=np.array([0, 0.5, 1]),
)
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.type == ValueError


def test_maximizer_objfun_failure_modes_bias():
"""Test for maximize-minimize failure mode:
Use of bias objfun which is unbounded
"""
with pytest.raises(SystemExit) as pytest_wrapped_e:
with pytest.raises(ValueError) as pytest_wrapped_e:
_ = get_objfun_minimize_or_maximize(obj_func="bias")
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.type == ValueError


def test_maximizer_objfun_failure_modes_pbias():
"""Test for maximize-minimize failure mode:
Use of pbias objfun which is unbounded
"""
with pytest.raises(SystemExit) as pytest_wrapped_e:
with pytest.raises(ValueError) as pytest_wrapped_e:
_ = get_objfun_minimize_or_maximize(obj_func="pbias")
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.type == ValueError


def test_maximizer_objfun_failure_modes_volume_error():
"""Test for maximize-minimize failure mode:
Use of volume_error objfun which is unbounded
"""
with pytest.raises(SystemExit) as pytest_wrapped_e:
with pytest.raises(ValueError) as pytest_wrapped_e:
_ = get_objfun_minimize_or_maximize(obj_func="volume_error")
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.type == ValueError


def test_maximizer_objfun_failure_modes_unknown_metric():
"""Test for maximize-minimize failure mode:
Use of unknown objfun
"""
with pytest.raises(SystemExit) as pytest_wrapped_e:
with pytest.raises(NotImplementedError) as pytest_wrapped_e:
_ = get_objfun_minimize_or_maximize(obj_func="unknown_of")
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.type == NotImplementedError
Loading

0 comments on commit 92f75c5

Please sign in to comment.