From 32b076b5d83f61bef4b48dc35309b1ec051970ca Mon Sep 17 00:00:00 2001 From: Henrik Andersson Date: Thu, 2 Nov 2023 18:35:15 +0100 Subject: [PATCH] Merge _UnstructuredFile into _Dfsu --- mikeio/dfsu/_common.py | 33 +++++++++++ mikeio/dfsu/_dfsu.py | 121 ++++++++++------------------------------- mikeio/dfsu/_mesh.py | 8 +-- 3 files changed, 67 insertions(+), 95 deletions(-) create mode 100644 mikeio/dfsu/_common.py diff --git a/mikeio/dfsu/_common.py b/mikeio/dfsu/_common.py new file mode 100644 index 000000000..781eec880 --- /dev/null +++ b/mikeio/dfsu/_common.py @@ -0,0 +1,33 @@ +import numpy as np + +# TODO type hints +def _get_elements_from_source(source): + element_table = _get_element_table_from_mikecore( + source.ElementTable + ) + element_ids = source.ElementIds - 1 + return element_table, element_ids + + +def _get_nodes_from_source(source): + xn = source.X + yn = source.Y + zn = source.Z + nc = np.column_stack([xn, yn, zn]) + codes = np.array(list(source.Code)) + node_ids = source.NodeIds - 1 + return nc, codes, node_ids + +def _offset_element_table_by(element_table, offset, copy=True): + offset = int(offset) + new_elem_table = element_table.copy() if copy else element_table + for j in range(len(element_table)): + new_elem_table[j] = element_table[j] + offset + return new_elem_table + + +def _get_element_table_from_mikecore(element_table): + return _offset_element_table_by(element_table, -1) + +def _element_table_to_mikecore(element_table): + return _offset_element_table_by(element_table, 1) diff --git a/mikeio/dfsu/_dfsu.py b/mikeio/dfsu/_dfsu.py index c6d502b6a..9cef47b39 100644 --- a/mikeio/dfsu/_dfsu.py +++ b/mikeio/dfsu/_dfsu.py @@ -37,10 +37,10 @@ from ..spatial._FM_utils import _plot_map from ..spatial import Grid2D from .._track import _extract_track +from ._common import _get_elements_from_source, _get_nodes_from_source def _write_dfsu(filename: str, data: Dataset): - filename = str(filename) if len(data.time) == 1: @@ -104,30 +104,9 @@ def _write_dfsu(filename: str, data: Dataset): dfs.Close() -class _UnstructuredFile: - """ - _UnstructuredFile is base class for Mesh and Dfsu - has file handle, items and timesteps and reads file header - """ - +class _Dfsu: show_progress = False - def __init__(self) -> None: - self._type = None # -1: mesh, 0: 2d-dfsu, 4:dfsu3dsigma, ... - self._geometry = None - self._geom2d = None - # self._shapely_domain_obj = None - - self._filename = None - self._source = None - self._deletevalue = None - - self._n_timesteps = None - self._start_time = None - self._timestep_in_seconds = None - - self._items = None - def __repr__(self): out = [] type_name = "Flexible Mesh" if self._type is None else self.type_name @@ -168,7 +147,7 @@ def __repr__(self): out.append(f" {self._start_time} -- {self.end_time}") return str.join("\n", out) - def _read_header(self, input): + def _read_header(self, input: DfsuFile | str | Path): if isinstance(input, DfsuFile): # input is a dfsu file object (already open) self._read_dfsu_header(input) @@ -199,8 +178,8 @@ def _read_mesh_header(self, filename): self._source = msh self._type = None # =DfsuFileType.Mesh - nc, codes, node_ids = self._get_nodes_from_source(msh) - el_table, el_ids = self._get_elements_from_source(msh) + nc, codes, node_ids = _get_nodes_from_source(msh) + el_table, el_ids = _get_elements_from_source(msh) self._geometry = GeometryFM2D( node_coordinates=nc, @@ -232,8 +211,8 @@ def _read_dfsu_header(self, dfs): frequencies=frequencies, directions=directions ) else: - nc, codes, node_ids = self._get_nodes_from_source(dfs) - el_table, el_ids = self._get_elements_from_source(dfs) + nc, codes, node_ids = _get_nodes_from_source(dfs) + el_table, el_ids = _get_elements_from_source(dfs) if self.is_layered: geom_cls = GeometryFM3D @@ -307,40 +286,6 @@ def _read_dfsu_header(self, dfs): dfs.Close() - @staticmethod - def _get_nodes_from_source(source): - xn = source.X - yn = source.Y - zn = source.Z - nc = np.column_stack([xn, yn, zn]) - codes = np.array(list(source.Code)) - node_ids = source.NodeIds - 1 - return nc, codes, node_ids - - @staticmethod - def _get_elements_from_source(source): - element_table = _UnstructuredFile._get_element_table_from_mikecore( - source.ElementTable - ) - element_ids = source.ElementIds - 1 - return element_table, element_ids - - @staticmethod - def _offset_element_table_by(element_table, offset, copy=True): - offset = int(offset) - new_elem_table = element_table.copy() if copy else element_table - for j in range(len(element_table)): - new_elem_table[j] = element_table[j] + offset - return new_elem_table - - @staticmethod - def _get_element_table_from_mikecore(element_table): - return _UnstructuredFile._offset_element_table_by(element_table, -1) - - @staticmethod - def _element_table_to_mikecore(element_table): - return _UnstructuredFile._offset_element_table_by(element_table, 1) - @property def type_name(self): """Type name, e.g. Mesh, Dfsu2D""" @@ -572,7 +517,6 @@ def plot( ax=None, add_colorbar=True, ): - warnings.warn( FutureWarning( "Dfsu.plot() have been deprecated, please use DataArray.plot() instead" @@ -619,9 +563,7 @@ def plot( add_colorbar=add_colorbar, ) - -class _Dfsu(_UnstructuredFile): - def __init__(self, filename, dfs=None): + def __init__(self, filename, dfs: DfsuFile | None = None): """ Create a Dfsu object @@ -631,18 +573,15 @@ def __init__(self, filename, dfs=None): dfsu or mesh filename dfs : """ - super().__init__() + # placeholder + self._timestep_in_seconds = None + self._filename = str(filename) input = self._filename if dfs is None else dfs self._read_header(input) - # show progress bar for large files - # if self._type == UnstructuredType.Mesh: - # tot_size = self.n_elements - # else: - # tot_size = self.n_elements * self.n_timesteps * self.n_items - # if tot_size > 1e6: - # self.show_progress = True + # Caching + self._geom2d = None @property def deletevalue(self): @@ -705,7 +644,6 @@ def _read( error_bad_data=True, fill_bad_data_value=np.nan, ) -> Dataset: - if dtype not in [np.float32, np.float64]: raise ValueError("Invalid data type. Choose np.float32 or np.float64") @@ -761,7 +699,6 @@ def _read( for i in trange(n_steps, disable=not self.show_progress): it = time_steps[i] for item in range(n_items): - dfs, d = _read_item_time_step( dfs=dfs, filename=self._filename, @@ -1041,7 +978,9 @@ def _write( n_time_steps = np.shape(data[0])[0] if dt is None: - if self.timestep is None: + if ( + self.timestep is None + ): # TODO this is a sign that this method needs to be removed dt = 1 else: dt = self.timestep # 1 # Arbitrary if there is only a single timestep @@ -1182,7 +1121,6 @@ def _write( return self except Exception as e: - print(e) self._dfs.Close() os.remove(filename) @@ -1244,7 +1182,6 @@ def to_mesh(self, outfilename): class Dfsu2DH(_Dfsu): - def read( self, *, @@ -1291,17 +1228,19 @@ def read( Dataset A Dataset with data dimensions [t,elements] """ - - return self._read(items=items, - time=time, - elements=elements, - area=area, - x=x, - y=y, - keepdims=keepdims, - dtype=dtype, - error_bad_data=error_bad_data, - fill_bad_data_value=fill_bad_data_value) + + return self._read( + items=items, + time=time, + elements=elements, + area=area, + x=x, + y=y, + keepdims=keepdims, + dtype=dtype, + error_bad_data=error_bad_data, + fill_bad_data_value=fill_bad_data_value, + ) def _dfs_read_item_time_func(self, item: int, step: int): dfs = DfsuFile.Open(self._filename) @@ -1373,4 +1312,4 @@ def extract_track(self, track, items=None, method="nearest", dtype=np.float32): data_read_func=self._dfs_read_item_time_func, ) dfs.Close() - return res \ No newline at end of file + return res diff --git a/mikeio/dfsu/_mesh.py b/mikeio/dfsu/_mesh.py index be8273b98..6dce62086 100644 --- a/mikeio/dfsu/_mesh.py +++ b/mikeio/dfsu/_mesh.py @@ -8,8 +8,8 @@ from mikecore.MeshFile import MeshFile from ..eum import EUMType, EUMUnit -from ._dfsu import _UnstructuredFile from ..spatial import GeometryFM2D +from ._common import _get_elements_from_source, _get_nodes_from_source, _element_table_to_mikecore class Mesh: @@ -39,8 +39,8 @@ def __init__(self, filename: str | Path) -> None: def _read_header(self, filename: str | Path) -> GeometryFM2D: msh = MeshFile.ReadMesh(filename) - nc, codes, node_ids = _UnstructuredFile._get_nodes_from_source(msh) - el_table, el_ids = _UnstructuredFile._get_elements_from_source(msh) + nc, codes, node_ids = _get_nodes_from_source(msh) + el_table, el_ids = _get_elements_from_source(msh) geom = GeometryFM2D( node_coordinates=nc, @@ -124,7 +124,7 @@ def write( assert isinstance(geometry, GeometryFM2D) # i.e. not a GeometryPoint2d quantity = eumQuantity.Create(EUMType.Bathymetry, unit) - elem_table = _UnstructuredFile._element_table_to_mikecore( + elem_table = _element_table_to_mikecore( geometry.element_table )