From 99cedf7688fca2abe394aaf1256c252163f7e6c2 Mon Sep 17 00:00:00 2001 From: Henrik Andersson Date: Tue, 12 Mar 2024 15:40:37 +0100 Subject: [PATCH 1/2] Slim mesh api --- Makefile | 2 +- mikeio/dfsu/_mesh.py | 52 ++++++----------------------------------- tests/test_dfsu_plot.py | 4 ++-- tests/test_mesh.py | 18 -------------- 4 files changed, 10 insertions(+), 66 deletions(-) diff --git a/Makefile b/Makefile index 34a80e113..e67e879fd 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ build: typecheck test python -m build lint: - ruff . + ruff check . pylint: pylint --disable=all --enable=attribute-defined-outside-init mikeio/ diff --git a/mikeio/dfsu/_mesh.py b/mikeio/dfsu/_mesh.py index f7300a464..16a251732 100644 --- a/mikeio/dfsu/_mesh.py +++ b/mikeio/dfsu/_mesh.py @@ -1,21 +1,18 @@ from __future__ import annotations from pathlib import Path from typing import TYPE_CHECKING -from collections.abc import Collection -import warnings + import numpy as np -from mikecore.eum import eumQuantity -from mikecore.MeshBuilder import MeshBuilder + from mikecore.MeshFile import MeshFile -from ..eum import EUMType, EUMUnit + from ..spatial import GeometryFM2D from ._common import ( get_elements_from_source, get_nodes_from_source, - element_table_to_mikecore, ) if TYPE_CHECKING: @@ -48,20 +45,8 @@ class Mesh: """ def __init__(self, filename: str | Path) -> None: - ext = Path(filename).suffix.lower() - - if ext == ".mesh": - self.geometry: GeometryFM2D = self._read_header(filename) - elif ext == ".dfsu": - # TODO remove in v 1.8 - import mikeio - - warnings.warn( - f'Reading dfsu with `Mesh` is deprecated. Read a .dfsu geometry with `geom = mikeio.open("{filename}").geometry`', - FutureWarning, - ) - self.geometry = mikeio.open(str(filename)).geometry + self.geometry: GeometryFM2D = self._read_header(filename) self.plot = self.geometry.plot def _read_header(self, filename: str | Path) -> GeometryFM2D: @@ -128,7 +113,7 @@ def zn(self) -> np.ndarray: return self.geometry.node_coordinates[:, 2] @zn.setter - def zn(self, v: np.ndarray): + def zn(self, v: np.ndarray) -> None: if len(v) != self.n_nodes: raise ValueError(f"zn must have length of nodes ({self.n_nodes})") self.geometry._nc[:, 2] = v @@ -136,8 +121,6 @@ def zn(self, v: np.ndarray): def write( self, outfilename: str | Path, - elements: Collection[int] | None = None, - unit: EUMUnit = EUMUnit.meter, ) -> None: """write mesh to file @@ -145,34 +128,13 @@ def write( ---------- outfilename : str path to file - elements : list(int) - list of element ids (subset) to be saved to new mesh """ - # TODO reconsider if selection of elements should be done here, it is possible to do with geometry.isel and then write the mesh - builder = MeshBuilder() - if elements is not None: - geometry = self.geometry.isel(elements) - else: - geometry = self.geometry + geometry = self.geometry assert isinstance(geometry, GeometryFM2D) # i.e. not a GeometryPoint2d - quantity = eumQuantity.Create(EUMType.Bathymetry, unit) - elem_table = element_table_to_mikecore(geometry.element_table) - - nc = geometry.node_coordinates - builder.SetNodes(nc[:, 0], nc[:, 1], nc[:, 2], geometry.codes) - - builder.SetElements(elem_table) - builder.SetProjection(geometry.projection_string) - builder.SetEumQuantity(quantity) - - newMesh = builder.CreateMesh() - newMesh.Write(outfilename) - - def plot_boundary_nodes(self, boundary_names=None, figsize=None, ax=None) -> None: - return self.geometry.plot.boundary_nodes(boundary_names, figsize, ax) + self.geometry.to_mesh(outfilename=outfilename) def to_shapely(self) -> MultiPolygon: """Convert Mesh geometry to shapely MultiPolygon diff --git a/tests/test_dfsu_plot.py b/tests/test_dfsu_plot.py index f383b4e4e..9687229ea 100644 --- a/tests/test_dfsu_plot.py +++ b/tests/test_dfsu_plot.py @@ -73,8 +73,8 @@ def test_plot_mesh_ax(): def test_plot_mesh_boundary_nodes(): msh = Mesh("tests/testdata/odense_rough.mesh") - msh.plot_boundary_nodes() - msh.plot_boundary_nodes(["Land", "Sea"]) + msh.plot.boundary_nodes() + msh.plot.boundary_nodes(["Land", "Sea"]) assert True diff --git a/tests/test_mesh.py b/tests/test_mesh.py index 35b036fdd..8944b68ea 100644 --- a/tests/test_mesh.py +++ b/tests/test_mesh.py @@ -122,16 +122,6 @@ def test_write(tri_mesh, tmp_path): assert outfilename.exists() -def test_write_part(tri_mesh, tmp_path): - outfilename = tmp_path / "simple_sub.mesh" - - msh = tri_mesh - - msh.write(outfilename, elements=list(range(0, 100))) - - assert outfilename.exists() - - def test_write_part_isel(tri_mesh, tmp_path): outfilename = tmp_path / "simple_sub.mesh" @@ -160,14 +150,6 @@ def test_write_mesh_from_dfsu(tmp_path): assert np.all(np.hstack(msh2.element_table) == np.hstack(geometry.element_table)) -def test_open_dfsu_as_mesh_is_removed_give_hint(): - dfsufilename = "tests/testdata/FakeLake.dfsu" - with pytest.warns(FutureWarning): - msh = Mesh(dfsufilename) - - msh.plot() - - def test_to_shapely(tri_mesh) -> None: msh = tri_mesh shp = msh.to_shapely() From 2e7f6b5850bb45b5e456c83ab539ec91801b17f5 Mon Sep 17 00:00:00 2001 From: Henrik Andersson Date: Tue, 12 Mar 2024 16:08:10 +0100 Subject: [PATCH 2/2] _Dfsu repr --- mikeio/dfsu/_dfsu.py | 31 +++++++++++++------------------ tests/test_consistency.py | 9 +++++++++ 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/mikeio/dfsu/_dfsu.py b/mikeio/dfsu/_dfsu.py index 9b147c8db..008c3006b 100644 --- a/mikeio/dfsu/_dfsu.py +++ b/mikeio/dfsu/_dfsu.py @@ -139,9 +139,7 @@ def __init__(self, filename: str | Path) -> None: self._items = self._read_items(filename) def __repr__(self): - out = [] - type_name = "Flexible Mesh" if self._type is None else self.type_name - out.append(type_name) + out = [f""] if self._type is not DfsuFileType.DfsuSpectral0D: if self._type is not DfsuFileType.DfsuSpectral1D: @@ -161,21 +159,18 @@ def __repr__(self): or self._type == DfsuFileType.Dfsu3DSigmaZ ): out.append(f"max number of z layers: {self.n_layers - self.n_sigma_layers}") - if hasattr(self, "items") and self.items is not None: - if self.n_items < 10: - out.append("items:") - for i, item in enumerate(self.items): - out.append(f" {i}: {item}") - else: - out.append(f"number of items: {self.n_items}") - if self.n_timesteps is not None: - if self.n_timesteps == 1: - out.append(f"time: time-invariant file (1 step) at {self._start_time}") - else: - out.append( - f"time: {str(self.time[0])} - {str(self.time[-1])} ({self.n_timesteps} records)" - ) - out.append(f" {self.start_time} -- {self.end_time}") + if self.n_items < 10: + out.append("items:") + for i, item in enumerate(self.items): + out.append(f" {i}: {item}") + else: + out.append(f"number of items: {self.n_items}") + if self.n_timesteps == 1: + out.append(f"time: time-invariant file (1 step) at {self.time[0]}") + else: + out.append( + f"time: {str(self.time[0])} - {str(self.time[-1])} ({self.n_timesteps} records)" + ) return str.join("\n", out) def _read_items(self, filename: str) -> list[ItemInfo]: diff --git a/tests/test_consistency.py b/tests/test_consistency.py index 314da71a1..ce1c9e7de 100644 --- a/tests/test_consistency.py +++ b/tests/test_consistency.py @@ -263,6 +263,15 @@ def test_read_dfs_time_selection_str(): assert dsr.shape == dsgetitem.shape +def test_open_dfs_repr(): + extensions = ["dfsu", "dfs2", "dfs1", "dfs0"] + for ext in extensions: + filename = f"tests/testdata/consistency/oresundHD.{ext}" + dfs = mikeio.open(filename=filename) + text = repr(dfs) + assert "