Skip to content

Commit

Permalink
Merge pull request #2323 from modflowpy/v3.8.2
Browse files Browse the repository at this point in the history
Release 3.8.2
  • Loading branch information
wpbonelli authored Oct 3, 2024
2 parents 1eaab1c + 7ddfa3c commit 70339c3
Show file tree
Hide file tree
Showing 15 changed files with 163 additions and 62 deletions.
9 changes: 9 additions & 0 deletions .docs/md/version_changes.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
# Changelog
### Version 3.8.2

#### Bug fixes

* [fix(mp7particledata)](https://github.com/modflowpy/flopy/commit/a0e9219407b7be208d38f4f902cd2b5b96da1351): Fix get_extent() vertical extent calculation (#2307). Committed by wpbonelli on 2024-09-12.
* [fix(array3d_export)](https://github.com/modflowpy/flopy/commit/693f01a0ce41f08d05395832b540fcc4f7dcff43): Fix exporting of array3d to shp (#2310). Committed by martclanor on 2024-09-16.
* [fix(binaryfile)](https://github.com/modflowpy/flopy/commit/181e101a605bdb9b628c6781abff7b3276aca635): Accommodate windows drives for in-place reversal (#2312). Committed by wpbonelli on 2024-09-16.
* [fix(get_modflow)](https://github.com/modflowpy/flopy/commit/38180335445fa09f5463cf8b9239e6ed0c10bf5b): Accommodate missing ratelimit info on api response (#2320). Committed by wpbonelli on 2024-10-01.

### Version 3.8.1

#### New features
Expand Down
4 changes: 2 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ message: If you use this software, please cite both the article from preferred-c
references, and the software itself.
type: software
title: FloPy
version: 3.8.1
date-released: '2024-09-05'
version: 3.8.2
date-released: '2024-10-03'
doi: 10.5066/F7BK19FH
abstract: A Python package to create, run, and post-process MODFLOW-based models.
repository-artifact: https://pypi.org/project/flopy
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

<img src="https://raw.githubusercontent.com/modflowpy/flopy/master/examples/images/flopy3.png" alt="flopy3" style="width:50;height:20">

### Version 3.8.1
### Version 3.8.2
[![flopy continuous integration](https://github.com/modflowpy/flopy/actions/workflows/commit.yml/badge.svg?branch=develop)](https://github.com/modflowpy/flopy/actions/workflows/commit.yml)
[![Read the Docs](https://github.com/modflowpy/flopy/actions/workflows/rtd.yml/badge.svg?branch=develop)](https://github.com/modflowpy/flopy/actions/workflows/rtd.yml)

Expand Down Expand Up @@ -150,7 +150,7 @@ How to Cite

##### ***Software/Code citation for FloPy:***

[Bakker, Mark, Post, Vincent, Hughes, J. D., Langevin, C. D., White, J. T., Leaf, A. T., Paulinski, S. R., Bellino, J. C., Morway, E. D., Toews, M. W., Larsen, J. D., Fienen, M. N., Starn, J. J., Brakenhoff, D. A., and Bonelli, W. P., 2024, FloPy v3.8.1: U.S. Geological Survey Software Release, 05 September 2024, https://doi.org/10.5066/F7BK19FH](https://doi.org/10.5066/F7BK19FH)
[Bakker, Mark, Post, Vincent, Hughes, J. D., Langevin, C. D., White, J. T., Leaf, A. T., Paulinski, S. R., Bellino, J. C., Morway, E. D., Toews, M. W., Larsen, J. D., Fienen, M. N., Starn, J. J., Brakenhoff, D. A., and Bonelli, W. P., 2024, FloPy v3.8.2: U.S. Geological Survey Software Release, 03 October 2024, https://doi.org/10.5066/F7BK19FH](https://doi.org/10.5066/F7BK19FH)


Additional FloPy Related Publications
Expand Down
68 changes: 63 additions & 5 deletions autotest/test_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,6 @@ def test_export_shapefile_polygon_closed(function_tmpdir):
shp.close()


@excludes_platform("Windows")
@requires_pkg("rasterio", "pyshp", "scipy", name_map={"pyshp": "shapefile"})
def test_export_array(function_tmpdir, example_data_path):
import rasterio
Expand Down Expand Up @@ -467,10 +466,10 @@ def test_export_array(function_tmpdir, example_data_path):
with rasterio.open(function_tmpdir / "fb.tif") as src:
arr = src.read(1)
assert src.shape == (m.nrow, m.ncol)
# TODO: these tests currently fail -- fix is in progress
# assert np.abs(src.bounds[0] - m.modelgrid.extent[0]) < 1e-6
# assert np.abs(src.bounds[1] - m.modelgrid.extent[1]) < 1e-6
pass
assert np.abs(src.bounds[0] - m.modelgrid.extent[0]) < 1e-6
assert np.abs(src.bounds[2] - m.modelgrid.extent[1]) < 1e-6
assert np.abs(src.bounds[1] - m.modelgrid.extent[2]) < 1e-6
assert np.abs(src.bounds[3] - m.modelgrid.extent[3]) < 1e-6


@requires_pkg("netCDF4", "pyproj")
Expand Down Expand Up @@ -646,6 +645,65 @@ def test_export_array2(function_tmpdir):
assert os.path.isfile(filename), "did not create array shapefile"


@pytest.mark.mf6
@requires_pkg("pyshp", name_map={"pyshp": "shapefile"})
def test_array3d_export_structured(function_tmpdir):
from shapefile import Reader

xll, yll = 468970, 3478635
xur, yur = 681010, 3716462
spacing = 20000
ncol = int((xur - xll) / spacing)
nrow = int((yur - yll) / spacing)
sim = flopy.mf6.MFSimulation("sim", sim_ws=function_tmpdir)
gwf = flopy.mf6.ModflowGwf(
sim,
modelname="array3d_export_unstructured",
)
flopy.mf6.ModflowGwfdis(
gwf,
nlay=3,
top=5,
botm=[4, 3, 2],
delr=spacing,
delc=spacing,
nrow=nrow,
ncol=ncol,
)

shp_file = os.path.join(function_tmpdir, "dis_botm.shp")
gwf.dis.botm.export(shp_file)

with Reader(shp_file) as shp:
assert list(shp.shapeRecord(-1).record) == [
110, # node
11, # row
10, # column
4.0, # botm_1
3.0, # botm_2
2.0, # botm_3
]


@requires_pkg("pyshp", name_map={"pyshp": "shapefile"})
def test_array3d_export_unstructured(function_tmpdir):
from shapefile import Reader

name = "array3d_export_unstructured"
sim = disu_sim(name, function_tmpdir)
gwf = sim.get_model(name)

shp_file = function_tmpdir / "disu_bot.shp"
gwf.disu.bot.export(shp_file)

with Reader(shp_file) as shp:
assert list(shp.shapeRecord(-1).record) == [
1770, # node
3, # layer
0.0, # bot
]


@requires_pkg("pyshp", "shapely", name_map={"pyshp": "shapefile"})
def test_export_array_contours_structured(function_tmpdir):
nrow = 7
Expand Down
15 changes: 15 additions & 0 deletions autotest/test_particledata.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
ParticleGroupLRCTemplate,
ParticleGroupNodeTemplate,
)
from flopy.modpath.mp7particledata import get_extent
from flopy.modpath.mp7particlegroup import ParticleGroup
from flopy.utils.modpathfile import EndpointFile, PathlineFile

Expand All @@ -47,6 +48,20 @@ def flatten(a):
]


# test get_extent()


def test_get_extent_structured_multilayer():
grid = GridCases().structured_small()
i, j = 1, 2
for k in range(grid.nlay):
extent = get_extent(grid, k=k, i=i, j=j)
assert extent.minz == grid.botm[k, i, j]
assert extent.maxz == (
grid.top[i, j] if k == 0 else grid.botm[k - 1, i, j]
)


# test initializers


Expand Down
2 changes: 1 addition & 1 deletion docs/PyPI_release.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ How to Cite

*Software/Code citation for FloPy:*

[Bakker, Mark, Post, Vincent, Hughes, J. D., Langevin, C. D., White, J. T., Leaf, A. T., Paulinski, S. R., Bellino, J. C., Morway, E. D., Toews, M. W., Larsen, J. D., Fienen, M. N., Starn, J. J., Brakenhoff, D. A., and Bonelli, W. P., 2024, FloPy v3.8.1: U.S. Geological Survey Software Release, 05 September 2024, https://doi.org/10.5066/F7BK19FH](https://doi.org/10.5066/F7BK19FH)
[Bakker, Mark, Post, Vincent, Hughes, J. D., Langevin, C. D., White, J. T., Leaf, A. T., Paulinski, S. R., Bellino, J. C., Morway, E. D., Toews, M. W., Larsen, J. D., Fienen, M. N., Starn, J. J., Brakenhoff, D. A., and Bonelli, W. P., 2024, FloPy v3.8.2: U.S. Geological Survey Software Release, 03 October 2024, https://doi.org/10.5066/F7BK19FH](https://doi.org/10.5066/F7BK19FH)
26 changes: 16 additions & 10 deletions flopy/export/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1207,16 +1207,22 @@ def array3d_export(f: Union[str, os.PathLike], u3d, fmt=None, **kwargs):
f
).suffix.lower() == ".shp":
array_dict = {}
for ilay in range(modelgrid.nlay):
u2d = u3d[ilay]
if isinstance(u2d, np.ndarray):
dname = u3d.name
array = u2d
else:
dname = u2d.name
array = u2d.array
name = f"{shapefile_utils.shape_attr_name(dname)}_{ilay + 1}"
array_dict[name] = array
array_shape = u3d.array.shape

if len(array_shape) == 1:
name = shapefile_utils.shape_attr_name(u3d.name)
array_dict[name] = u3d.array
else:
for ilay in range(array_shape[0]):
u2d = u3d[ilay]
if isinstance(u2d, np.ndarray):
dname = u3d.name
array = u2d
else:
dname = u2d.name
array = u2d.array
name = f"{shapefile_utils.shape_attr_name(dname)}_{ilay + 1}"
array_dict[name] = array
shapefile_utils.write_grid_shapefile(f, modelgrid, array_dict)

elif isinstance(f, NetCdf) or isinstance(f, dict):
Expand Down
9 changes: 8 additions & 1 deletion flopy/modpath/mp7particledata.py
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,14 @@ def get_extent(grid, k=None, i=None, j=None, nn=None, localz=False) -> Extent:
# get cell coords and span in each dimension
if not (k is None or i is None or j is None):
verts = grid.get_cell_vertices(i, j)
minz, maxz = (0, 1) if localz else (grid.botm[k, i, j], grid.top[i, j])
minz, maxz = (
(0, 1)
if localz
else (
grid.botm[k, i, j],
grid.top[i, j] if k == 0 else grid.botm[k - 1, i, j],
)
)
elif nn is not None:
verts = grid.get_cell_vertices(nn)
if grid.grid_type == "structured":
Expand Down
66 changes: 35 additions & 31 deletions flopy/utils/binaryfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import tempfile
import warnings
from pathlib import Path
from shutil import move
from typing import List, Optional, Union

import numpy as np
Expand Down Expand Up @@ -460,9 +461,9 @@ class BinaryLayerFile(LayerFile):
"""

def __init__(
self, filename: Union[str, os.PathLike], precision, verbose, kwargs
self, filename: Union[str, os.PathLike], precision, verbose, **kwargs
):
super().__init__(filename, precision, verbose, kwargs)
super().__init__(filename, precision, verbose, **kwargs)

def _build_index(self):
"""
Expand Down Expand Up @@ -661,7 +662,7 @@ def __init__(
self.header_dtype = BinaryHeader.set_dtype(
bintype="Head", precision=precision
)
super().__init__(filename, precision, verbose, kwargs)
super().__init__(filename, precision, verbose, **kwargs)

def reverse(self, filename: Optional[os.PathLike] = None):
"""
Expand Down Expand Up @@ -733,10 +734,18 @@ def reverse_header(header):
header["pertim"] = perlen - header["pertim"]
return header

# reverse record order and write to temporary file
temp_dir_path = Path(tempfile.gettempdir())
temp_file_path = temp_dir_path / filename.name
with open(temp_file_path, "wb") as f:
target = filename

# if rewriting the same file, write
# temp file then copy it into place
inplace = filename == self.filename
if inplace:
temp_dir_path = Path(tempfile.gettempdir())
temp_file_path = temp_dir_path / filename.name
target = temp_file_path

# reverse record order
with open(target, "wb") as f:
for i in range(len(self) - 1, -1, -1):
header = self.recordarray[i].copy()
header = reverse_header(header)
Expand All @@ -752,16 +761,10 @@ def reverse_header(header):
ilay=ilay,
)

# if we're rewriting the original file, close it first
if filename == self.filename:
self.close()

# move temp file to destination
temp_file_path.replace(filename)

# if we rewrote the original file, reinitialize
if filename == self.filename:
super().__init__(self.filename, self.precision, self.verbose, {})
if inplace:
move(target, filename)
super().__init__(filename, self.precision, self.verbose)


class UcnFile(BinaryLayerFile):
Expand Down Expand Up @@ -828,7 +831,7 @@ def __init__(
self.header_dtype = BinaryHeader.set_dtype(
bintype="Ucn", precision=precision
)
super().__init__(filename, precision, verbose, kwargs)
super().__init__(filename, precision, verbose, **kwargs)
return


Expand Down Expand Up @@ -898,7 +901,7 @@ def __init__(
self.header_dtype = BinaryHeader.set_dtype(
bintype="Head", precision=precision
)
super().__init__(filename, precision, verbose, kwargs)
super().__init__(filename, precision, verbose, **kwargs)

def _get_data_array(self, totim=0.0):
"""
Expand Down Expand Up @@ -2325,10 +2328,17 @@ def reverse(self, filename: Optional[os.PathLike] = None):
# get number of records
nrecords = len(self)

# open backward budget file
temp_dir_path = Path(tempfile.gettempdir())
temp_file_path = temp_dir_path / filename.name
with open(temp_file_path, "wb") as f:
target = filename

# if rewriting the same file, write
# temp file then copy it into place
inplace = filename == self.filename
if inplace:
temp_dir_path = Path(tempfile.gettempdir())
temp_file_path = temp_dir_path / filename.name
target = temp_file_path

with open(target, "wb") as f:
# loop over budget file records in reverse order
for idx in range(nrecords - 1, -1, -1):
# load header array
Expand Down Expand Up @@ -2415,13 +2425,7 @@ def reverse(self, filename: Optional[os.PathLike] = None):
# Write data
data.tofile(f)

# if we're rewriting the original file, close it first
if filename == self.filename:
self.close()

# move temp file to destination
temp_file_path.replace(filename)

# if we rewrote the original file, reinitialize
if filename == self.filename:
self.__init__(self.filename, self.precision, self.verbose)
if inplace:
move(target, filename)
self.__init__(filename, self.precision, self.verbose)
2 changes: 1 addition & 1 deletion flopy/utils/datafile.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class LayerFile:
"""

def __init__(
self, filename: Union[str, os.PathLike], precision, verbose, kwargs
self, filename: Union[str, os.PathLike], precision, verbose, **kwargs
):
from ..discretization.structuredgrid import StructuredGrid

Expand Down
4 changes: 3 additions & 1 deletion flopy/utils/datautil.py
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,9 @@ def build_list(self, callback):
(entry_point[0][-1], new_location)
)
else:
entry_point[0].append(callback(entry_point[1]))
entry_point[0].append(
callback(tuple(i + val for i in entry_point[1]))
)
entry_points = new_entry_points

def first_item(self):
Expand Down
6 changes: 3 additions & 3 deletions flopy/utils/formattedfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ class FormattedLayerFile(LayerFile):
"""

def __init__(self, filename, precision, verbose, kwargs):
super().__init__(filename, precision, verbose, kwargs)
def __init__(self, filename, precision, verbose, **kwargs):
super().__init__(filename, precision, verbose, **kwargs)

def _build_index(self):
"""
Expand Down Expand Up @@ -376,7 +376,7 @@ def __init__(
**kwargs,
):
self.text = text
super().__init__(filename, precision, verbose, kwargs)
super().__init__(filename, precision, verbose, **kwargs)

def _get_text_header(self):
"""
Expand Down
4 changes: 2 additions & 2 deletions flopy/utils/get_modflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ def get_release(owner=None, repo=None, tag="latest", quiet=False) -> dict:
try:
with urllib.request.urlopen(request, timeout=10) as resp:
result = resp.read()
remaining = int(resp.headers["x-ratelimit-remaining"])
if remaining <= 10:
remaining = resp.headers.get("x-ratelimit-remaining", None)
if remaining and int(remaining) <= 10:
warnings.warn(
f"Only {remaining} GitHub API requests remaining "
"before rate-limiting"
Expand Down
Loading

0 comments on commit 70339c3

Please sign in to comment.