Skip to content

Commit 7db052d

Browse files
committed
make layer column dtype int
- mask result when recarray, return NA when dataframe - update tests/nb
1 parent a3db6cb commit 7db052d

3 files changed

Lines changed: 40 additions & 25 deletions

File tree

.docs/Notebooks/grid_intersection_example.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,13 @@
114114
yoff = 0.0
115115
angrot = 0.0
116116
sgr = fgrid.StructuredGrid(
117-
delc, delr, top=None, botm=None, xoff=xoff, yoff=yoff, angrot=angrot
117+
delc,
118+
delr,
119+
top=np.ones(100).reshape((10, 10)),
120+
botm=np.zeros(100).reshape((1, 10, 10)),
121+
xoff=xoff,
122+
yoff=yoff,
123+
angrot=angrot,
118124
)
119125

120126
# %%

autotest/test_gridintersect.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,10 @@ def test_rect_grid_3d_point_inside():
149149
gr = get_rect_grid(top=2 * np.ones(4).reshape((2, 2)), botm=botm)
150150
ix = GridIntersect(gr)
151151
result = ix.intersect(Point(2.0, 2.0, 0.2), handle_z=False, geo_dataframe=df_toggle)
152-
assert result.cellids[0] == (1, 0)
152+
assert result["cellids"][0] == (1, 0)
153153
result = ix.intersect(Point(2.0, 2.0, 0.2), handle_z=True, geo_dataframe=df_toggle)
154-
assert result.cellids[0] == (1, 0)
155-
assert result.layer[0] == 2.0 # returned as float to allow +/-inf
154+
assert result["cellids"][0] == (1, 0)
155+
assert result["layer"][0] == 2
156156

157157

158158
@requires_pkg("shapely")
@@ -167,7 +167,7 @@ def test_rect_grid_3d_point_above():
167167
assert result.cellids[0] == (1, 0)
168168
result = ix.intersect(Point(2.0, 2.0, 10.0), handle_z=True, geo_dataframe=df_toggle)
169169
assert len(result) == 1
170-
assert np.isfinite(result.layer[0]) is np.False_
170+
assert np.ma.is_masked(result["layer"][0])
171171

172172

173173
# %% test point shapely
@@ -1160,7 +1160,7 @@ def test_rect_grid_multiple_points_array_with_z_points_to_cellids():
11601160
assert result.cellids[0] == (1, 0)
11611161
assert pd.isna(result.cellids[1])
11621162
result = ix.points_to_cellids(pts, handle_z=True)
1163-
assert ~np.isfinite(result.layer[0])
1163+
assert pd.isna(result.layer[0])
11641164
assert pd.isna(result.cellids[1])
11651165

11661166

flopy/utils/gridintersect.py

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,8 @@ def intersect(
197197
handle_z : bool, optional
198198
Method for handling z-dimension in intersection results for point
199199
intersections. Default is False which ignores z-dimension. If True
200-
returns the layer index for each point. Points above the grid
201-
are returned as +np.inf and below the grid as -np.inf.
200+
returns the layer index for each point. Points below/above the grid
201+
are returned as masked values or pd.NA if returned as dataframe.
202202
geo_dataframe : bool, optional
203203
If True, return a geopandas ``GeoDataFrame``, otherwise return a
204204
numpy recarray. Default will be set to True in the future;
@@ -253,10 +253,11 @@ def intersect(
253253
rec,
254254
names="layer",
255255
data=laypos,
256-
dtypes="f8",
256+
dtypes=int,
257257
usemask=False,
258258
asrecarray=True,
259259
)
260+
rec = np.ma.masked_where(rec.layer < 0, rec)
260261

261262
elif shapetype in {
262263
"LineString",
@@ -303,6 +304,7 @@ def intersect(
303304
gpd.GeoDataFrame(rec)
304305
.rename(columns={"ixshapes": "geometry"})
305306
.set_geometry("geometry")
307+
.replace(999999, NA)
306308
)
307309
if self.mfgrid.crs is not None:
308310
gdf = gdf.set_crs(self.mfgrid.crs)
@@ -979,19 +981,24 @@ def points_to_cellids(
979981
shapely point (or multipoint) geometries.
980982
handle_z : bool, optional
981983
Handle z-dimension for points. If True, returns a "layer" column with
982-
the computed layer index for each point (``+inf`` above the grid,
983-
``-inf`` below). Default is False.
984+
the computed layer index for each point (NA is returned where the
985+
points lie above/below the model grid). Default is False.
984986
dataframe : bool, optional
985987
If True, return a ``pandas.DataFrame``; otherwise return a numpy
986988
recarray. Default is True.
987989
988990
Returns
989991
-------
990-
numpy.recarray or pandas.DataFrame
991-
Return intersection results per point. Result includes "cellid", and
992-
"cellids" (legacy result that contains (row, col) tuples for structured
993-
grids). For structured grids result includes "row" and "col" column.
994-
When ``handle_z=True``, result includes a "layer" column.
992+
pandas.DataFrame or numpy.recarray
993+
Grid cell indices per point. Result contains the following
994+
columns:
995+
- cellid: cellid of grid cell containing point
996+
- cellids: legacy column containing (row, col) tuples for structured grids,
997+
or cellids for vertex grids (deprecated, use "cellid" column instead)
998+
And optionally:
999+
- row: row index of intersected grid cell, for structured grids
1000+
- col: column index of intersected grid cell, for structured grids
1001+
- layer: layer index of for points with z-dimension when handle_z is True
9951002
9961003
Notes
9971004
-----
@@ -1052,13 +1059,16 @@ def points_to_cellids(
10521059
rec,
10531060
names="layer",
10541061
data=laypos,
1055-
dtypes=float,
1062+
dtypes=int,
10561063
usemask=False,
10571064
asrecarray=True,
10581065
)
10591066

10601067
if dataframe:
1061-
return DataFrame(rec).replace(-1, NA).set_index("shp_id")
1068+
# replace invalid indices with NA, replace invalid layer with NA
1069+
return (
1070+
DataFrame(rec).replace(-1, NA).replace(999_999, NA).set_index("shp_id")
1071+
)
10621072
return np.ma.masked_where(rec.cellid < 0, rec)
10631073

10641074
@staticmethod
@@ -1266,9 +1276,8 @@ def get_layer_from_z(self, pts, cellids):
12661276
Returns
12671277
-------
12681278
numpy.ndarray
1269-
Array of floats with the layer index for each point. Points above the
1270-
grid are ``+np.inf``; below the grid ``-np.inf``. Non-intersecting points
1271-
are ``np.nan``.
1279+
layer index for each point. Points below/above the grid are returned
1280+
with index -1.
12721281
"""
12731282
z_arr = np.atleast_1d(shapely.get_z(pts))
12741283
mask_valid = cellids >= 0
@@ -1285,10 +1294,10 @@ def get_layer_from_z(self, pts, cellids):
12851294
zb = surface_elevations < z_arr[mask_valid]
12861295
mask_above = zb.all(axis=0)
12871296
mask_below = (~zb).all(axis=0)
1288-
laypos = (np.nanargmax(zb, axis=0) - 1).astype(float)
1289-
laypos[mask_above] = np.inf
1290-
laypos[mask_below] = -np.inf
1291-
laypos_full = np.full_like(z_arr, np.nan, dtype=float)
1297+
laypos = (np.nanargmax(zb, axis=0) - 1).astype(int)
1298+
laypos[mask_above] = -1
1299+
laypos[mask_below] = -1
1300+
laypos_full = np.full_like(z_arr, -1, dtype=int)
12921301
laypos_full[mask_valid] = laypos
12931302
return laypos_full
12941303

0 commit comments

Comments
 (0)