nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: DHI/mikeio
Pull request #236 (2021-09-08 10:56:27)

Eum type search for velocity fails


Patch:
diff --git a/mikeio/eum.py b/mikeio/eum.py
index a400d776..88f16571 100644
--- a/mikeio/eum.py
+++ b/mikeio/eum.py
@@ -12,8 +12,8 @@ Examples
 degree Kelvin
 
 """
-# from DHI.Generic.MikeZero import EUMWrapper
-from mikecore.eum import eumDLL, eumWrapper
+from typing import List
+from mikecore.eum import eumWrapper
 from enum import IntEnum
 
 from mikeio.helpers import to_datatype
@@ -116,6 +116,7 @@ class EUMType(IntEnum):
     >>> EUMType.Temperature.units
     [degree Celsius, degree Fahrenheit, degree Kelvin]
     """
+
     Water_Level = 100000
     Discharge = 100001
     Wind_Velocity = 100002
@@ -215,7 +216,7 @@ class EUMType(IntEnum):
     Accumulated_transport_per_meter = 100096
     Significant_wave_height = 100097
     Critical_Shields_parameter = 100098
-    # Phib_angle_og_bed_velocity = 100099
+    AngleBedVelocity = 100099
     Profile_number = 100100
     Climate_number = 100101
     Spectral_description = 100102
@@ -712,12 +713,12 @@ class EUMType(IntEnum):
     def units(self):
         """List valid units for this EUM type"""
         temp = unit_list(self.code).items()
-        return [EUMUnit(value) for key, value in temp]
+        return [EUMUnit(value) for _, value in temp]
 
     @staticmethod
-    def search(pattern):
+    def search(pattern) -> List["EUMType"]:
         temp = type_list(pattern).items()
-        return [EUMType(key) for key, value in temp]
+        return [EUMType(key) for key, _ in temp]
 
 
 class EUMUnit(IntEnum):
@@ -729,6 +730,7 @@ class EUMUnit(IntEnum):
     >>> EUMUnit.degree_Kelvin
     degree Kelvin
     """
+
     meter = 1000
     kilometer = 1001
     centimeter = 1007
diff --git a/setup.py b/setup.py
index 325b9959..768cd04a 100644
--- a/setup.py
+++ b/setup.py
@@ -7,7 +7,7 @@ setuptools.setup(
     name="mikeio",
     version="0.7.dev3",
     install_requires=[
-        "mikecore>=0.1.2",
+        "mikecore",
         "numpy",
         "pandas",
         "scipy",


Test patch:
diff --git a/tests/test_eum.py b/tests/test_eum.py
index 3fd59fe6..74b7c6b2 100644
--- a/tests/test_eum.py
+++ b/tests/test_eum.py
@@ -46,3 +46,10 @@ def test_create_info_with_type_only_positional():
 
     assert item.name == "Water Level"
     assert item.type == EUMType.Water_Level
+
+
+def test_eum_type_search():
+
+    types = EUMType.search("velocity")
+
+    assert len(types) > 0
Repository: DHI/mikeio
Pull request #307 (2022-03-30 16:54:46)

add geometry when combine datasets
add geometry to the combined dataset, otherwise _to_dfs() method with throw error, as it looks for geometry.


Patch:
diff --git a/mikeio/dataset.py b/mikeio/dataset.py
index 2993295a..a88764ac 100644
--- a/mikeio/dataset.py
+++ b/mikeio/dataset.py
@@ -915,7 +915,16 @@ class Dataset(DataUtilsMixin, TimeSeries, collections.abc.MutableMapping):
             newdata[j][idx1, :] = ds[j].to_numpy()
             newdata[j][idx2, :] = other[j].to_numpy()
 
-        return Dataset(newdata, newtime, ds.items)
+        zn = None
+        if self._zn is not None:
+            zshape = (len(newtime), self._zn.shape[1])
+            zn = np.zeros(shape=zshape, dtype=self._zn.dtype)
+            zn[idx1, :] = self._zn
+            zn[idx2, :] = other._zn
+
+        return Dataset(
+            newdata, time=newtime, items=ds.items, geometry=ds.geometry, zn=zn
+        )
 
     def _check_all_items_match(self, other):
         if self.n_items != other.n_items:


Test patch:
diff --git a/tests/test_dataset.py b/tests/test_dataset.py
index 017182a4..44afa0e6 100644
--- a/tests/test_dataset.py
+++ b/tests/test_dataset.py
@@ -1244,6 +1244,24 @@ def test_concat():
     assert ds3.n_timesteps == (ds1.n_timesteps + ds2.n_timesteps)
     assert ds3.start_time == ds1.start_time
     assert ds3.end_time == ds2.end_time
+    assert type(ds3.geometry) == type(ds1.geometry)
+    assert ds3.geometry.n_elements == ds1.geometry.n_elements
+
+
+def test_concat_dfsu3d():
+    filename = "tests/testdata/basin_3d.dfsu"
+    ds = mikeio.read(filename)
+    ds1 = mikeio.read(filename, time=[0, 1])
+    ds2 = mikeio.read(filename, time=[1, 2])
+    ds3 = ds1.concat(ds2)
+
+    assert ds1.n_items == ds2.n_items == ds3.n_items
+    assert ds3.start_time == ds.start_time
+    assert ds3.end_time == ds.end_time
+    assert type(ds3.geometry) == type(ds.geometry)
+    assert ds3.geometry.n_elements == ds1.geometry.n_elements
+    assert ds3._zn.shape == ds._zn.shape
+    assert np.all(ds3._zn == ds._zn)
 
 
 def test_append_items():
diff --git a/tests/test_dfs2.py b/tests/test_dfs2.py
index 429c8e84..79988a0d 100644
--- a/tests/test_dfs2.py
+++ b/tests/test_dfs2.py
@@ -567,6 +567,24 @@ def test_incremental_write_from_dfs2_context_manager(tmpdir):
     assert dfs.end_time == newdfs.end_time
 
 
+def test_read_concat_write_dfs2(tmp_path):
+    outfilename = tmp_path / "waves_concat.dfs2"
+
+    ds1 = mikeio.read("tests/testdata/waves.dfs2", time_steps=[0, 1])
+    # ds2 = mikeio.read("tests/testdata/waves.dfs2", time_steps=2) # dont do this, it will not work!
+    ds2 = mikeio.read("tests/testdata/waves.dfs2", time_steps=[2])
+    dsc = ds1.concat(ds2)
+    assert dsc.n_timesteps == 3
+    assert dsc.end_time == ds2.end_time
+    assert isinstance(dsc.geometry, Grid2D)
+    dsc.to_dfs(outfilename)
+
+    dsnew = mikeio.read(outfilename)
+    assert isinstance(dsnew.geometry, Grid2D)
+    assert dsnew.n_timesteps == 3
+    assert dsnew.end_time == ds2.end_time
+
+
 def test_spatial_aggregation_dfs2_to_dfs0(tmp_path):
 
     outfilename = tmp_path / "waves_max.dfs0"
Repository: DHI/mikeio
Pull request #352 (2022-05-24 11:12:31)

Concat ndim 1 Datasets


Patch:
diff --git a/mikeio/dataset.py b/mikeio/dataset.py
index bdfed8ab..4ebc2833 100644
--- a/mikeio/dataset.py
+++ b/mikeio/dataset.py
@@ -1051,6 +1051,10 @@ class Dataset(DataUtilsMixin, TimeSeries, collections.abc.MutableMapping):
         self._check_all_items_match(other)
         if not np.all(self.shape[1:] == other.shape[1:]):
             raise ValueError("Shape of the datasets must match (except time dimension)")
+        if "time" not in self.dims:
+            raise ValueError(
+                "Datasets cannot be concatenated as they have no time axis!"
+            )
         ds = self.copy() if copy else self
 
         s1 = pd.Series(np.arange(len(ds.time)), index=ds.time, name="idx1")
@@ -1065,8 +1069,8 @@ class Dataset(DataUtilsMixin, TimeSeries, collections.abc.MutableMapping):
         idx2 = np.where(~df12["idx2"].isna())
         for j in range(ds.n_items):
             # if there is an overlap "other" data will be used!
-            newdata[j][idx1, :] = ds[j].to_numpy()
-            newdata[j][idx2, :] = other[j].to_numpy()
+            newdata[j][idx1] = ds[j].to_numpy()
+            newdata[j][idx2] = other[j].to_numpy()
 
         zn = None
         if self._zn is not None:


Test patch:
diff --git a/tests/test_dataset.py b/tests/test_dataset.py
index 8432616f..d52edf96 100644
--- a/tests/test_dataset.py
+++ b/tests/test_dataset.py
@@ -1213,12 +1213,35 @@ def test_concat_by_time():
     assert ds3.n_timesteps == 145
     assert ds3.is_equidistant
 
-    ds4 = mikeio.Dataset.concat([ds1, ds2])
 
-    assert isinstance(ds4, mikeio.Dataset)
-    assert len(ds1) == len(ds2) == len(ds4)
-    assert ds4.start_time == ds1.start_time
-    assert ds4.end_time == ds2.end_time
+def test_concat_by_time_ndim1():
+    ds1 = mikeio.read("tests/testdata/tide1.dfs1").isel(x=0)
+    ds2 = mikeio.read("tests/testdata/tide2.dfs1").isel(x=0)
+    ds3 = mikeio.Dataset.concat([ds1, ds2])
+
+    assert isinstance(ds3, mikeio.Dataset)
+    assert len(ds1) == len(ds2) == len(ds3)
+    assert ds3.start_time == ds1.start_time
+    assert ds3.start_time < ds2.start_time
+    assert ds3.end_time == ds2.end_time
+    assert ds3.end_time > ds1.end_time
+    assert ds3.n_timesteps == 145
+    assert ds3.is_equidistant
+
+
+def test_concat_by_time_inconsistent_shape_not_possible():
+    ds1 = mikeio.read("tests/testdata/tide1.dfs1").isel(x=[0, 1])
+    ds2 = mikeio.read("tests/testdata/tide2.dfs1").isel(x=[0, 1, 2])
+    with pytest.raises(ValueError, match="Shape"):
+        mikeio.Dataset.concat([ds1, ds2])
+
+
+# TODO: implement this
+def test_concat_by_time_no_time():
+    ds1 = mikeio.read("tests/testdata/tide1.dfs1", time=0)
+    ds2 = mikeio.read("tests/testdata/tide2.dfs1", time=1)
+    with pytest.raises(ValueError, match="no time axis"):
+        mikeio.Dataset.concat([ds1, ds2])
 
 
 def test_concat_by_time_2():
Repository: DHI/mikeio
Pull request #371 (2022-06-23 12:36:01)

Fix reading vertical column in Dfsu3d


Patch:
diff --git a/mikeio/dfsu_layered.py b/mikeio/dfsu_layered.py
index dbc39fef..00ee5c01 100644
--- a/mikeio/dfsu_layered.py
+++ b/mikeio/dfsu_layered.py
@@ -191,7 +191,7 @@ class DfsuLayered(_Dfsu):
             n_nodes = self.n_nodes
             geometry = self.geometry
         else:
-            elements = [elements] if np.isscalar(elements) else elements
+            elements = list(elements)
             n_elems = len(elements)
             geometry = self.geometry.elements_to_geometry(elements)
             if self.is_layered:  # and items[0].name == "Z coordinate":


Test patch:
diff --git a/tests/test_dfsu_layered.py b/tests/test_dfsu_layered.py
index baac6a8a..d6bf07b2 100644
--- a/tests/test_dfsu_layered.py
+++ b/tests/test_dfsu_layered.py
@@ -145,6 +145,16 @@ def test_read_dfsu3d_column():
     assert dscol2._zn.shape == (ds.n_timesteps, 5 * 3)
 
 
+def test_read_dfsu3d_columns_sigma_only():
+    dfs = mikeio.open("tests/testdata/basin_3d.dfsu")
+    dscol = dfs.read(x=500, y=50)
+    assert isinstance(dscol.geometry, GeometryFMVerticalColumn)
+    assert dscol.n_elements == 10
+    assert dscol.n_items == dfs.n_items
+
+    assert dscol["U velocity"].isel(time=-1)[-1].values == pytest.approx(0.363413)
+
+
 def test_read_dfsu3d_xyz():
     filename = "tests/testdata/oresund_sigma_z.dfsu"
     dfs = mikeio.open(filename)
Repository: DHI/mikeio
Pull request #372 (2022-06-23 15:21:51)

Dfsu3d sel vertical column


Patch:
diff --git a/mikeio/spatial/FM_geometry.py b/mikeio/spatial/FM_geometry.py
index f528d1d9..70df5883 100644
--- a/mikeio/spatial/FM_geometry.py
+++ b/mikeio/spatial/FM_geometry.py
@@ -1191,6 +1191,7 @@ class GeometryFM(_Geometry):
         # create new geometry
         new_type = self._type
         if self.is_layered:
+            elements = list(elements)
             layers_used = self.layer_ids[elements]
             unique_layer_ids = np.unique(layers_used)
             n_layers = len(unique_layer_ids)
@@ -1514,7 +1515,7 @@ class _GeometryFMLayered(GeometryFM):
                 idx_3d = np.hstack(self.e2_e3_table[idx_2d])
             else:
                 idx_3d = self._find_elem3d_from_elem2d(idx_2d, z)
-            idx = np.intersect1d(idx, idx_3d)
+            idx = np.intersect1d(idx, idx_3d).astype(int)
         elif area is not None:
             idx_area = self._elements_in_area(area)
             idx = np.intersect1d(idx, idx_area)


Test patch:
diff --git a/tests/test_dfsu_layered.py b/tests/test_dfsu_layered.py
index d6bf07b2..d79ac12a 100644
--- a/tests/test_dfsu_layered.py
+++ b/tests/test_dfsu_layered.py
@@ -151,9 +151,11 @@ def test_read_dfsu3d_columns_sigma_only():
     assert isinstance(dscol.geometry, GeometryFMVerticalColumn)
     assert dscol.n_elements == 10
     assert dscol.n_items == dfs.n_items
-
     assert dscol["U velocity"].isel(time=-1)[-1].values == pytest.approx(0.363413)
 
+    dscol2 = dfs.read().sel(x=500, y=50)
+    assert dscol.shape == dscol2.shape
+
 
 def test_read_dfsu3d_xyz():
     filename = "tests/testdata/oresund_sigma_z.dfsu"
Repository: DHI/mikeio
Pull request #373 (2022-06-23 18:54:59)

Save vertical profile from sigma only dfsu 3d
Right after releasing v 1.0.2 I found another problem with profiles extracted from DfsuSigma files where number of sigma layers where incorrect and prevented saving them as a new Dfsu file.
![image](https://user-images.githubusercontent.com/614215/175378148-0d61620b-9e31-4178-bcdf-92aa4a2f84e9.png)



Patch:
diff --git a/mikeio/spatial/FM_geometry.py b/mikeio/spatial/FM_geometry.py
index 70df5883..81398ca5 100644
--- a/mikeio/spatial/FM_geometry.py
+++ b/mikeio/spatial/FM_geometry.py
@@ -1258,7 +1258,7 @@ class GeometryFM(_Geometry):
             else:
                 geom._type = self._type
                 geom._n_layers = n_layers
-                lowest_sigma = self.n_layers - self.n_sigma_layers + 1
+                lowest_sigma = self.n_layers - self.n_sigma_layers
                 geom._n_sigma = sum(unique_layer_ids >= lowest_sigma)
 
                 # If source is sigma-z but output only has sigma layers


Test patch:
diff --git a/tests/test_dfsu_layered.py b/tests/test_dfsu_layered.py
index d79ac12a..7f573809 100644
--- a/tests/test_dfsu_layered.py
+++ b/tests/test_dfsu_layered.py
@@ -145,6 +145,27 @@ def test_read_dfsu3d_column():
     assert dscol2._zn.shape == (ds.n_timesteps, 5 * 3)
 
 
+def test_read_dfsu3d_column_save(tmpdir):
+    filename = "tests/testdata/oresund_sigma_z.dfsu"
+    dfs = mikeio.open(filename)
+
+    (x, y) = (333934.1, 6158101.5)
+
+    ds = dfs.read(x=x, y=y)  # all data in file
+    assert ds.geometry.n_sigma_layers == 4
+    assert ds.geometry.n_z_layers == 0
+    outfilename = os.path.join(tmpdir, "new_column.dfsu")
+    ds.to_dfs(outfilename)
+
+    (x, y) = (347698.5188405, 6221233.34815)
+
+    ds = dfs.read(x=x, y=y)  # all data in file
+    assert ds.geometry.n_sigma_layers == 4
+    assert ds.geometry.n_z_layers == 4
+    outfilename = os.path.join(tmpdir, "new_column_2.dfsu")
+    ds.to_dfs(outfilename)
+
+
 def test_read_dfsu3d_columns_sigma_only():
     dfs = mikeio.open("tests/testdata/basin_3d.dfsu")
     dscol = dfs.read(x=500, y=50)
@@ -157,6 +178,17 @@ def test_read_dfsu3d_columns_sigma_only():
     assert dscol.shape == dscol2.shape
 
 
+def test_read_dfsu3d_columns_sigma_only_save(tmpdir):
+    dfs = mikeio.open("tests/testdata/basin_3d.dfsu")
+    assert dfs.geometry.n_sigma_layers == 10
+    assert dfs.geometry.n_z_layers == 0
+    dscol = dfs.read(x=500, y=50)
+    assert dscol.geometry.n_sigma_layers == 10
+    assert dscol.geometry.n_z_layers == 0
+    outfilename = os.path.join(tmpdir, "new_column.dfsu")
+    dscol.to_dfs(outfilename)
+
+
 def test_read_dfsu3d_xyz():
     filename = "tests/testdata/oresund_sigma_z.dfsu"
     dfs = mikeio.open(filename)
Repository: DHI/mikeio
Pull request #392 (2022-07-27 08:48:34)

dfsu3d to_mesh fix
It was previously not possible to write a 3d GeometryFM object to a new mesh file. This PR fixes this. Thanks to @lezhongwen for pointing this out in https://github.com/DHI/mikeio/discussions/391. 


Patch:
diff --git a/mikeio/spatial/FM_geometry.py b/mikeio/spatial/FM_geometry.py
index 81398ca5..0024ed78 100644
--- a/mikeio/spatial/FM_geometry.py
+++ b/mikeio/spatial/FM_geometry.py
@@ -1388,16 +1388,24 @@ class GeometryFM(_Geometry):
         return mp
 
     def to_mesh(self, outfilename):
+        """Export geometry to new mesh file
 
+        Parameters
+        ----------
+        outfilename : str
+            path to file to be written
+        """
         builder = MeshBuilder()
 
-        nc = self.node_coordinates
-        builder.SetNodes(nc[:, 0], nc[:, 1], nc[:, 2], self.codes)
-        # builder.SetNodeIds(self.node_ids+1)
-        # builder.SetElementIds(self.elements+1)
-        element_table_MZ = [np.asarray(row) + 1 for row in self.element_table]
+        geom2d = self._geometry2d
+
+        nc = geom2d.node_coordinates
+        builder.SetNodes(nc[:, 0], nc[:, 1], nc[:, 2], geom2d.codes)
+        # builder.SetNodeIds(geom2d.node_ids+1)
+        # builder.SetElementIds(geom2d.elements+1)
+        element_table_MZ = [np.asarray(row) + 1 for row in geom2d.element_table]
         builder.SetElements(element_table_MZ)
-        builder.SetProjection(self.projection_string)
+        builder.SetProjection(geom2d.projection_string)
         quantity = eumQuantity.Create(EUMType.Bathymetry, EUMUnit.meter)
         builder.SetEumQuantity(quantity)
         newMesh = builder.CreateMesh()


Test patch:
diff --git a/tests/test_dfsu_layered.py b/tests/test_dfsu_layered.py
index 7f573809..4f3bd2cd 100644
--- a/tests/test_dfsu_layered.py
+++ b/tests/test_dfsu_layered.py
@@ -522,15 +522,15 @@ def test_to_mesh_3d(tmpdir):
 
     dfs = mikeio.open(filename)
 
-    outfilename = os.path.join(tmpdir, "oresund.mesh")
-
+    outfilename = os.path.join(tmpdir, "oresund_from_dfs.mesh")
     dfs.to_mesh(outfilename)
-
     assert os.path.exists(outfilename)
-
     mesh = Mesh(outfilename)
 
-    assert True
+    outfilename = os.path.join(tmpdir, "oresund_from_geometry.mesh")
+    dfs.geometry.to_mesh(outfilename)
+    assert os.path.exists(outfilename)
+    mesh = Mesh(outfilename)
 
 
 def test_extract_surface_elevation_from_3d(tmpdir):
Repository: DHI/mikeio
Pull request #393 (2022-07-27 13:41:03)

Fix top elements 3d dfsu subset
Algorithm for finding dfsu3d top_elements after subsetting was missing the last top element. This PR fixes this. 


Patch:
diff --git a/mikeio/spatial/FM_geometry.py b/mikeio/spatial/FM_geometry.py
index 81398ca5..0eb7b24b 100644
--- a/mikeio/spatial/FM_geometry.py
+++ b/mikeio/spatial/FM_geometry.py
@@ -1270,30 +1270,10 @@ class GeometryFM(_Geometry):
                     # TODO fix this
                     geom._type = DfsuFileType.Dfsu3DSigma
 
-                geom._top_elems = geom._get_top_elements_from_coordinates()
+                geom._top_elems = geom._findTopLayerElements(geom.element_table)
 
         return geom
 
-    def _get_top_elements_from_coordinates(self, ec=None):
-        """Get list of top element ids based on element coordinates"""
-        if ec is None:
-            ec = self.element_coordinates
-
-        d_eps = 1e-4
-        top_elems = []
-        x_old = ec[0, 0]
-        y_old = ec[0, 1]
-        for j in range(1, len(ec)):
-            d2 = (ec[j, 0] - x_old) ** 2 + (ec[j, 1] - y_old) ** 2
-            # print(d2)
-            if d2 > d_eps:
-                # this is a new x,y point
-                # then the previous element must be a top element
-                top_elems.append(j - 1)
-            x_old = ec[j, 0]
-            y_old = ec[j, 1]
-        return np.array(top_elems)
-
     def _get_nodes_and_table_for_elements(self, elements, node_layers="all"):
         """list of nodes and element table for a list of elements
 


Test patch:
diff --git a/tests/test_dfsu_layered.py b/tests/test_dfsu_layered.py
index 7f573809..59165df0 100644
--- a/tests/test_dfsu_layered.py
+++ b/tests/test_dfsu_layered.py
@@ -391,6 +391,22 @@ def test_top_elements():
     assert not hasattr(dfs, "top_elements")
 
 
+def test_top_elements_subset():
+    filename = os.path.join("tests", "testdata", "oresund_sigma_z.dfsu")
+    g3d = mikeio.open(filename).geometry
+    g2d = g3d.geometry2d
+
+    area = [356000, 6144000, 359000, 6146000]
+    idx2d = g2d.find_index(area=area)
+    assert len(idx2d) == 6
+    assert idx2d[-1] == 3408
+
+    idx3d = g3d.find_index(area=area)
+    subg = g3d.isel(idx3d)
+
+    assert len(subg.top_elements) == 6
+
+
 def test_bottom_elements():
     filename = os.path.join("tests", "testdata", "basin_3d.dfsu")
     dfs = mikeio.open(filename)
Repository: DHI/mikeio
Pull request #405 (2022-08-26 12:01:51)

Convenience method to create a new DataArray


Patch:
diff --git a/mikeio/dataset.py b/mikeio/dataset.py
index 594568d1..030d75e3 100644
--- a/mikeio/dataset.py
+++ b/mikeio/dataset.py
@@ -518,6 +518,22 @@ class Dataset(DataUtilsMixin, TimeSeries, collections.abc.MutableMapping):
 
         return Dataset(data=res, validate=False)
 
+    def create_data_array(self, data, item=None) -> DataArray:
+        """Create a new  DataArray with the same time and geometry as the dataset
+
+        Examples
+        --------
+
+        >>> ds = mikeio.read("file.dfsu")
+        >>> values = np.zeros(ds.Temperature.shape)
+        >>> da = ds.create_data_array(values)
+        >>> da_name = ds.create_data_array(values,"Foo")
+        >>> da_eum = ds.create_data_array(values, item=mikeio.ItemInfo("TS", mikeio.EUMType.Temperature))
+        """
+        return DataArray(
+            data=data, time=self.time, geometry=self.geometry, zn=self._zn, item=item
+        )
+
     # TODO: delete this?
     @staticmethod
     def create_empty_data(n_items=1, n_timesteps=1, n_elements=None, shape=None):


Test patch:
diff --git a/tests/test_dataset.py b/tests/test_dataset.py
index 22d506cb..4ea1f572 100644
--- a/tests/test_dataset.py
+++ b/tests/test_dataset.py
@@ -1481,3 +1481,33 @@ def test_create_dataset_with_many_items():
     ds = mikeio.Dataset(das)
 
     assert ds.n_items == n_items
+
+
+def test_create_array_with_defaults_from_dataset():
+
+    filename = "tests/testdata/oresund_sigma_z.dfsu"
+    ds: mikeio.Dataset = mikeio.read(filename)
+
+    values = np.zeros(ds.Temperature.shape)
+
+    da = ds.create_data_array(values)
+
+    assert isinstance(da, mikeio.DataArray)
+    assert da.geometry == ds.geometry
+    assert all(da.time == ds.time)
+    assert da.item.type == mikeio.EUMType.Undefined
+
+    da_name = ds.create_data_array(values, "Foo")
+
+    assert isinstance(da, mikeio.DataArray)
+    assert da_name.geometry == ds.geometry
+    assert da_name.item.type == mikeio.EUMType.Undefined
+    assert da_name.name == "Foo"
+
+    da_eum = ds.create_data_array(
+        values, item=mikeio.ItemInfo("TS", mikeio.EUMType.Temperature)
+    )
+
+    assert isinstance(da_eum, mikeio.DataArray)
+    assert da_eum.geometry == ds.geometry
+    assert da_eum.item.type == mikeio.EUMType.Temperature
Repository: DHI/mikeio
Pull request #443 (2022-10-04 14:13:36)

Pfs take first of repeated keywords
MIKE FM does not use repeated keywords. If the same keyword is defined in a section, the first one will be read. MIKE IO should have the same behaviour.


Patch:
diff --git a/mikeio/pfs.py b/mikeio/pfs.py
index 10d80fce..f5ea8616 100644
--- a/mikeio/pfs.py
+++ b/mikeio/pfs.py
@@ -203,8 +203,11 @@ def parse_yaml_preserving_duplicates(src, unique_keywords=True):
                         data[key] = []
                     data[key].append(val)
                 else:
-                    warnings.warn(f"Keyword {key} defined multiple times. Value: {val}")
-                    data[key] = val
+                    warnings.warn(
+                        f"Keyword {key} defined multiple times (first will be used). Value: {val}"
+                    )
+                    if key not in data:
+                        data[key] = val
             else:
                 data[key] = val
         return data


Test patch:
diff --git a/tests/test_pfs.py b/tests/test_pfs.py
index 1bf1e42e..33d6ac0e 100644
--- a/tests/test_pfs.py
+++ b/tests/test_pfs.py
@@ -375,8 +375,8 @@ def test_non_unique_keywords():
     assert len(pfs.BoundaryExtractor.POINT_1) == 2
     assert isinstance(pfs.BoundaryExtractor.POINT_1[1], mikeio.PfsSection)
 
-    # last value will be kept
-    assert pfs.BoundaryExtractor.z_min == 19
+    # first value will be kept (like MIKE FM)
+    assert pfs.BoundaryExtractor.z_min == -3000
 
 
 def test_non_unique_keywords_allowed():