Skip to content

Commit f8810c2

Browse files
authored
refactor(gridintersect): clean up gridintersect (#2346)
This PR addresses #2344 and does the following: * Add DeprecationWarning when method != "vertex" * Remove all Shapely<2.0 code * Remove warnings filters for older numpy versions * Mark methods/tests that should be removed when method="structured" is officially removed * Ensure full test suite is maintained after removal of structured tests. * Move raster tests to a separate file. * Add option to return intersection results as (Geo)DataFrame * Allow plotting options to take as input GeoDataFrame (bit unnecessary as they have their own plotting logic) and improve plotting results. * Add plot_intersection_result() to plot result + modelgrid (optional). * Update example notebook. Note: Tests for 3D point intersections above/inside grid are deactivated. This is not yet working for method="vertex". Will probably be added in a separate PR.
1 parent 370efbf commit f8810c2

File tree

6 files changed

+594
-935
lines changed

6 files changed

+594
-935
lines changed

.docs/Notebooks/grid_intersection_example.py

Lines changed: 21 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@
6060
print(sys.version)
6161
print(f"numpy version: {np.__version__}")
6262
print(f"matplotlib version: {mpl.__version__}")
63-
print(f"flopy version: {flopy.__version__}")
6463
print(f"shapely version: {shapely.__version__}")
64+
print(f"flopy version: {flopy.__version__}")
6565
# -
6666

6767
# ## <a id="gridclass"></a>[GridIntersect Class](#top)
@@ -70,23 +70,14 @@
7070
# the constructor. There are options users can select to change how the
7171
# intersection is calculated.
7272
#
73-
# - `method`: derived from model grid type or defined by the user: can be either `"vertex"` or
74-
# `"structured"`. If `"structured"` is passed, the intersections are performed
75-
# using structured methods. These methods use information about the regular grid
76-
# to limit the search space for intersection calculations. Note that `method="vertex"`
77-
# also works for structured grids.
78-
# - `rtree`: either `True` (default) or `False`, only read when
79-
# `method="vertex"`. When True, an STR-tree is built, which allows for fast
80-
# spatial queries. Building the STR-tree does take some time however. Setting the
81-
# option to False avoids building the STR-tree but requires the intersection
82-
# calculation to loop through all grid cells.
83-
#
84-
# In general the "vertex" option is robust and fast and is therefore recommended
85-
# in most situations. In some rare cases building the STR-tree might not be worth
86-
# the time, in which case it can be avoided by passing `rtree=False`. If you are
87-
# working with a structured grid, then the `method="structured"` can speed up
88-
# intersection operations in some situations (e.g. for (multi)points) with the added
89-
# advantage of not having to build an STR-tree.
73+
# - `rtree`: either `True` (default) or `False`. When True, an STR-tree is built,
74+
# which allows for fast spatial queries. Building the STR-tree takes some
75+
# time however. Setting the option to False avoids building the STR-tree but requires
76+
# the intersection calculation to loop through all grid cells. It is generally
77+
# recommended to set this option to True.
78+
# - `local`: either `False` (default) or `True`. When True the local model coordinates
79+
# are used. When False, real-world coordinates are used. Can be useful if shapes are
80+
# defined in local coordinates.
9081
#
9182
# The important methods in the GridIntersect object are:
9283
#
@@ -96,9 +87,7 @@
9687
# - `intersect()`: for intersecting the modelgrid with point, linestrings, and
9788
# polygon geometries (accepts shapely geometry objects, flopy geometry object,
9889
# shapefile.Shape objects, and geojson objects)
99-
# - `plot_point()`: for plotting point intersection results
100-
# - `plot_linestring()`: for plotting linestring intersection results
101-
# - `plot_polygon()`: for plotting polygon intersection results
90+
# - `ix.plot_intersection_result()`: for plotting intersection results
10291
#
10392
# In the following sections examples of intersections are shown for structured
10493
# and vertex grids for different types of shapes (Polygon, LineString and Point).
@@ -133,8 +122,8 @@
133122
holes=[[(25, 25), (25, 45), (45, 45), (45, 25)]],
134123
)
135124

136-
# Create the GridIntersect class for our modelgrid. The `method` kwarg is passed to force GridIntersect to use the `"vertex"` intersection methods.
137-
125+
# Create the GridIntersect class for our modelgrid.
126+
# TODO: remove method kwarg in v3.9.0
138127
ix = GridIntersect(sgr, method="vertex")
139128

140129
# Do the intersect operation for a polygon
@@ -151,7 +140,7 @@
151140
# Looking at the first few entries of the results of the polygon intersection (convert to pandas.DataFrame for prettier formatting)
152141

153142
result[:5]
154-
# pd.DataFrame(result) # recommended for prettier formatting and working with result
143+
# pd.DataFrame(result).head()
155144

156145
# The cellids can be easily obtained
157146

@@ -165,18 +154,14 @@
165154

166155
ix.intersects(p)
167156

168-
# The results of an intersection can be visualized with the plotting methods in the `GridIntersect` object:
169-
# - `plot_polygon`
170-
# - `plot_linestring`
171-
# - `plot_point`
157+
# The results of an intersection can be visualized with the `GridIntersect.plot_intersection_result()` method.
172158

173159
# +
174160
# create a figure and plot the grid
175161
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
176-
sgr.plot(ax=ax)
177162

178163
# the intersection object contains some helpful plotting commands
179-
ix.plot_polygon(result, ax=ax)
164+
ix.plot_intersection_result(result, ax=ax)
180165

181166
# add black x at cell centers
182167
for irow, icol in result.cellids:
@@ -205,12 +190,8 @@
205190

206191
result2 = ix.intersect(p, contains_centroid=True)
207192

208-
# create a figure and plot the grid
209193
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
210-
sgr.plot(ax=ax)
211-
212-
# the intersection object contains some helpful plotting commands
213-
ix.plot_polygon(result2, ax=ax)
194+
ix.plot_intersection_result(result2, ax=ax)
214195

215196
# add black x at cell centers
216197
for irow, icol in result2.cellids:
@@ -232,12 +213,8 @@
232213

233214
result3 = ix.intersect(p, min_area_fraction=0.35)
234215

235-
# create a figure and plot the grid
236216
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
237-
sgr.plot(ax=ax)
238-
239-
# the intersection object contains some helpful plotting commands
240-
ix.plot_polygon(result3, ax=ax)
217+
ix.plot_intersection_result(result3, ax=ax)
241218

242219
# add black x at cell centers
243220
for irow, icol in result3.cellids:
@@ -247,35 +224,6 @@
247224
"kx",
248225
label="centroids of intersected gridcells",
249226
)
250-
251-
# add legend
252-
ax.legend([h2], [i.get_label() for i in [h2]], loc="best")
253-
# -
254-
255-
# Alternatively, the intersection can be calculated using special methods optimized for structured grids. Access these methods by instantiating the GridIntersect class with the `method="structured"` keyword argument.
256-
257-
ixs = GridIntersect(sgr, method="structured")
258-
result4 = ixs.intersect(p)
259-
260-
# The result is the same as before:
261-
262-
# +
263-
# create a figure and plot the grid
264-
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
265-
sgr.plot(ax=ax)
266-
267-
# the intersection object contains some helpful plotting commands
268-
ix.plot_polygon(result4, ax=ax)
269-
270-
# add black x at cell centers
271-
for irow, icol in result4.cellids:
272-
(h2,) = ax.plot(
273-
sgr.xcellcenters[0, icol],
274-
sgr.ycellcenters[irow, 0],
275-
"kx",
276-
label="centroids of intersected gridcells",
277-
)
278-
279227
# add legend
280228
ax.legend([h2], [i.get_label() for i in [h2]], loc="best")
281229
# -
@@ -295,7 +243,7 @@
295243
# +
296244
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
297245
sgr.plot(ax=ax)
298-
ix.plot_linestring(result, ax=ax, cmap="viridis")
246+
ix.plot_intersection_result(result, ax=ax, cmap="viridis")
299247

300248
for irow, icol in result.cellids:
301249
(h2,) = ax.plot(
@@ -308,21 +256,6 @@
308256
ax.legend([h2], [i.get_label() for i in [h2]], loc="best")
309257
# -
310258

311-
# Same as before, the intersect for structured grids can also be performed with a different method optimized for structured grids
312-
313-
ixs = GridIntersect(sgr, method="structured")
314-
315-
# +
316-
result2 = ixs.intersect(mls)
317-
318-
# ordering is different so compare sets to check equality
319-
check = len(set(result2.cellids) - set(result.cellids)) == 0
320-
print(
321-
"Intersection result with method='structured' and "
322-
f"method='vertex' are equal: {check}"
323-
)
324-
# -
325-
326259
# ### [MultiPoint with regular grid](#top)<a id="rectgrid.3"></a>
327260
#
328261
# MultiPoint to intersect with
@@ -368,21 +301,6 @@
368301
ax.legend([h2, h3], [i.get_label() for i in [h2, h3]], loc="best")
369302
# -
370303

371-
# Same as before, the intersect for structured grids can also be performed with a different method written specifically for structured grids.
372-
373-
ixs = GridIntersect(sgr, method="structured")
374-
375-
# +
376-
result2 = ixs.intersect(mp, return_all_intersections=False)
377-
378-
# ordering is different so compare sets to check equality
379-
check = len(set(result2.cellids) - set(result.cellids)) == 0
380-
print(
381-
"Intersection result with method='structured' and "
382-
f"method='vertex' are equal: {check}"
383-
)
384-
# -
385-
386304
# ## <a id="trigrid"></a>[Vertex Grid](#top)
387305

388306
cell2d = [
@@ -420,9 +338,7 @@
420338

421339
# +
422340
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
423-
pmv = fplot.PlotMapView(ax=ax, modelgrid=tgr)
424-
pmv.plot_grid()
425-
ix.plot_polygon(result, ax=ax)
341+
ix.plot_intersection_result(result, ax=ax)
426342

427343
# only cells that intersect with shape
428344
for cellid in result.cellids:
@@ -442,9 +358,7 @@
442358

443359
# +
444360
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
445-
pmv = fplot.PlotMapView(ax=ax, modelgrid=tgr)
446-
pmv.plot_grid()
447-
ix2.plot_linestring(result, ax=ax, lw=3)
361+
ix2.plot_intersection_result(result, ax=ax, lw=3)
448362

449363
for cellid in result.cellids:
450364
(h2,) = ax.plot(
@@ -464,9 +378,7 @@
464378

465379
# +
466380
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
467-
pmv = fplot.PlotMapView(ax=ax, modelgrid=tgr)
468-
pmv.plot_grid()
469-
ix2.plot_point(result, ax=ax, color="k", zorder=5, s=80)
381+
ix2.plot_intersection_result(result, ax=ax, color="k", zorder=5, s=80)
470382

471383
for cellid in result.cellids:
472384
(h2,) = ax.plot(

0 commit comments

Comments
 (0)