Skip to content

Commit

Permalink
fix(pathlike): fix docstrings and impl, add test for compare fns
Browse files Browse the repository at this point in the history
  • Loading branch information
wpbonelli committed Mar 2, 2023
1 parent d0b83c6 commit 97cdea4
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 61 deletions.
124 changes: 120 additions & 4 deletions autotest/test_compare.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
import os

import numpy as np
import pytest
from modflow_devtools.markers import requires_exe, requires_pkg

from flopy.mf6.utils import MfGrdFile
from flopy.utils.compare import _diffmax, _difftol
from flopy.modflow import (
Modflow,
ModflowBas,
ModflowDis,
ModflowLpf,
ModflowOc,
ModflowPcg,
ModflowWel,
)
from flopy.utils.compare import (
_diffmax,
_difftol,
compare_budget,
compare_heads,
)


def test_diffmax():
Expand Down Expand Up @@ -39,9 +56,108 @@ def test_eval_bud_diff(example_data_path):
# TODO: create/run minimal model, then compare budget files


@pytest.mark.skip(reason="todo")
def test_compare_budget():
pass
@pytest.fixture
def comparison_model_1(function_tmpdir):
nlay = 3
nrow = 3
ncol = 3
model_name = "t1"

ml = Modflow(
modelname=model_name,
model_ws=function_tmpdir,
verbose=True,
exe_name="mf2005",
)
dis = ModflowDis(
ml, nlay=nlay, nrow=nrow, ncol=ncol, top=0, botm=[-1.0, -2.0, -3.0]
)
ibound = np.ones((nlay, nrow, ncol), dtype=int)
ibound[0, 1, 1] = 0
ibound[0, 0, -1] = -1
bas = ModflowBas(ml, ibound=ibound)
lpf = ModflowLpf(ml, ipakcb=102)
wd = ModflowWel.get_empty(ncells=2, aux_names=["v1", "v2"])
wd["k"][0] = 2
wd["i"][0] = 2
wd["j"][0] = 2
wd["flux"][0] = -1000.0
wd["v1"][0] = 1.0
wd["v2"][0] = 2.0
wd["k"][1] = 2
wd["i"][1] = 1
wd["j"][1] = 1
wd["flux"][1] = -500.0
wd["v1"][1] = 200.0
wd["v2"][1] = 100.0
wel_data = {0: wd}
wel = ModflowWel(ml, stress_period_data=wel_data, dtype=wd.dtype)
oc = ModflowOc(ml)
pcg = ModflowPcg(ml)

ml.write_input()

# run the modflow-2005 model
success, buff = ml.run_model(silent=False)
assert success, "could not run MODFLOW-2005 model"

# load the model
m = Modflow.load(
f"{model_name}.nam",
model_ws=function_tmpdir,
verbose=True,
exe_name="mf2005",
)

wl = m.wel.stress_period_data[0]
assert np.array_equal(wel.stress_period_data[0], wl), (
"previous well package stress period data does not match "
"stress period data loaded."
)

# change model work space
pth = os.path.join(function_tmpdir, "flopy")
m.change_model_ws(new_pth=pth)

# remove the existing well package
m.remove_package("WEL")

# recreate well package with binary output
wel = ModflowWel(
m, stress_period_data=wel_data, binary=True, dtype=wd.dtype
)

m.write_input()

fn1 = function_tmpdir / "flopy" / f"{model_name}.nam"
fn0 = function_tmpdir / f"{model_name}.nam"
fhsum = function_tmpdir / f"{os.path.splitext(model_name)[0]}.head.out"
fbsum = function_tmpdir / f"{os.path.splitext(model_name)[0]}.budget.out"

return m, fn1, fn0, fhsum, fbsum


@requires_exe("mf2005")
def test_compare_budget_and_heads(comparison_model_1):
m, fn1, fn0, fhsum, fbsum = comparison_model_1
success, buff = m.run_model()
assert success, "could not run the new MODFLOW-2005 model"

# compare the files
assert compare_heads(
fn0, fn1, outfile=fhsum
), "head comparison failure (pathlib.Path)"
assert compare_heads(
str(fn0), str(fn1), outfile=fhsum
), "head comparison failure (str path)"
assert compare_budget(
fn0, fn1, max_incpd=0.1, max_cumpd=0.1, outfile=fbsum
), "budget comparison failure (pathlib.Path)"
assert compare_budget(
str(fn0), str(fn1), max_incpd=0.1, max_cumpd=0.1, outfile=str(fbsum)
), "budget comparison failure (str path)"

# todo test with files1 and files2 arguments


@pytest.mark.skip(reason="todo")
Expand Down
6 changes: 3 additions & 3 deletions flopy/export/shapefile_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ def write_grid_shapefile(
value to fill nans
epsg : str, int
epsg code
prj : str or PathLike
prj : str or PathLike, optional, default None
projection file path
verbose : bool
verbose : bool, default False
whether to print verbose output
Returns
Expand Down Expand Up @@ -234,7 +234,7 @@ def model_attributes_to_shapefile(
array_dict : dict of {name:2D array} pairs
Additional 2D arrays to add as attributes to the shapefile.
(default is None)
verbose : bool
verbose : bool, optional, default False
whether to print verbose output
**kwargs : keyword arguments
modelgrid : fp.modflow.Grid object
Expand Down
37 changes: 26 additions & 11 deletions flopy/export/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import os
from typing import Union
from typing import Optional, Union

import numpy as np

Expand Down Expand Up @@ -1516,6 +1516,8 @@ def export_array(
fieldname : str
Attribute field name for array values (shapefile export only).
(default 'values')
verbose : bool, optional, default False
whether to show verbose output
kwargs:
keyword arguments to np.savetxt (ascii)
rasterio.open (GeoTIFF)
Expand Down Expand Up @@ -1662,7 +1664,8 @@ def export_contours(
contours,
fieldname="level",
epsg=None,
prj=None,
prj: Optional[Union[str, os.PathLike]] = None,
verbose=False,
**kwargs,
):
"""
Expand All @@ -1678,8 +1681,10 @@ def export_contours(
gis attribute table field name
epsg : int
EPSG code. See https://www.epsg-registry.org/ or spatialreference.org
prj : str
prj : str or PathLike, optional, default None
Existing projection file to be used with new shapefile.
verbose : bool, optional, default False
whether to show verbose output
**kwargs : key-word arguments to flopy.export.shapefile_utils.recarray2shp
Returns
Expand All @@ -1705,15 +1710,17 @@ def export_contours(
# convert the dictionary to a recarray
ra = np.array(level, dtype=[(fieldname, float)]).view(np.recarray)

recarray2shp(ra, geoms, filename, epsg=epsg, prj=prj, **kwargs)
recarray2shp(
ra, geoms, filename, epsg=epsg, prj=prj, verbose=verbose, **kwargs
)


def export_contourf(
filename: Union[str, os.PathLike],
contours,
fieldname="level",
epsg=None,
prj=None,
prj: Optional[Union[str, os.PathLike]] = None,
verbose=False,
**kwargs,
):
Expand All @@ -1732,8 +1739,10 @@ def export_contourf(
the range represented by the polygon. Default is 'level'.
epsg : int
EPSG code. See https://www.epsg-registry.org/ or spatialreference.org
prj : str
prj : str or PathLike, optional, default None
Existing projection file to be used with new shapefile.
verbose : bool, optional, default False
whether to show verbose output
**kwargs : keyword arguments to flopy.export.shapefile_utils.recarray2shp
Expand Down Expand Up @@ -1800,7 +1809,9 @@ def export_contourf(
# Create recarray
ra = np.array(level, dtype=[(fieldname, float)]).view(np.recarray)

recarray2shp(ra, geoms, filename, epsg=epsg, prj=prj, **kwargs)
recarray2shp(
ra, geoms, filename, epsg=epsg, prj=prj, verbose=verbose, **kwargs
)


def export_array_contours(
Expand All @@ -1812,7 +1823,8 @@ def export_array_contours(
levels=None,
maxlevels=1000,
epsg=None,
prj=None,
prj: Optional[Union[str, os.PathLike]] = None,
verbose=False,
**kwargs,
):
"""
Expand All @@ -1836,8 +1848,10 @@ def export_array_contours(
maximum number of contour levels
epsg : int
EPSG code. See https://www.epsg-registry.org/ or spatialreference.org
prj : str
prj : str or PathLike, optional, default None
Existing projection file to be used with new shapefile.
verbose : bool, optional, default False
whether to show verbose output
**kwargs : keyword arguments to flopy.export.shapefile_utils.recarray2shp
"""
Expand All @@ -1857,7 +1871,9 @@ def export_array_contours(
levels = np.arange(imin, imax, interval)
ax = plt.subplots()[-1]
ctr = contour_array(modelgrid, ax, a, levels=levels)
export_contours(filename, ctr, fieldname, epsg, prj, **kwargs)
export_contours(
filename, ctr, fieldname, epsg, prj, verbose=verbose, **kwargs
)
plt.close()


Expand All @@ -1871,7 +1887,6 @@ def contour_array(modelgrid, ax, a, **kwargs):
modelgrid object
ax : matplotlib.axes.Axes
ax to add the contours
a : np.ndarray
array to contour
Expand Down
11 changes: 8 additions & 3 deletions flopy/mbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,7 @@ def __getattr__(self, item):

def get_ext_dict_attr(
self,
ext_unit_dict: Union[str, os.PathLike] = None,
ext_unit_dict=None,
unit=None,
filetype=None,
pop_key=True,
Expand Down Expand Up @@ -725,7 +725,7 @@ def _output_msg(self, i, add=True):
def add_output_file(
self,
unit,
fname: Union[str, os.PathLike] = None,
fname: Optional[Union[str, os.PathLike]] = None,
extension="cbc",
binflag=True,
package=None,
Expand Down Expand Up @@ -808,6 +808,7 @@ def add_output(
binary or not. (default is False)
"""
fname = str(fname)
if fname in self.output_fnames:
if self.verbose:
print(
Expand All @@ -834,7 +835,7 @@ def add_output(
self._output_msg(-1, add=True)

def remove_output(
self, fname: Union[str, os.PathLike, None] = None, unit=None
self, fname: Optional[Union[str, os.PathLike]] = None, unit=None
):
"""
Remove an output file from the model by specifying either the
Expand All @@ -848,6 +849,7 @@ def remove_output(
Unit number of output array
"""
if fname is not None:
fname = str(fname)
for i, e in enumerate(self.output_fnames):
if fname in e:
if self.verbose:
Expand Down Expand Up @@ -883,6 +885,7 @@ def get_output(
unit : int, optional
Unit number of output array
"""
fname = str(fname)
if fname is not None:
for i, e in enumerate(self.output_fnames):
if fname in e:
Expand Down Expand Up @@ -917,6 +920,7 @@ def set_output_attribute(
"""
idx = None
if fname is not None:
fname = str(fname)
for i, e in enumerate(self.output_fnames):
if fname in e:
idx = i
Expand Down Expand Up @@ -1717,6 +1721,7 @@ def run_model(
normal_msg[idx] = s.lower()

# Check to make sure that program and namefile exist
exe_name = str(Path(exe_name).expanduser().absolute())
exe = which(exe_name)
if exe is None:
if exe_name.lower().endswith(".exe"):
Expand Down
2 changes: 1 addition & 1 deletion flopy/mf6/mfbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class MFFileMgmt:
Parameters
----------
path : str
path : str or PathLike
Path on disk to the simulation
Attributes
Expand Down
8 changes: 4 additions & 4 deletions flopy/mf6/modflow/mfsimulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -951,7 +951,7 @@ def check(
Parameters
----------
f : str or PathLike
f : str or PathLike, optional
String defining file name or file handle for summary file
of check method output. If str or pathlike, a file handle
is created. If None, the method does not write results to
Expand Down Expand Up @@ -2455,7 +2455,7 @@ def _is_in_solution_group(self, item, index, any_idx_after=False):

def plot(
self,
model_list: Union[str, List[str]] = None,
model_list: Optional[Union[str, List[str]]] = None,
SelPackList=None,
**kwargs,
):
Expand All @@ -2467,9 +2467,9 @@ def plot(
Parameters
----------
model_list: (list)
model_list: list, optional
List of model names to plot, if none all models will be plotted
SelPackList: (list)
SelPackList: list, optional
List of package names to plot, if none all packages will be
plotted
kwargs:
Expand Down
Loading

0 comments on commit 97cdea4

Please sign in to comment.