Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions docs/examples/example_globcurrent.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ def set_globcurrent_fieldset(
indices=None,
deferred_load=True,
use_xarray=False,
time_periodic=False,
timestamps=None,
):
if filename is None:
Expand All @@ -32,7 +31,9 @@ def set_globcurrent_fieldset(
if use_xarray:
ds = xr.open_mfdataset(filename, combine="by_coords")
return parcels.FieldSet.from_xarray_dataset(
ds, variables, dimensions, time_periodic=time_periodic
ds,
variables,
dimensions,
)
else:
return parcels.FieldSet.from_netcdf(
Expand All @@ -41,7 +42,6 @@ def set_globcurrent_fieldset(
dimensions,
indices,
deferred_load=deferred_load,
time_periodic=time_periodic,
timestamps=timestamps,
)

Expand Down Expand Up @@ -118,6 +118,8 @@ def test_globcurrent_particles(use_xarray):
assert abs(pset[0].lat - -35.3) < 1


@pytest.mark.v4remove
@pytest.mark.xfail(reason="time_periodic removed in v4")
@pytest.mark.parametrize("rundays", [300, 900])
def test_globcurrent_time_periodic(rundays):
sample_var = []
Expand Down
8 changes: 0 additions & 8 deletions docs/examples/tutorial_timestamps.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,6 @@
" )"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Note, by the way, that adding the `time_periodic` argument to `Field.from_netcdf()` will also mean that the climatology can be cycled for multiple years.\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
Expand Down
1 change: 1 addition & 0 deletions docs/v4/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ List of tasks that are important to do before the release of version 4 (but can'
- [ ] Make migration guide for v3 to v4
- [ ] Just prior to release: Update conda feedstock recipe dependencies (remove cgen and compiler dependencies). Make sure that recipe is up-to-date.
- [ ] Revamp the oceanparcels.org landing page, and perhaps also consider new logo/branding?
- [ ] Look into xarray and whether users can create periodic datasets without increasing the size of the original dataset (i.e., no compromise alternative to `time_periodic` param in v3). Update docs accordingly.
2 changes: 0 additions & 2 deletions parcels/_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

"""

import datetime
import os
from collections.abc import Callable
from typing import Any, Literal, get_args
Expand All @@ -32,7 +31,6 @@
ChunkMode = Literal["auto", "specific", "failsafe"] # corresponds with `chunk_mode`
GridIndexingType = Literal["pop", "mom5", "mitgcm", "nemo", "croco"] # corresponds with `gridindexingtype`
UpdateStatus = Literal["not_updated", "first_updated", "updated"] # corresponds with `_update_status`
TimePeriodic = float | datetime.timedelta | Literal[False] # corresponds with `time_periodic`
NetcdfEngine = Literal["netcdf4", "xarray", "scipy"]


Expand Down
59 changes: 3 additions & 56 deletions parcels/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@
GridIndexingType,
InterpMethod,
Mesh,
TimePeriodic,
VectorType,
assert_valid_gridindexingtype,
assert_valid_interp_method,
)
from parcels.tools._helpers import default_repr, field_repr, timedelta_to_float
from parcels.tools._helpers import default_repr, field_repr
from parcels.tools.converters import (
TimeConverter,
UnitConverter,
Expand Down Expand Up @@ -155,10 +154,6 @@
allow_time_extrapolation : bool
boolean whether to allow for extrapolation in time
(i.e. beyond the last available time snapshot)
time_periodic : bool, float or datetime.timedelta
To loop periodically over the time component of the Field. It is set to either False or the length of the period (either float in seconds or datetime.timedelta object).
The last value of the time series can be provided (which is the same as the initial one) or not (Default: False)
This flag overrides the allow_time_extrapolation and sets it to False
chunkdims_name_map : str, optional
Gives a name map to the FieldFileBuffer that declared a mapping between chunksize name, NetCDF dimension and Parcels dimension;
required only if currently incompatible OCM field is loaded and chunking is used by 'chunksize' (which is the default)
Expand All @@ -174,7 +169,6 @@
"""

allow_time_extrapolation: bool
time_periodic: TimePeriodic
_cast_data_dtype: type[np.float32] | type[np.float64]

def __init__(
Expand All @@ -196,7 +190,6 @@
time_origin: TimeConverter | None = None,
interp_method: InterpMethod = "linear",
allow_time_extrapolation: bool | None = None,
time_periodic: TimePeriodic = False,
gridindexingtype: GridIndexingType = "nemo",
to_write: bool = False,
**kwargs,
Expand Down Expand Up @@ -261,28 +254,6 @@
else:
self.allow_time_extrapolation = allow_time_extrapolation

self.time_periodic = time_periodic
if self.time_periodic is not False and self.allow_time_extrapolation:
warnings.warn(
"allow_time_extrapolation and time_periodic cannot be used together. allow_time_extrapolation is set to False",
FieldSetWarning,
stacklevel=2,
)
self.allow_time_extrapolation = False
if self.time_periodic is True:
raise ValueError(
"Unsupported time_periodic=True. time_periodic must now be either False or the length of the period (either float in seconds or datetime.timedelta object."
)
if self.time_periodic is not False:
self.time_periodic = timedelta_to_float(self.time_periodic)

if not np.isclose(self.grid.time[-1] - self.grid.time[0], self.time_periodic):
if self.grid.time[-1] - self.grid.time[0] > self.time_periodic:
raise ValueError("Time series provided is longer than the time_periodic parameter")
self.grid._add_last_periodic_data_timestep = True
self.grid.time = np.append(self.grid.time, self.grid.time[0] + self.time_periodic)
self.grid.time_full = self.grid.time

self.vmin = vmin
self.vmax = vmax

Expand Down Expand Up @@ -457,7 +428,6 @@
mesh: Mesh = "spherical",
timestamps=None,
allow_time_extrapolation: bool | None = None,
time_periodic: TimePeriodic = False,
deferred_load: bool = True,
**kwargs,
) -> "Field":
Expand Down Expand Up @@ -491,9 +461,6 @@
boolean whether to allow for extrapolation in time
(i.e. beyond the last available time snapshot)
Default is False if dimensions includes time, else True
time_periodic : bool, float or datetime.timedelta
boolean whether to loop periodically over the time component of the FieldSet
This flag overrides the allow_time_extrapolation and sets it to False (Default value = False)
deferred_load : bool
boolean whether to only pre-load data (in deferred mode) or
fully load them (default: True). It is advised to deferred load the data, since in
Expand Down Expand Up @@ -743,7 +710,6 @@

kwargs["dimensions"] = dimensions.copy()
kwargs["indices"] = indices
kwargs["time_periodic"] = time_periodic
kwargs["netcdf_engine"] = netcdf_engine

return cls(
Expand All @@ -764,7 +730,6 @@
dimensions,
mesh: Mesh = "spherical",
allow_time_extrapolation: bool | None = None,
time_periodic: TimePeriodic = False,
**kwargs,
):
"""Create field from xarray Variable.
Expand All @@ -788,9 +753,6 @@
boolean whether to allow for extrapolation in time
(i.e. beyond the last available time snapshot)
Default is False if dimensions includes time, else True
time_periodic : bool, float or datetime.timedelta
boolean whether to loop periodically over the time component of the FieldSet
This flag overrides the allow_time_extrapolation and sets it to False (Default value = False)
**kwargs :
Keyword arguments passed to the :class:`Field` constructor.
"""
Expand All @@ -806,7 +768,6 @@
time = time_origin.reltime(time) # type: ignore[assignment]

grid = Grid.create_grid(lon, lat, depth, time, time_origin=time_origin, mesh=mesh)
kwargs["time_periodic"] = time_periodic
return cls(
name,
data,
Expand Down Expand Up @@ -1001,24 +962,10 @@
Note that we normalize to either the first or the last index
if the sampled value is outside the time value range.
"""
if (
not self.time_periodic
and not self.allow_time_extrapolation
and (time < self.grid.time[0] or time > self.grid.time[-1])
):
if not self.allow_time_extrapolation and (time < self.grid.time[0] or time > self.grid.time[-1]):

Check warning on line 965 in parcels/field.py

View check run for this annotation

Codecov / codecov/patch

parcels/field.py#L965

Added line #L965 was not covered by tests
raise TimeExtrapolationError(time, field=self)
time_index = self.grid.time <= time
if self.time_periodic:
if time_index.all() or np.logical_not(time_index).all():
periods = int(
math.floor((time - self.grid.time_full[0]) / (self.grid.time_full[-1] - self.grid.time_full[0]))
)
self.grid.periods = periods
time -= periods * (self.grid.time_full[-1] - self.grid.time_full[0])
time_index = self.grid.time <= time
ti = time_index.argmin() - 1 if time_index.any() else 0
return (ti, periods)
return (time_index.argmin() - 1 if time_index.any() else 0, 0)

if time_index.all():
# If given time > last known field time, use
# the last field frame without interpolation
Expand Down
Loading
Loading