Skip to content

Commit

Permalink
Feature: individual process models run from separated parameters.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmccreight committed Jun 7, 2023
1 parent 4ba3766 commit 3b085e2
Show file tree
Hide file tree
Showing 23 changed files with 199 additions and 125 deletions.
13 changes: 10 additions & 3 deletions autotest/test_atmosphere.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,16 @@
from pywatershed.parameters import PrmsParameters


@pytest.fixture(scope="function")
def params(domain):
return PrmsParameters.load(domain["param_file"])
@pytest.fixture(scope="function", params=["params_sep", "params_one"])
def params(domain, request):
if request.param == "params_one":
params = PrmsParameters.load(domain["param_file"])
else:
params = PrmsParameters.from_netcdf(
domain["dir"] / "parameters_PRMSAtmosphere.nc"
)

return params


@pytest.fixture(scope="function")
Expand Down
53 changes: 10 additions & 43 deletions autotest/test_canopy.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,16 @@ def test_simple():
return


@pytest.fixture(scope="function")
def params(domain):
return PrmsParameters.load(domain["param_file"])
@pytest.fixture(scope="function", params=["params_sep", "params_one"])
def params(domain, request):
if request.param == "params_one":
params = PrmsParameters.load(domain["param_file"])
else:
params = PrmsParameters.from_netcdf(
domain["dir"] / "parameters_PRMSCanopy.nc"
)

return params


@pytest.fixture(scope="function")
Expand Down Expand Up @@ -136,45 +143,5 @@ def test_compare_prms(domain, control, tmp_path, calc_method):

if not all_success:
raise Exception("pywatershed results do not match prms results")
# is comparing along the way slower or faster than comparing netcdf?

# prms_output_dataframes = {}
# for cv in comparison_variables:
# fname = prms_output_files[cv]
# print(f"loading {fname}")
# csvobj = CsvFile(fname)
# df = csvobj.to_dataframe()
# prms_output_dataframes[cv] = df

# # get a dictionary of dataframes for process model output
# pyws_output_dataframes = cnp.get_output_dataframes()

# # compare prms and pywatershed data
# for cv in comparison_variables:
# prms_data = prms_output_dataframes[cv]
# pyws_data = pyws_output_dataframes[cv]

# print(f"\n{50*'*'}")
# print(f"{cv} min max")
# a1 = prms_data.to_numpy()
# a2 = pyws_data.to_numpy()
# diff = a1 - a2
# diffmin = diff.min()
# diffmax = diff.max()
# print(f"prms {a1.min()} {a1.max()}")
# print(f"pywatershed {a2.min()} {a2.max()}")
# print(f"diff {diffmin} {diffmax}")

# atol = 1.0e-5
# errmsg = f"Canopy variable {cv} does not match to within {atol}"
# assert np.allclose(diffmin, 0.0, atol=atol), errmsg
# assert np.allclose(diffmax, 0.0, atol=atol), errmsg

# # save cnp output as dataframes in temp/domain_name
# saveoutput = False
# if saveoutput:
# pth = pathlib.Path(".", "temp", domain["domain_name"])
# pth.mkdir(parents=True, exist_ok=True)
# cnp.output_to_csv(pth)

return
23 changes: 18 additions & 5 deletions autotest/test_channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,31 @@
calc_methods = ("numpy", "numba", "fortran")


@pytest.fixture(scope="function", params=["params_sep", "params_one"])
def params(domain, request):
if request.param == "params_one":
params = PrmsParameters.load(domain["param_file"])
else:
params = PrmsParameters.from_netcdf(
domain["dir"] / "parameters_PRMSChannel.nc"
)

return params


@pytest.fixture(scope="function")
def control(domain, params):
return Control.load(domain["control_file"], params=params)


@pytest.mark.parametrize("calc_method", calc_methods)
def test_compare_prms(domain, tmp_path, calc_method):
def test_compare_prms(domain, control, tmp_path, calc_method):
if not has_prmschannel_f and calc_method == "fortran":
pytest.skip(
"PRMSChannel fortran code not available, skipping its test."
)

tmp_path = pl.Path(tmp_path)
params = PrmsParameters.load(domain["param_file"])

# Set information from the control file
control = Control.load(domain["control_file"], params=params)

# load csv files into dataframes
output_dir = domain["prms_output_dir"]
Expand Down
23 changes: 18 additions & 5 deletions autotest/test_groundwater.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,31 @@
calc_methods = ("numpy", "numba", "fortran")


@pytest.fixture(scope="function", params=["params_sep", "params_one"])
def params(domain, request):
if request.param == "params_one":
params = PrmsParameters.load(domain["param_file"])
else:
params = PrmsParameters.from_netcdf(
domain["dir"] / "parameters_PRMSGroundwater.nc"
)

return params


@pytest.fixture(scope="function")
def control(domain, params):
return Control.load(domain["control_file"], params=params)


@pytest.mark.parametrize("calc_method", calc_methods)
def test_compare_prms(domain, tmp_path, calc_method):
def test_compare_prms(domain, control, tmp_path, calc_method):
if not has_prmsgroundwater_f and calc_method == "fortran":
pytest.skip(
"PRMSGroundwater fortran code not available, skipping its test."
)

tmp_path = pl.Path(tmp_path)
params = PrmsParameters.load(domain["param_file"])

# Set information from the control file
control = Control.load(domain["control_file"], params=params)

# load csv files into dataframes
output_dir = domain["prms_output_dir"]
Expand Down
16 changes: 10 additions & 6 deletions autotest/test_param_separate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

import numpy as np
import pytest
import xarray as xr

import pywatershed
from pywatershed.base.control import Control
from pywatershed.base.data_model import xr_ds_to_dd
from pywatershed.base.data_model import open_datasetdict
from pywatershed.parameters import PrmsParameters
from pywatershed.utils import separate_domain_params_to_ncdf

Expand Down Expand Up @@ -52,16 +51,21 @@ def test_param_sep(domain, control, use_xr, tmp_path):

# check roundtrip to file and back
for proc_class, proc_file in proc_nc_files.items():
params_file = xr_ds_to_dd(xr.open_dataset(proc_file))
assert set(params_file["data_vars"].keys()) == set(
proc_class.get_parameters()
params_file = open_datasetdict(proc_file)
# some coords in the file may not be in the parameters
coords_not_in_params = set(params_file.variables.keys()).difference(
set(proc_class.get_parameters())
)
# assert that any coords not in the class params are in the file coords
assert not len(
coords_not_in_params.difference(set(params_file["coords"].keys()))
)

# checking dim equality is not necessary, it is covered by the
# metadata check
for param in proc_class.get_parameters():
np.testing.assert_equal(
params_file["data_vars"][param],
params_file.variables[param],
control.params.parameters[param],
)
np.testing.assert_equal(
Expand Down
13 changes: 10 additions & 3 deletions autotest/test_runoff.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,16 @@
calc_methods = ("numpy", "numba")


@pytest.fixture(scope="function")
def params(domain):
return PrmsParameters.load(domain["param_file"])
@pytest.fixture(scope="function", params=["params_sep", "params_one"])
def params(domain, request):
if request.param == "params_one":
params = PrmsParameters.load(domain["param_file"])
else:
params = PrmsParameters.from_netcdf(
domain["dir"] / "parameters_PRMSRunoff.nc"
)

return params


@pytest.fixture(scope="function")
Expand Down
18 changes: 12 additions & 6 deletions autotest/test_snow.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,26 @@
from pywatershed.hydrology.PRMSSnow import PRMSSnow
from pywatershed.parameters import PrmsParameters

calc_methods = ("numpy", "numba")

@pytest.fixture(scope="function")
def params(domain):
return PrmsParameters.load(domain["param_file"])

@pytest.fixture(scope="function", params=["params_sep", "params_one"])
def params(domain, request):
if request.param == "params_one":
params = PrmsParameters.load(domain["param_file"])
else:
params = PrmsParameters.from_netcdf(
domain["dir"] / "parameters_PRMSSnow.nc"
)

return params


@pytest.fixture(scope="function")
def control(domain, params):
return Control.load(domain["control_file"], params=params)


calc_methods = ("numpy", "numba")


@pytest.mark.xfail
@pytest.mark.parametrize("calc_method", calc_methods)
class TestPRMSSnow:
Expand Down
13 changes: 10 additions & 3 deletions autotest/test_soilzone.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,16 @@
calc_methods = ("numpy", "numba")


@pytest.fixture(scope="function")
def params(domain):
return PrmsParameters.load(domain["param_file"])
@pytest.fixture(scope="function", params=["params_sep", "params_one"])
def params(domain, request):
if request.param == "params_one":
params = PrmsParameters.load(domain["param_file"])
else:
params = PrmsParameters.from_netcdf(
domain["dir"] / "parameters_PRMSSoilzone.nc"
)

return params


@pytest.fixture(scope="function")
Expand Down
13 changes: 10 additions & 3 deletions autotest/test_solar_geom.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@
from pywatershed.parameters import PrmsParameters


@pytest.fixture(scope="function")
def params(domain):
return PrmsParameters.load(domain["param_file"])
@pytest.fixture(scope="function", params=["params_sep", "params_one"])
def params(domain, request):
if request.param == "params_one":
params = PrmsParameters.load(domain["param_file"])
else:
params = PrmsParameters.from_netcdf(
domain["dir"] / "parameters_PRMSSolarGeometry.nc"
)

return params


@pytest.fixture(scope="function")
Expand Down
7 changes: 2 additions & 5 deletions pywatershed/atmosphere/PRMSAtmosphere.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,15 +206,12 @@ def _calculate_all_time(self):

@staticmethod
def get_dimensions():
return (
"nhru",
"nmonth",
"ntime",
)
return ("nhru", "nmonth", "ndoy", "ntime")

@staticmethod
def get_parameters():
return (
"doy",
"radadj_intcp",
"radadj_slope",
"tmax_index",
Expand Down
13 changes: 8 additions & 5 deletions pywatershed/atmosphere/PRMSSolarGeometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ def __init__(
netcdf_separate_files: bool = True,
netcdf_output_vars: list = None,
):
# This is a singular case of having a constant parameter dimensions
self.ndoy = doy

budget_type = None
self._set_budget(budget_type)
self.netcdf_output_dir = netcdf_output_dir

# self._time is needed by storageUnit for timeseries arrays
# TODO: this is redundant because the parameter doy is set
# on load of prms file. Could pass the name to use for
# self._time to super or come up with some other work around.
self._time = doy

super().__init__(
Expand Down Expand Up @@ -123,6 +125,7 @@ def get_dimensions() -> tuple:
@staticmethod
def get_parameters() -> tuple:
return (
"doy",
"hru_slope",
"radj_sppt",
"radj_wppt",
Expand Down Expand Up @@ -441,7 +444,7 @@ def _write_netcdf_timeseries(self) -> None:
nc.add_all_data(
var,
self[var].data,
self._time,
self.doy,
time_coord="doy",
)
nc.close()
Expand All @@ -462,7 +465,7 @@ def _write_netcdf_timeseries(self) -> None:
nc.add_all_data(
var,
self[var].data,
self._time,
self.doy,
time_coord="doy",
)

Expand Down
Loading

0 comments on commit 3b085e2

Please sign in to comment.