import numpy as np
import pandas as pd
import mikeio
from mikeio import ItemInfo, EUMType, EUMUnit
Write a dfs0
A mikeio.Dataset contains the information needed to write a dfs file. A Dataset consists of one or more mikeio.DataArrays each corresponding to an “item” in a dfs file.
= 10
nt = pd.date_range("2000-1-1", periods=nt, freq='H')
time
= np.zeros(nt)
d1 = ItemInfo("Zeros", EUMType.Water_Level)
item = mikeio.DataArray(d1, time=time, item=item)
da1
= np.ones(nt)
d2 = ItemInfo("Ones", EUMType.Discharge, EUMUnit.meter_pow_3_per_sec)
item = mikeio.DataArray(d2, time=time, item=item)
da2
= mikeio.Dataset([da1, da2])
ds ds
<mikeio.Dataset>
dims: (time:10)
time: 2000-01-01 00:00:00 - 2000-01-01 09:00:00 (10 records)
items:
0: Zeros <Water Level> (meter)
1: Ones <Discharge> (meter pow 3 per sec)
ds.is_equidistant
True
"test.dfs0", title="Zeros and ones") ds.to_dfs(
Read a timeseries
A dfs file is easily read with mikeio.read which returns a Dataset.
= mikeio.read("test.dfs0")
ds ds
<mikeio.Dataset>
dims: (time:10)
time: 2000-01-01 00:00:00 - 2000-01-01 09:00:00 (10 records)
items:
0: Zeros <Water Level> (meter)
1: Ones <Discharge> (meter pow 3 per sec)
From comma separated file
= pd.read_csv("../tests/testdata/co2-mm-mlo.csv", parse_dates=True, index_col='Date', na_values=-99.99)
df df.head()
Decimal Date | Average | Interpolated | Trend | Number of Days | |
---|---|---|---|---|---|
Date | |||||
1958-03-01 | 1958.208 | 315.71 | 315.71 | 314.62 | -1 |
1958-04-01 | 1958.292 | 317.45 | 317.45 | 315.29 | -1 |
1958-05-01 | 1958.375 | 317.50 | 317.50 | 314.71 | -1 |
1958-06-01 | 1958.458 | NaN | 317.10 | 314.85 | -1 |
1958-07-01 | 1958.542 | 315.86 | 315.86 | 314.98 | -1 |
Remove missing values
= df.dropna()
df = df[["Average","Trend"]]
df df.plot()
<AxesSubplot: xlabel='Date'>
A dataframe with a datetimeindex can be used to create a dfs 0 with a non-equidistant time axis.
"mauna_loa_co2.dfs0") df.to_dfs0(
To get a equidistant time axis first interpolate to hourly values.
= df.resample('h').interpolate() df_h
"mauna_loa_co2_eq_1hr.dfs0") df_h.to_dfs0(
Read a timeseries
= mikeio.read("test.dfs0")
res res
<mikeio.Dataset>
dims: (time:10)
time: 2000-01-01 00:00:00 - 2000-01-01 09:00:00 (10 records)
items:
0: Zeros <Water Level> (meter)
1: Ones <Discharge> (meter pow 3 per sec)
res.time
DatetimeIndex(['2000-01-01 00:00:00', '2000-01-01 01:00:00',
'2000-01-01 02:00:00', '2000-01-01 03:00:00',
'2000-01-01 04:00:00', '2000-01-01 05:00:00',
'2000-01-01 06:00:00', '2000-01-01 07:00:00',
'2000-01-01 08:00:00', '2000-01-01 09:00:00'],
dtype='datetime64[ns]', freq=None)
res.to_numpy()
array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]])
Or as a Pandas dataframe
A mikeio.Dataset ds is converted to a pandas dataframe with ds.to_dataframe()
= "../tests/testdata/da_diagnostic.dfs0"
dfs0file = mikeio.read(dfs0file).to_dataframe()
df df.head()
State 1Sign. Wave Height | State 2Sign. Wave Height | Mean StateSign. Wave Height | MeasurementSign. Wave Height | |
---|---|---|---|---|
2017-10-27 00:00:00 | 1.749465 | 1.749465 | 1.749465 | 1.72 |
2017-10-27 00:10:00 | 1.811340 | 1.796895 | 1.807738 | NaN |
2017-10-27 00:20:00 | 1.863424 | 1.842759 | 1.853422 | NaN |
2017-10-27 00:30:00 | 1.922261 | 1.889839 | 1.897670 | NaN |
2017-10-27 00:40:00 | 1.972455 | 1.934886 | 1.935281 | NaN |
= "../tests/testdata/random.dfs0"
dfs0file = mikeio.read(dfs0file).to_dataframe()
df df.head()
VarFun01 | NotFun | |
---|---|---|
2017-01-01 00:00:00 | 0.843547 | 0.640486 |
2017-01-01 05:00:00 | 0.093729 | 0.653257 |
2017-01-01 10:00:00 | NaN | NaN |
2017-01-01 15:00:00 | 0.305065 | 0.214208 |
2017-01-01 20:00:00 | 0.900190 | 0.999157 |
Create a timeseries with non-equidistant data
= np.random.uniform(low=0.0, high=5.0, size=5)
d1 = pd.DatetimeIndex(["2000-1-1", "2000-1-8", "2000-1-10", "2000-2-22", "2000-11-29"])
time = mikeio.DataArray(d1, time=time, item=ItemInfo("Random"))
da da
<mikeio.DataArray>
name: Random
dims: (time:5)
time: 2000-01-01 00:00:00 - 2000-11-29 00:00:00 (5 non-equidistant records)
values: [3.747, 2.771, ..., 2.366]
da.is_equidistant
False
"neq.dfs0", title="Non equidistant") da.to_dfs(
Create a timeseries with accumulated timestep
Find correct eum units
"prec") EUMType.search(
[Correction of precipitation,
Precipitation correction,
Precipitation,
Specific Precipitation,
Precipitation Rate]
EUMType.Precipitation_Rate.units
[mm per day,
mm per hour,
cm per hour,
meter per sec,
meter per day,
feet per day,
inch per hour,
inch per min,
inch per day,
mm per year]
from mikecore.DfsFile import DataValueType
= 1000
n= pd.date_range("2017-01-01 00:00", freq='H', periods=n)
time
# use default name and unit based on type
= ItemInfo(EUMType.Water_Level, data_value_type=DataValueType.Instantaneous)
item = mikeio.DataArray(data=np.random.random([n]), time=time, item=item)
da1
# use a custom name
= ItemInfo("Nedbør", EUMType.Precipitation_Rate, data_value_type=DataValueType.Accumulated)
item = mikeio.DataArray(data=np.random.random([n]), time=time, item=item)
da2
= mikeio.Dataset([da1, da2])
ds 'accumulated.dfs0') ds.to_dfs(
= mikeio.read("accumulated.dfs0")
ds ds
<mikeio.Dataset>
dims: (time:1000)
time: 2017-01-01 00:00:00 - 2017-02-11 15:00:00 (1000 records)
items:
0: Water Level <Water Level> (meter)
1: Nedbør <Precipitation Rate> (mm per day) - 1
Modify an existing timeseries
= mikeio.read("test.dfs0")
ds ds
<mikeio.Dataset>
dims: (time:10)
time: 2000-01-01 00:00:00 - 2000-01-01 09:00:00 (10 records)
items:
0: Zeros <Water Level> (meter)
1: Ones <Discharge> (meter pow 3 per sec)
'Ones'] ds[
<mikeio.DataArray>
name: Ones
dims: (time:10)
time: 2000-01-01 00:00:00 - 2000-01-01 09:00:00 (10 records)
values: [1, 1, ..., 1]
Modify the data in some way…
'Ones'] = ds['Ones']*np.pi
ds['Ones'].values ds[
array([3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265,
3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265])
"modified.dfs0") ds.to_dfs(
= mikeio.read("modified.dfs0")
res 'Ones'] res[
<mikeio.DataArray>
name: Ones
dims: (time:10)
time: 2000-01-01 00:00:00 - 2000-01-01 09:00:00 (10 records)
values: [3.142, 3.142, ..., 3.142]
The second item is not modified.
'Zeros'] res[
<mikeio.DataArray>
name: Zeros
dims: (time:10)
time: 2000-01-01 00:00:00 - 2000-01-01 09:00:00 (10 records)
values: [0, 0, ..., 0]
Convert units
Read a file with waterlevel i meters.
= "../tests/testdata/waterlevel_viken.dfs0"
filename # filename = r"C:\Program Files (x86)\DHI\MIKE Zero\2021\Examples\MIKE_21\FlowModel_FM\HD\Oresund\Data\1993\Boundary_Conditions\waterlevel_viken.dfs0"
= mikeio.read(filename)
ds ds
<mikeio.Dataset>
dims: (time:577)
time: 1993-12-02 00:00:00 - 1993-12-14 00:00:00 (577 records)
items:
0: ST 2: WL (m) <Water Level> (meter)
ds.plot()
The aim is to convert this timeseries to feet (1m = 3.3 ft)
0] = ds[0]*3.3 ds[
Which units are acceptable?
0].type.units ds.items[
[meter,
kilometer,
centimeter,
millimeter,
feet,
feet US,
inch,
inch US,
mile,
mile US,
yard,
yard US]
0].item = ItemInfo("Viken", ds[0].item.type, EUMUnit.feet) ds[
"wl_feet.dfs0") ds.to_dfs(
Extrapolation
# filename = r"C:\Program Files (x86)\DHI\MIKE Zero\2021\Examples\MIKE_21\FlowModel_FM\HD\Oresund\Data\1993\Boundary_Conditions\waterlevel_viken.dfs0"
= "../tests/testdata/waterlevel_viken.dfs0"
filename = mikeio.read(filename)
ds = ds.to_dataframe()
df df.plot()
<AxesSubplot: >
= pd.date_range("1993-12-1","1994-1-1",freq='30t')
rng = pd.DatetimeIndex(rng)
ix = df.reindex(ix)
dfr dfr.plot()
<AxesSubplot: >
Replace NaN with constant extrapolation (forward fill + back fill).
= dfr.ffill().bfill()
dfr dfr.plot()
<AxesSubplot: >
"Viken_extrapolated.dfs0",
dfr.to_dfs0(=ds.items,
items="Caution extrapolated data!"
title )
Clean up
import os
"test.dfs0")
os.remove("modified.dfs0")
os.remove("neq.dfs0")
os.remove("accumulated.dfs0")
os.remove("wl_feet.dfs0")
os.remove("mauna_loa_co2_eq_1hr.dfs0")
os.remove("mauna_loa_co2.dfs0")
os.remove("Viken_extrapolated.dfs0") os.remove(