Skip to content

Commit

Permalink
comments Davíd
Browse files Browse the repository at this point in the history
  • Loading branch information
OnnoEbbens committed Oct 11, 2024
1 parent 4a50762 commit 8682e27
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 66 deletions.
95 changes: 41 additions & 54 deletions nlmod/dims/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,61 +243,48 @@ def set_ds_time(
if isinstance(time, str) or not hasattr(time, "__iter__"):
time = [time]

# parse start
if isinstance(start, (int, np.integer, float)):
if isinstance(time[0], (int, np.integer, float, str)):
raise TypeError("Make sure 'start' or 'time' argument is a valid TimeStamp")
try:
start = time[0] - pd.to_timedelta(start, "D")
except (OutOfBoundsDatetime, OutOfBoundsTimedelta) as e:
msg = f"using cftime time index because of {e}"
logger.debug(msg)
time = _pd_timestamp_to_cftime(time)
start = time[0] - dt.timedelta(days=start)
elif isinstance(start, str):
start = pd.Timestamp(start)
elif isinstance(start, (pd.Timestamp, cftime.datetime)):
pass
elif isinstance(start, np.datetime64):
start = pd.Timestamp(start)
else:
raise TypeError("Cannot parse start datetime.")

# parse time make sure 'time' and 'start' are same type (pd.Timestamps or cftime.datetime)
if isinstance(time[0], (int, np.integer, float)):
if isinstance(start, cftime.datetime):
time = [start + dt.timedelta(days=int(td)) for td in time]
try:
# parse start
if isinstance(start, (int, np.integer, float)):
if isinstance(time[0], (int, np.integer, float, str)):
raise TypeError("Make sure 'start' or 'time' argument is a valid TimeStamp")
elif isinstance(start, str):
start = pd.Timestamp(start)
elif isinstance(start, (pd.Timestamp, cftime.datetime)):
pass
elif isinstance(start, np.datetime64):
start = pd.Timestamp(start)
else:
try:
time = start + pd.to_timedelta(time, time_units)
except (OutOfBoundsDatetime, OutOfBoundsTimedelta) as e:
msg = f"using cftime time index because of {e}"
logger.debug(msg)
start = _pd_timestamp_to_cftime(start)
raise TypeError("Cannot parse start datetime.")

# parse time make sure 'time' and 'start' are same type (pd.Timestamps or cftime.datetime)
if isinstance(time[0], (int, np.integer, float)):
if isinstance(start, cftime.datetime):
time = [start + dt.timedelta(days=int(td)) for td in time]
elif isinstance(time[0], str):
try:
else:
time = start + pd.to_timedelta(time, time_units)
elif isinstance(time[0], str):
time = pd.to_datetime(time)
if isinstance(start, cftime.datetime):
time = _pd_timestamp_to_cftime(time)
except (OutOfBoundsDatetime, OutOfBoundsTimedelta) as e:
msg = f"Cannot process time argument combined with out of bound start {start}. Please use any of these types for the time or perlen argument: int, float, pd.Timestamp, np.datetime64, cftime.datetime"
raise TypeError(msg) from e
elif isinstance(time[0], (pd.Timestamp)):
if isinstance(start, cftime.datetime):
time = _pd_timestamp_to_cftime(time)
elif isinstance(time[0], (np.datetime64, xr.core.variable.Variable)):
logger.info(
"time arguments with types np.datetime64, xr.core.variable.Variable not tested!"
)
pass
elif isinstance(time[0], cftime.datetime):
start = _pd_timestamp_to_cftime(start)
else:
msg = (
f"Cannot process 'time' argument. Datatype -> {type(time)} not understood."
)
raise TypeError(msg)
elif isinstance(time[0], (pd.Timestamp)):
if isinstance(start, cftime.datetime):
time = _pd_timestamp_to_cftime(time)
elif isinstance(time[0], (np.datetime64, xr.core.variable.Variable)):
logger.info(
"time arguments with types np.datetime64, xr.core.variable.Variable not tested!"
)
pass
elif isinstance(time[0], cftime.datetime):
start = _pd_timestamp_to_cftime(start)
else:
msg = (
f"Cannot process 'time' argument. Datatype -> {type(time)} not understood."
)
raise TypeError(msg)
except (OutOfBoundsDatetime, OutOfBoundsTimedelta) as e:
msg = f"cannot convert 'start' and 'time' to pandas datetime, use cftime types for 'start' and 'time'"
raise type(e)(msg)

if time[0] <= start:
msg = (
Expand All @@ -319,7 +306,7 @@ def set_ds_time(
return ds


def set_ds_time_numerical(
def set_ds_time_numeric(
ds,
start,
time=None,
Expand Down Expand Up @@ -436,8 +423,8 @@ def set_time_variables(ds, start, time, steady, steady_start, time_units, nstp,
Returns
-------
_type_
_description_
ds : xarray.Dataset
model dataset with attributes added to the time coordinates
"""
# add steady, nstp and tsmult to dataset
if isinstance(steady, bool):
Expand Down Expand Up @@ -764,7 +751,7 @@ def ds_time_to_pandas_index(ds, include_start=True):
pandas datetime index
"""
if include_start:
if ds.time.dtype.kind == "M":
if ds.time.dtype.kind == "M": # "M" is a numpy datetime-type
return ds.time.to_index().insert(0, pd.Timestamp(ds.time.start))
elif ds.time.dtype.kind == "O":
start = _pd_timestamp_to_cftime(pd.Timestamp(ds.time.start))
Expand Down
4 changes: 2 additions & 2 deletions nlmod/gwf/surface_water.py
Original file line number Diff line number Diff line change
Expand Up @@ -1111,8 +1111,8 @@ def add_season_timeseries(
summer_name : str, optional
The name of the time-series with ones in summer. The default is "summer".
"""
if ds.time.dtype.kind in ['i','f','O']:
raise TypeError('add_season_timeseries requires a datetime64[ns] time index')
if ds.time.dtype.kind != "M":
raise TypeError("add_season_timeseries requires a datetime64[ns] time index")
tmin = pd.to_datetime(ds.time.start)
if tmin.month in summer_months:
ts_data = [(0.0, 0.0, 1.0)]
Expand Down
2 changes: 1 addition & 1 deletion nlmod/mfoutput/mfoutput.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def _get_time_index(fobj, ds=None, gwf_or_gwt=None):
fobj.get_times(),
start_datetime=(ds.time.attrs["start"] if "time" in ds else None),
time_units=(ds.time.attrs["time_units"] if "time" in ds else None),
dtype='float' if ds.time.dtype.kind in ['i', 'f'] else 'datetime'
dtype="float" if ds.time.dtype.kind in ["i", "f"] else "datetime",
)
return tindex

Expand Down
4 changes: 2 additions & 2 deletions nlmod/read/bro.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ def add_modelled_head(oc, ml=None, ds=None, method="linear"):

# this function requires a flopy model object, see
# https://github.com/ArtesiaWater/hydropandas/issues/146
if ds.time.dtype.kind != 'M':
raise TypeError('add modelled head requires a datetime64[ns] time index')
if ds.time.dtype.kind != "M":
raise TypeError("add modelled head requires a datetime64[ns] time index")

oc_modflow = hpd.read_modflow(oc, ml, heads.values, ds.time.values, method=method)

Expand Down
4 changes: 2 additions & 2 deletions nlmod/read/knmi.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ def get_recharge(ds, method="linear", most_common_station=False):
"Please run nlmod.time.set_ds_time()"
)
)
if ds.time.dtype.kind != 'M':
raise TypeError('get recharge requires a datetime64[ns] time index')
if ds.time.dtype.kind != "M":
raise TypeError("get recharge requires a datetime64[ns] time index")

start = pd.Timestamp(ds.time.attrs["start"])
end = pd.Timestamp(ds.time.data[-1])
Expand Down
3 changes: 2 additions & 1 deletion nlmod/sim/sim.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ def get_tdis_perioddata(ds, nstp="nstp", tsmult="tsmult"):
if len(ds["time"]) > 1:
perlen.extend(np.diff(ds["time"]) / deltat)
elif ds.time.dtype.kind in ["i", "f"]:
perlen = ds["time"].values
perlen = [ds['time'][0]]
perlen.extent(np.diff(ds["time"].values))

nstp = util._get_value_from_ds_datavar(ds, "nstp", nstp, return_da=False)

Expand Down
9 changes: 5 additions & 4 deletions tests/test_016_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,14 @@ def test_time_out_of_bounds():
with pytest.raises(TypeError):
nlmod.dims.set_ds_time(ds, start=96500, time="1000-01-01")


def test_numerical_time_index():

ds = nlmod.get_ds([0, 1000, 2000, 3000])

# start str and time floats
_ = nlmod.dims.set_ds_time_numerical(ds, start='2000-1-1', time=[10.,20.,30.1])
_ = nlmod.dims.set_ds_time_numerical(ds, start="2000-1-1", time=[10.0, 20.0, 30.1])

# start timestamp and time ints
_ = nlmod.dims.set_ds_time_numerical(ds, start=pd.Timestamp("1000-01-01"),
time=[10,20,30])
_ = nlmod.dims.set_ds_time_numerical(
ds, start=pd.Timestamp("1000-01-01"), time=[10, 20, 30]
)

0 comments on commit 8682e27

Please sign in to comment.