Skip to content

Commit fb3dda2

Browse files
authored
Merge pull request #779 from DHI/test_dfsu_read_x_y
Add missing dfsu read x,y test
2 parents 16c27c4 + 08befe2 commit fb3dda2

File tree

3 files changed

+53
-77
lines changed

3 files changed

+53
-77
lines changed

mikeio/dfsu/_dfsu.py

Lines changed: 20 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -399,8 +399,8 @@ def read(
399399
time: int | str | slice | None = None,
400400
elements: Sequence[int] | np.ndarray | None = None,
401401
area: tuple[float, float, float, float] | None = None,
402-
x: float | None = None,
403-
y: float | None = None,
402+
x: float | Sequence[float] | None = None,
403+
y: float | Sequence[float] | None = None,
404404
keepdims: bool = False,
405405
dtype: Any = np.float32,
406406
error_bad_data: bool = True,
@@ -421,7 +421,7 @@ def read(
421421
Read only data inside (horizontal) area given as a
422422
bounding box (tuple with left, lower, right, upper)
423423
or as list of coordinates for a polygon, by default None
424-
x, y: float, optional
424+
x, y: float or list[float], optional
425425
Read only data for elements containing the (x,y) points(s),
426426
by default None
427427
elements: list[int], optional
@@ -447,8 +447,11 @@ def read(
447447
single_time_selected, time_steps = _valid_timesteps(dfs, time)
448448

449449
_validate_elements_and_geometry_sel(elements, area=area, x=x, y=y)
450-
if elements is None:
451-
elements = self._parse_geometry_sel(area=area, x=x, y=y)
450+
if area is not None:
451+
elements = self.geometry._elements_in_area(area)
452+
453+
if (x is not None) or (y is not None):
454+
elements = self.geometry.find_index(x=x, y=y)
452455

453456
if elements is None:
454457
geometry = self.geometry
@@ -459,44 +462,34 @@ def read(
459462
geometry = self.geometry.elements_to_geometry(elements)
460463

461464
item_numbers = _valid_item_numbers(dfs.ItemInfo, items)
462-
items = _get_item_info(dfs.ItemInfo, item_numbers)
463465
n_items = len(item_numbers)
464466

465-
deletevalue = self.deletevalue
466-
467-
data_list = []
468-
469-
shape: tuple[int, ...]
470-
471467
t_rel = np.zeros(len(time_steps))
472468

473469
n_steps = len(time_steps)
474-
shape = (
470+
shape: tuple[int, ...] = (
475471
(n_elems,)
476472
if (single_time_selected and not keepdims)
477473
else (n_steps, n_elems)
478474
)
479-
for item in range(n_items):
480-
# Initialize an empty data block
481-
data: np.ndarray = np.ndarray(shape=shape, dtype=dtype)
482-
data_list.append(data)
475+
data_list: list[np.ndarray] = [
476+
np.ndarray(shape=shape, dtype=dtype) for _ in range(n_items)
477+
]
483478

484479
for i in trange(n_steps, disable=not self.show_progress):
485-
it = time_steps[i]
486480
for item in range(n_items):
487-
dfs, d, t = _read_item_time_step(
481+
dfs, d, t_rel[i] = _read_item_time_step(
488482
dfs=dfs,
489483
filename=self._filename,
490484
time=time,
491485
item_numbers=item_numbers,
492-
deletevalue=deletevalue,
486+
deletevalue=self.deletevalue,
493487
shape=shape,
494488
item=item,
495-
it=it,
489+
it=time_steps[i],
496490
error_bad_data=error_bad_data,
497491
fill_bad_data_value=fill_bad_data_value,
498492
)
499-
t_rel[i] = t
500493

501494
if elements is not None:
502495
d = d[elements]
@@ -506,13 +499,9 @@ def read(
506499
else:
507500
data_list[item][i] = d
508501

509-
time = pd.to_datetime(t_rel, unit="s", origin=self.start_time)
510-
511502
dfs.Close()
512503

513-
dims: tuple[str, ...]
514-
515-
dims = ("time", "element")
504+
dims: tuple[str, ...] = ("time", "element")
516505

517506
if single_time_selected and not keepdims:
518507
dims = ("element",)
@@ -522,10 +511,13 @@ def read(
522511
dims = tuple([d for d in dims if d != "element"])
523512
data_list = [np.squeeze(d, axis=-1) for d in data_list]
524513

514+
time = pd.to_datetime(t_rel, unit="s", origin=self.start_time)
515+
item_infos = _get_item_info(dfs.ItemInfo, item_numbers)
516+
525517
return Dataset(
526518
data_list,
527519
time,
528-
items,
520+
item_infos,
529521
geometry=geometry,
530522
dims=dims,
531523
validate=False,
@@ -558,53 +550,6 @@ def append(self, ds: Dataset, validate: bool = True) -> None:
558550
info = _get_dfsu_info(self._filename)
559551
self._n_timesteps = info.n_timesteps
560552

561-
def _parse_geometry_sel(
562-
self,
563-
area: tuple[float, float, float, float] | None,
564-
x: float | None,
565-
y: float | None,
566-
) -> np.ndarray | None:
567-
"""Parse geometry selection.
568-
569-
Parameters
570-
----------
571-
area : list[float], optional
572-
Read only data inside (horizontal) area given as a
573-
bounding box (tuple with left, lower, right, upper)
574-
or as list of coordinates for a polygon, by default None
575-
x : float, optional
576-
Read only data for elements containing the (x,y) points(s),
577-
by default None
578-
y : float, optional
579-
Read only data for elements containing the (x,y) points(s),
580-
by default None
581-
582-
Returns
583-
-------
584-
list[int]
585-
List of element ids
586-
587-
Raises
588-
------
589-
ValueError
590-
If no elements are found in selection
591-
592-
"""
593-
elements = None
594-
595-
if area is not None:
596-
elements = self.geometry._elements_in_area(area)
597-
598-
if (x is not None) or (y is not None):
599-
elements = self.geometry.find_index(x=x, y=y)
600-
601-
if (x is not None) or (y is not None) or (area is not None):
602-
# selection was attempted
603-
if (elements is None) or len(elements) == 0:
604-
raise ValueError("No elements in selection!")
605-
606-
return elements
607-
608553
def get_overset_grid(
609554
self,
610555
dx: float | None = None,

mikeio/spatial/_FM_geometry.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,14 +1077,16 @@ def _elements_in_area(
10771077
xc = self.element_coordinates[:, 0]
10781078
yc = self.element_coordinates[:, 1]
10791079
mask = (xc >= x0) & (xc <= x1) & (yc >= y0) & (yc <= y1)
1080-
return np.where(mask)[0]
10811080
elif self._area_is_polygon(area):
10821081
polygon = np.array(area)
10831082
xy = self.element_coordinates[:, :2]
10841083
mask = self._inside_polygon(polygon, xy)
1085-
return np.where(mask)[0]
10861084
else:
10871085
raise ValueError("'area' must be bbox [x0,y0,x1,y1] or polygon")
1086+
elements = np.where(mask)[0]
1087+
if len(elements) == 0:
1088+
raise ValueError("No elements in selection!")
1089+
return elements
10881090

10891091
def elements_to_geometry(
10901092
self, elements: int | Sequence[int], keepdims: bool = False

tests/test_dfsu.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,35 @@ def test_read_elements():
259259
assert ds2.Wind_speed.to_numpy()[0, 1] == pytest.approx(9.530759811401367)
260260

261261

262+
def test_read_x_y() -> None:
263+
x = [1.49318531, 3.69276145]
264+
y = [53.97088571, 54.08928194]
265+
dfs = mikeio.open("tests/testdata/wind_north_sea.dfsu")
266+
assert isinstance(dfs, mikeio.Dfsu2DH)
267+
ds = dfs.read(x=x, y=y, time=0, keepdims=True)
268+
assert isinstance(ds.geometry, mikeio.GeometryFM2D)
269+
assert ds.geometry.element_coordinates[0][0] == pytest.approx(1.4931853081272184)
270+
assert ds.Wind_speed.to_numpy()[0, 0] == pytest.approx(9.530759811401367)
271+
272+
x = x[::-1]
273+
y = y[::-1]
274+
ds2 = mikeio.read(
275+
filename="tests/testdata/wind_north_sea.dfsu", x=x, y=y, time=0, keepdims=True
276+
)
277+
assert isinstance(ds2.geometry, mikeio.GeometryFM2D)
278+
assert ds2.geometry.element_coordinates[1][0] == pytest.approx(1.4931853081272184)
279+
assert ds2.Wind_speed.to_numpy()[0, 1] == pytest.approx(9.530759811401367)
280+
281+
x = 1.49318531
282+
y = 53.97088571
283+
ds3 = mikeio.read(
284+
filename="tests/testdata/wind_north_sea.dfsu", x=x, y=y, time=0, keepdims=True
285+
)
286+
assert isinstance(ds3.geometry, mikeio.spatial.GeometryPoint2D)
287+
assert ds3.geometry.x == pytest.approx(1.4931853081272184)
288+
assert ds3.geometry.y == pytest.approx(53.97088571)
289+
290+
262291
def test_find_index_on_island():
263292
filename = "tests/testdata/FakeLake.dfsu"
264293
dfs = mikeio.open(filename)

0 commit comments

Comments
 (0)