neural_lam.utils.time#

Time-delta conversion and interior/boundary time-axis alignment.

Functions#

apply_time_crop(→ xarray.DataArray)

Apply a get_time_crop_slice() result to da, logging removals.

get_integer_time(→ tuple[int, str])

Express a datetime.timedelta as an integer number of time units.

get_time_crop_slice(→ tuple[str, slice])

Return the da_requested dimension and slice da_available covers.

get_time_step(→ numpy.timedelta64)

Calculate the (constant) time step from a 1D time array.

Module Contents#

neural_lam.utils.time.apply_time_crop(da: xarray.DataArray, crop_dim: str, crop_slice: slice) → xarray.DataArray[source]#

Apply a get_time_crop_slice() result to da, logging removals.

Parameters:
  • da (xr.DataArray) – Dataarray to crop.

  • crop_dim (str) – Dimension to crop along.

  • crop_slice (slice) – Positional slice to keep.

Returns:

da cropped, or unchanged when the slice keeps everything.

Return type:

xr.DataArray

neural_lam.utils.time.get_integer_time(tdelta: datetime.timedelta) → tuple[int, str][source]#

Express a datetime.timedelta as an integer number of time units.

Parameters:

tdelta (datetime.timedelta) – The time interval to convert.

Returns:

  • int – Integer value of the timedelta in the largest unit that divides it exactly, or 1 if no such unit exists.

  • str – The time unit as a string ('weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds'). Returns 'unknown' if no unit divides evenly.

Examples

>>> from datetime import timedelta
>>> get_integer_time(timedelta(days=14))
(2, 'weeks')
>>> get_integer_time(timedelta(hours=5))
(5, 'hours')
>>> get_integer_time(timedelta(milliseconds=1000))
(1, 'seconds')
>>> get_integer_time(timedelta(days=0.001))
(1, 'unknown')
neural_lam.utils.time.get_time_crop_slice(da_requested: xarray.DataArray, da_available: xarray.DataArray, da_requested_is_forecast: bool = False, da_available_is_forecast: bool = False, num_past_steps: int = 1, num_future_steps: int = 1, requested_max_lead: numpy.timedelta64 | None = None) → tuple[str, slice][source]#

Return the da_requested dimension and slice da_available covers.

Callers holding several dataarrays on the same time axis (interior state and forcing) apply this one slice to all of them so they stay aligned.

Parameters:
  • da_requested (xr.DataArray) – Driving dataarray whose times must be supported (typically interior state).

  • da_available (xr.DataArray) – Dataarray that must cover the requested windows (typically boundary forcing).

  • da_requested_is_forecast (bool) – Whether each side is in forecast mode (analysis_time + elapsed_forecast_duration dims) instead of plain time.

  • da_available_is_forecast (bool) – Whether each side is in forecast mode (analysis_time + elapsed_forecast_duration dims) instead of plain time.

  • num_past_steps (int) – Window size around each requested time, measured in da_available steps.

  • num_future_steps (int) – Window size around each requested time, measured in da_available steps.

  • requested_max_lead (np.timedelta64, optional) – Largest lead read from a forecast da_requested per sample; each analysis_time needs coverage out to it. Defaults to the full forecast length.

Returns:

The dimension to crop along ("analysis_time" for a forecast da_requested, else "time") and the positional slice to keep.

Return type:

tuple of (str, slice)

Raises:

ValueError – If no requested time is covered at all.

neural_lam.utils.time.get_time_step(times: numpy.ndarray) → numpy.timedelta64[source]#

Calculate the (constant) time step from a 1D time array.

Parameters:

times (np.ndarray) – 1D array of datetime64 or timedelta64 values.

Returns:

time_step – The constant spacing between successive values.

Return type:

np.timedelta64

Raises:

ValueError – If fewer than two values are given, or if the spacing is not constant.