2424from emsarray .exceptions import NoSuchCoordinateError
2525from emsarray .operations import geometry
2626from tests .utils import (
27- DiagonalShocGrid , ShocGridGenerator , ShocLayerGenerator ,
28- assert_property_not_cached
27+ AxisAlignedShocGrid , DiagonalShocGrid , ShocGridGenerator ,
28+ ShocLayerGenerator , assert_property_not_cached , plot_geometry
2929)
3030
3131
@@ -266,7 +266,7 @@ def test_polygons_no_bounds():
266266 assert polygons [20 * 9 + 3 ] is not None
267267
268268
269- def test_polygons_with_bounds ():
269+ def test_polygons_with_bounds () -> None :
270270 dataset = make_dataset (
271271 j_size = 10 , i_size = 20 ,
272272 include_bounds = True , corner_size = 3 )
@@ -289,7 +289,7 @@ def test_polygons_with_bounds():
289289 assert polygons [20 * 9 + 3 ] is not None
290290
291291
292- def test_holes ():
292+ def test_holes () -> None :
293293 dataset = make_dataset (j_size = 10 , i_size = 20 , corner_size = 5 )
294294 only_polygons = dataset .ems .polygons [dataset .ems .mask ]
295295
@@ -313,15 +313,57 @@ def test_holes():
313313 assert poly .equals_exact (Polygon ([(0.3 , 1.9 ), (0.4 , 1.8 ), (0.5 , 1.9 ), (0.4 , 2.0 ), (0.3 , 1.9 )]), 1e-6 )
314314
315315
316- def test_bounds ():
316+ def test_bounds () -> None :
317317 dataset = make_dataset (
318318 j_size = 10 , i_size = 20 , corner_size = 5 , include_bounds = True )
319319 # The corner cuts out some of the upper bounds
320320 assert_allclose (dataset .ems .bounds , (0 , 0 , 3 , 2.5 ))
321321 assert_property_not_cached (dataset .ems , 'geometry' )
322322
323323
324- def test_face_centres ():
324+ @pytest .mark .parametrize ("include_bounds" , [True , False ], ids = ["with-bounds" , "without-bounds" ])
325+ def test_bounds_river (
326+ include_bounds : bool ,
327+ tmp_path : pathlib .Path ,
328+ ) -> None :
329+ # Test calculated bounds for grids with one cell wide 'rivers'.
330+ # The river cells have cell centres but insufficient information to
331+ # construct any bounds for those cells.
332+ dataset = make_dataset (
333+ j_size = 7 , i_size = 7 , include_bounds = include_bounds , grid_type = AxisAlignedShocGrid )
334+ # Clear out a corner on both sides, leaving a one cell wide river.
335+ dataset ['longitude' ].values [:3 , :3 ] = numpy .nan
336+ dataset ['latitude' ].values [:3 , :3 ] = numpy .nan
337+ dataset ['longitude' ].values [- 3 :, :3 ] = numpy .nan
338+ dataset ['latitude' ].values [- 3 :, :3 ] = numpy .nan
339+ if include_bounds :
340+ dataset ['longitude_bounds' ].values [:3 , :3 ] = numpy .nan
341+ dataset ['latitude_bounds' ].values [:3 , :3 ] = numpy .nan
342+ dataset ['longitude_bounds' ].values [- 3 :, :3 ] = numpy .nan
343+ dataset ['latitude_bounds' ].values [- 3 :, :3 ] = numpy .nan
344+
345+ # Useful to see what the geometry looks like, not part of the test.
346+ plot_geometry (dataset , tmp_path / 'river.png' , extent = (- 0.05 , 0.75 , - 0.05 , 0.75 ))
347+
348+ convention : ShocSimple = dataset .ems
349+ polygons = convention .wind (xarray .DataArray (convention .polygons )).values
350+ assert numpy .all (polygons [:, 3 :] != None ) # noqa: E711
351+ assert numpy .all (polygons [:3 , :3 ] == None ) # noqa: E711
352+ assert numpy .all (polygons [- 3 :, :3 ] == None ) # noqa: E711
353+ river_polygons = polygons [3 , :3 ]
354+ if include_bounds :
355+ assert numpy .all (river_polygons != None ) # noqa: E711
356+ else :
357+ assert numpy .all (river_polygons == None ) # noqa: E711
358+
359+ if not include_bounds :
360+ # All the 'coast' cells should have the same minimum x coordinate,
361+ # even the one next to the river.
362+ min_x = [min (p .exterior .coords .xy [0 ]) for p in polygons [:, 3 ]]
363+ numpy .testing .assert_allclose (min_x , 0.35 )
364+
365+
366+ def test_face_centres () -> None :
325367 # SHOC simple face centres are taken directly from the coordinates,
326368 # not calculated from polygon centres.
327369 dataset = make_dataset (j_size = 10 , i_size = 20 , corner_size = 3 )
@@ -338,7 +380,7 @@ def test_face_centres():
338380 numpy .testing .assert_equal (face_centres [linear_index ], [lon , lat ])
339381
340382
341- def test_selector_for_index ():
383+ def test_selector_for_index () -> None :
342384 dataset = make_dataset (j_size = 5 , i_size = 7 )
343385 convention : ShocSimple = dataset .ems
344386
@@ -348,13 +390,13 @@ def test_selector_for_index():
348390 assert selector == convention .selector_for_index (index )
349391
350392
351- def test_make_geojson_geometry ():
393+ def test_make_geojson_geometry () -> None :
352394 dataset = make_dataset (j_size = 10 , i_size = 10 , corner_size = 3 )
353395 out = json .dumps (geometry .to_geojson (dataset ))
354396 assert isinstance (out , str )
355397
356398
357- def test_ravel_index ():
399+ def test_ravel_index () -> None :
358400 dataset = make_dataset (j_size = 5 , i_size = 7 )
359401 convention : ShocSimple = dataset .ems
360402
@@ -365,15 +407,15 @@ def test_ravel_index():
365407 assert convention .wind_index (linear_index , grid_kind = CFGridKind .face ) == index
366408
367409
368- def test_grid_kinds ():
410+ def test_grid_kinds () -> None :
369411 dataset = make_dataset (j_size = 3 , i_size = 5 )
370412 convention : ShocSimple = dataset .ems
371413
372414 assert convention .grid_kinds == frozenset ({CFGridKind .face })
373415 assert convention .default_grid_kind == CFGridKind .face
374416
375417
376- def test_grid_kind_and_size ():
418+ def test_grid_kind_and_size () -> None :
377419 dataset = make_dataset (j_size = 5 , i_size = 7 )
378420 convention : ShocSimple = dataset .ems
379421
@@ -382,7 +424,7 @@ def test_grid_kind_and_size():
382424 assert size == 5 * 7
383425
384426
385- def test_ravel ():
427+ def test_ravel () -> None :
386428 dataset = make_dataset (j_size = 5 , i_size = 7 )
387429 convention : ShocSimple = dataset .ems
388430
@@ -394,7 +436,7 @@ def test_ravel():
394436 temp .values .reshape (temp .shape [:2 ] + (- 1 ,)))
395437
396438
397- def test_wind ():
439+ def test_wind () -> None :
398440 dataset = make_dataset (j_size = 5 , i_size = 7 )
399441 convention : ShocSimple = dataset .ems
400442
@@ -413,7 +455,7 @@ def test_wind():
413455 values .reshape (time_size , 5 , 7 ))
414456
415457
416- def test_drop_geometry (datasets : pathlib .Path ):
458+ def test_drop_geometry (datasets : pathlib .Path ) -> None :
417459 dataset = xarray .open_dataset (datasets / 'cfgrid2d.nc' )
418460
419461 dropped = dataset .ems .drop_geometry ()
@@ -426,7 +468,7 @@ def test_drop_geometry(datasets: pathlib.Path):
426468 assert topology .longitude_name not in dropped .variables
427469
428470
429- def test_values ():
471+ def test_values () -> None :
430472 dataset = make_dataset (j_size = 10 , i_size = 20 , corner_size = 5 )
431473 eta = dataset .data_vars ["eta" ].isel (time = 0 )
432474 values = dataset .ems .ravel (eta )
@@ -439,7 +481,7 @@ def test_values():
439481
440482
441483@pytest .mark .matplotlib
442- def test_plot_on_figure ():
484+ def test_plot_on_figure () -> None :
443485 # Not much to test here, mostly that it doesn't throw an error
444486 dataset = make_dataset (j_size = 10 , i_size = 20 )
445487 surface_temp = dataset .data_vars ["temp" ].isel (k = - 1 , time = 0 )
0 commit comments