|
3 | 3 | """ |
4 | 4 |
|
5 | 5 | import numpy as np |
| 6 | +import pytest |
6 | 7 | from modflow_devtools.markers import requires_pkg |
7 | 8 |
|
8 | 9 | import flopy |
9 | 10 | from flopy.discretization import StructuredGrid, UnstructuredGrid, VertexGrid |
| 11 | +from flopy.discretization.grid import Grid |
10 | 12 | from flopy.export.shapefile_utils import model_attributes_to_shapefile, shp2recarray |
11 | 13 | from flopy.utils.crs import get_shapefile_crs |
12 | 14 |
|
@@ -49,6 +51,75 @@ def test_model_attributes_to_shapefile(example_data_path, function_tmpdir): |
49 | 51 | assert shpfile_path.exists() |
50 | 52 |
|
51 | 53 |
|
| 54 | +@requires_pkg("geopandas") |
| 55 | +def test_model_attributes_to_shapefile_modelgrid_kwarg(function_tmpdir): |
| 56 | + """Repro https://github.com/modflowpy/flopy/issues/2744 |
| 57 | +
|
| 58 | + The modelgrid kwarg to model_attributes_to_shapefile should be used as |
| 59 | + the geometry source if provided, overriding the model's own modelgrid. |
| 60 | + """ |
| 61 | + import warnings |
| 62 | + |
| 63 | + nrow, ncol = 3, 4 |
| 64 | + delr = np.ones(ncol) * 10.0 |
| 65 | + delc = np.ones(nrow) * 10.0 |
| 66 | + crs = 26916 |
| 67 | + |
| 68 | + # Model without a DIS package: modelgrid is a bare Grid with no geometry. |
| 69 | + # Without the fix, this reproduces the reported error: |
| 70 | + # TypeError: Grid.to_geodataframe() missing 1 required positional argument: 'features' |
| 71 | + sim = flopy.mf6.MFSimulation(sim_name="test", sim_ws=str(function_tmpdir)) |
| 72 | + gwf = flopy.mf6.ModflowGwf(sim, modelname="test") |
| 73 | + mg = StructuredGrid(delr=delr, delc=delc, nlay=1, crs=crs) |
| 74 | + shpfile = function_tmpdir / "test_no_dis.shp" |
| 75 | + with warnings.catch_warnings(): |
| 76 | + warnings.simplefilter("ignore", DeprecationWarning) |
| 77 | + model_attributes_to_shapefile(shpfile, gwf, modelgrid=mg) |
| 78 | + assert shpfile.exists() |
| 79 | + |
| 80 | + # The error in the issue could also have been avoided by retrieving the |
| 81 | + # modelgrid after attaching the DIS to the model. Before DIS is added, |
| 82 | + # gwf.modelgrid is the bare base Grid class. After DIS is attached, it |
| 83 | + # becomes a StructuredGrid whose to_geodataframe() needs no 'features'. |
| 84 | + sim1 = flopy.mf6.MFSimulation(sim_name="test_b", sim_ws=str(function_tmpdir)) |
| 85 | + gwf1 = flopy.mf6.ModflowGwf(sim1, modelname="test_b") |
| 86 | + assert isinstance(gwf1.modelgrid, Grid) |
| 87 | + flopy.mf6.ModflowGwfdis(gwf1, nlay=1, nrow=nrow, ncol=ncol) |
| 88 | + mg1 = gwf1.modelgrid |
| 89 | + assert isinstance(mg1, StructuredGrid) |
| 90 | + shpfile1 = function_tmpdir / "test_dis_first.shp" |
| 91 | + with warnings.catch_warnings(): |
| 92 | + warnings.simplefilter("ignore", DeprecationWarning) |
| 93 | + model_attributes_to_shapefile( |
| 94 | + shpfile1, gwf1, package_names=["dis"], modelgrid=mg1 |
| 95 | + ) |
| 96 | + assert shpfile1.exists() |
| 97 | + |
| 98 | + # Without a modelgrid kwarg and no DIS, to_geodataframe raises a clear |
| 99 | + # AttributeError rather than the cryptic TypeError about 'features'. |
| 100 | + sim_err = flopy.mf6.MFSimulation(sim_name="test_err", sim_ws=str(function_tmpdir)) |
| 101 | + gwf_err = flopy.mf6.ModflowGwf(sim_err, modelname="test_err") |
| 102 | + with warnings.catch_warnings(): |
| 103 | + warnings.simplefilter("ignore", DeprecationWarning) |
| 104 | + with pytest.raises(AttributeError, match="discretization package"): |
| 105 | + model_attributes_to_shapefile(function_tmpdir / "test_err.shp", gwf_err) |
| 106 | + |
| 107 | + # Model with a DIS package but a different modelgrid passed via kwarg: |
| 108 | + # the kwarg modelgrid's CRS should take precedence. |
| 109 | + sim2 = flopy.mf6.MFSimulation(sim_name="test2", sim_ws=str(function_tmpdir)) |
| 110 | + gwf2 = flopy.mf6.ModflowGwf(sim2, modelname="test2") |
| 111 | + flopy.mf6.ModflowGwfdis(gwf2, nlay=1, nrow=nrow, ncol=ncol) |
| 112 | + |
| 113 | + mg2 = StructuredGrid(delr=delr, delc=delc, nlay=1, crs=crs) |
| 114 | + shpfile2 = function_tmpdir / "test_with_dis.shp" |
| 115 | + with warnings.catch_warnings(): |
| 116 | + warnings.simplefilter("ignore", DeprecationWarning) |
| 117 | + model_attributes_to_shapefile( |
| 118 | + shpfile2, gwf2, package_names=["dis"], modelgrid=mg2 |
| 119 | + ) |
| 120 | + assert shpfile2.exists() |
| 121 | + |
| 122 | + |
52 | 123 | @requires_pkg("geopandas") |
53 | 124 | def test_create_geodataframe( |
54 | 125 | minimal_unstructured_grid_info, minimal_vertex_grid_info, function_tmpdir |
|
0 commit comments