Skip to content

Commit 4f1a48a

Browse files
committed
add warning to square grid generator when boundary does not fully enclose the AOI
1 parent 08e767c commit 4f1a48a

File tree

5 files changed

+237
-162
lines changed

5 files changed

+237
-162
lines changed

geowrangler/_modidx.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@
199199
'geowrangler/grids.py'),
200200
'geowrangler.grids.get_parallel_intersects': ( 'grids.html#get_parallel_intersects',
201201
'geowrangler/grids.py'),
202+
'geowrangler.grids.is_aoi_within_boundary': ( 'grids.html#is_aoi_within_boundary',
203+
'geowrangler/grids.py'),
202204
'geowrangler.grids.setup_boundary': ('grids.html#setup_boundary', 'geowrangler/grids.py')},
203205
'geowrangler.raster_process': { 'geowrangler.raster_process.query_window_by_gdf': ( 'raster_process.html#query_window_by_gdf',
204206
'geowrangler/raster_process.py'),

geowrangler/grids.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import numpy as np
1515
import pandas as pd
1616
import polars as pl
17+
import warnings
1718
from fastcore.all import defaults, parallel
1819
from fastcore.basics import patch
1920
from geopandas import GeoDataFrame, GeoSeries
@@ -170,8 +171,26 @@ def setup_boundary(
170171
x_min, y_min, x_max, y_max, boundary_type="custom_boundary"
171172
)
172173

174+
if not is_aoi_within_boundary(boundary, reprojected_gdf):
175+
warnings.warn(
176+
"The given boundary does not fully enclose the reprojected AOI. There might be missing grid cells due to this. Try getting the boundary of the reprojected AOI, and/or adding a buffer to the boundary. See geowrangler.thinkingmachin.es/tutorial.grids.html#reprojecting-before-gridding for more info."
177+
)
178+
173179
return boundary
174180

181+
182+
def is_aoi_within_boundary(
183+
boundary: Optional[Union[SquareGridGenerator, Iterable[float]]],
184+
gdf: GeoDataFrame,
185+
) -> bool:
186+
187+
gdf_minx, gdf_miny, gdf_maxx, gdf_maxy = gdf.total_bounds
188+
is_x_within_bounds = (gdf_minx >= boundary.x_min) & (gdf_maxx <= boundary.x_max)
189+
is_y_within_bounds = (gdf_miny >= boundary.y_min) & (gdf_maxy <= boundary.y_max)
190+
191+
is_within_bounds = is_x_within_bounds & is_y_within_bounds
192+
return is_within_bounds
193+
175194
# %% ../notebooks/00_grids.ipynb 14
176195
class FastSquareGridGenerator:
177196
PIXEL_DTYPE = polygon_fill.PIXEL_DTYPE

notebooks/00_grids.ipynb

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"import numpy as np\n",
7070
"import pandas as pd\n",
7171
"import polars as pl\n",
72+
"import warnings\n",
7273
"from fastcore.all import defaults, parallel\n",
7374
"from fastcore.basics import patch\n",
7475
"from geopandas import GeoDataFrame, GeoSeries\n",
@@ -278,8 +279,23 @@
278279
" x_min, y_min = transformer.transform(boundary[0], boundary[1])\n",
279280
" x_max, y_max = transformer.transform(boundary[2], boundary[3])\n",
280281
" boundary = SquareGridBoundary(x_min, y_min, x_max, y_max, boundary_type=\"custom_boundary\")\n",
281-
" \n",
282-
" return boundary"
282+
"\n",
283+
" if not is_aoi_within_boundary(boundary, reprojected_gdf):\n",
284+
" warnings.warn(\"The given boundary does not fully enclose the reprojected AOI. There might be missing grid cells due to this. Try getting the boundary of the reprojected AOI, and/or adding a buffer to the boundary. See geowrangler.thinkingmachin.es/tutorial.grids.html#reprojecting-before-gridding for more info.\")\n",
285+
"\n",
286+
" return boundary\n",
287+
"\n",
288+
"def is_aoi_within_boundary(\n",
289+
" boundary: Optional[Union[SquareGridGenerator,Iterable[float]]],\n",
290+
" gdf: GeoDataFrame,\n",
291+
") -> bool:\n",
292+
"\n",
293+
" gdf_minx, gdf_miny, gdf_maxx, gdf_maxy = gdf.total_bounds\n",
294+
" is_x_within_bounds = (gdf_minx >= boundary.x_min) & (gdf_maxx <= boundary.x_max)\n",
295+
" is_y_within_bounds = (gdf_miny >= boundary.y_min) & (gdf_maxy <= boundary.y_max)\n",
296+
"\n",
297+
" is_within_bounds = is_x_within_bounds & is_y_within_bounds\n",
298+
" return is_within_bounds"
283299
]
284300
},
285301
{

notebooks/tutorial.grids.ipynb

Lines changed: 190 additions & 156 deletions
Large diffs are not rendered by default.

tests/test_grids.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,15 @@ def test_boundary_smaller_then_a_cell():
7878

7979
def test_generate_grids_aoi_outside_boundary(sample_gdf):
8080
grid_generator = grids.SquareGridGenerator(15000, boundary=(10, 10, 20, 20))
81-
grids_gdf = grid_generator.generate_grid(sample_gdf)
81+
with pytest.warns(UserWarning):
82+
grids_gdf = grid_generator.generate_grid(sample_gdf)
8283

8384
assert len(grids_gdf) == 0
8485

8586
def test_generate_grids_aoi_partially_inside_boundary(sample_gdf):
8687
grid_generator = grids.SquareGridGenerator(15000, boundary=(0.5, 0.5, 20, 20))
87-
grids_gdf = grid_generator.generate_grid(sample_gdf)
88+
with pytest.warns(UserWarning):
89+
grids_gdf = grid_generator.generate_grid(sample_gdf)
8890

8991
assert len(grids_gdf) == 108
9092
assert grids_gdf.to_crs("EPSG:3857").area.apply(np.isclose, b=15000**2).all()
@@ -119,13 +121,15 @@ def test_generate_fast_grids_w_custom_boundary_2(sample_gdf):
119121

120122
def test_generate_fast_grids_aoi_outside_boundary(sample_gdf):
121123
grid_generator = grids.FastSquareGridGenerator(15000, boundary=(10, 10, 20, 20))
122-
grids_gdf = grid_generator.generate_grid(sample_gdf)
124+
with pytest.warns(UserWarning):
125+
grids_gdf = grid_generator.generate_grid(sample_gdf)
123126

124127
assert len(grids_gdf) == 0
125128

126129
def test_generate_fast_grids_aoi_partially_inside_boundary(sample_gdf):
127130
grid_generator = grids.FastSquareGridGenerator(15000, boundary=(0.5, 0.5, 20, 20))
128-
grids_gdf = grid_generator.generate_grid(sample_gdf)
131+
with pytest.warns(UserWarning):
132+
grids_gdf = grid_generator.generate_grid(sample_gdf)
129133

130134
assert len(grids_gdf) == 108
131135
assert grids_gdf.to_crs("EPSG:3857").area.apply(np.isclose, b=15000**2).all()

0 commit comments

Comments
 (0)