DHI / mikeio

Read, write and manipulate dfs0, dfs1, dfs2, dfs3, dfsu and mesh files.
https://dhi.github.io/mikeio
BSD 3-Clause "New" or "Revised" License
138 stars 55 forks source link

small inconcistency in time dimension for time-invariant data arrays? #643

Closed Hendrik1987 closed 7 months ago

Hendrik1987 commented 8 months ago

Selecting one time step and averaging over time both result in time-invariant dataarrays - so far so good. But the former seems to have dimension time = 1 and the latter has no time dimension. Here the example for Grid2D, which broke my to .tiff conversion for the 2nd case.

image

Is there a reasoning behind this behaviour, which I am overlooking? Thanks!

System information:

ecomodeller commented 8 months ago

@Hendrik1987 how did you select in time? I get no time dimension.

>>> ds = mikeio.read("waves.dfs2")
>>> ds
<mikeio.Dataset>
dims: (time:3, y:31, x:31)
time: 2004-01-01 00:00:00 - 2004-01-03 00:00:00 (3 records)
geometry: Grid2D (ny=31, nx=31)
items:
  0:  Sign. Wave Height <Significant wave height> (meter)
  1:  Peak Wave Period <Wave period> (second)
  2:  Mean Wave Direction <Mean Wave Direction> (degree)
>>> ds.isel(time=0)
<mikeio.Dataset>
dims: (y:31, x:31)
time: 2004-01-01 00:00:00 (time-invariant)
geometry: Grid2D (ny=31, nx=31)
items:
  0:  Sign. Wave Height <Significant wave height> (meter)
  1:  Peak Wave Period <Wave period> (second)
  2:  Mean Wave Direction <Mean Wave Direction> (degree)
>>> ds = mikeio.read("waves.dfs2",time=0)
>>> ds
<mikeio.Dataset>
dims: (y:31, x:31)
time: 2004-01-01 00:00:00 (time-invariant)
geometry: Grid2D (ny=31, nx=31)
items:
  0:  Sign. Wave Height <Significant wave height> (meter)
  1:  Peak Wave Period <Wave period> (second)
  2:  _Mean_ Wave Direction <Mean Wave Direction> (degree)
ds.sel(time="2004-01-01")
<mikeio.Dataset>
dims: (y:31, x:31)
time: 2004-01-01 00:00:00 (time-invariant)
geometry: Grid2D (ny=31, nx=31)
items:
  0:  Sign. Wave Height <Significant wave height> (meter)
  1:  Peak Wave Period <Wave period> (second)
  2:  Mean Wave Direction <Mean Wave Direction> (degree)
>>>
Hendrik1987 commented 7 months ago

Sorry for the incomplete / incorrect report @ecomodeller It actually does not happen during time select or aggregation, but when reading a time-invariant dfsu: image

ecomodeller commented 7 months ago

Sorry for the incomplete / incorrect report @ecomodeller It actually does not happen during time select or aggregation, but when reading a time-invariant dfsu: image

That is by design. If you know you are expect a time-invariant dfs file, you can do mikeio.read("time-invariant.dfsu", time=0).

In a NetCdf file you can be explicit about the dimensions, e.g. time can be a dimension with a single timestep, or have no time dimension, but in a dfs file, there will always be a start_time even if we want to interpret the file as time invariant.

It is a not easy to come up with a good design for singleton dimensions, but I hope this is good enough.

Hendrik1987 commented 7 months ago

Your suggestion mikeio.read("time-invariant.dfsu", time=0) works.

Both, ds and ds2 above carry the information on the first time step, or not? Only the array shape is different.

I personaly would expect a behaviour where after write and read ds2 is the same as ds. But the current design is definetely good enough!

ecomodeller commented 7 months ago

We are considering ways to improve consistency with xarray, currently experimenting with a dfs engine for dfs{2,3].

It could be as simple as:

import xarray as xr
import mikeio

ds = xr.open_dataset("some_meteo.dfs2", engine="mikeio")

That would be great for structured data, but I am still searching for the optimal solution for unstructured meshes, let me know if you have any suggestion.

Hendrik1987 commented 7 months ago

You likely know that this topic is also realized by xarray: https://docs.xarray.dev/en/stable/roadmap.html#specific-needs Maybe also worth to look at xarray extension approach by Deltares: https://github.com/Deltares/xugrid

In general, I find your geometry approach in mikeio much tidier than having additional dimensions like x_nodes etc. to store the mesh in the same ds. But keeping it seperate will require to also modify the geometry for all the .sel and aggregation methods. So, unfortunately no, no really good ideas right now from my end. But I am happy to test and contribute once your experiments mature :-)