From ad334e2844631cfaea95e69d3f980c48a0f55870 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Tue, 14 Jul 2026 17:21:57 +0200 Subject: [PATCH 01/10] Compute variables that have a mockT dimension --- src/parcels/_core/_windowed_array.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/parcels/_core/_windowed_array.py b/src/parcels/_core/_windowed_array.py index 77cb3cf1c..49526e687 100644 --- a/src/parcels/_core/_windowed_array.py +++ b/src/parcels/_core/_windowed_array.py @@ -108,4 +108,6 @@ def maybe_windowed(data: xr.DataArray, max_levels: int | None = None): return data if data.dims and data.dims[0] == "time" and is_dask_collection(data.data): return WindowedArray(data, max_levels=max_levels) + elif data.dims and data.dims[0] == "mockT" and is_dask_collection(data.data): + return data.compute() return data From 6034d1fca325756c753433bcc700cc23d0b9ad65 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Tue, 14 Jul 2026 17:25:46 +0200 Subject: [PATCH 02/10] Explicitly loading lon and lat --- src/parcels/_core/xgrid.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/parcels/_core/xgrid.py b/src/parcels/_core/xgrid.py index 91a48af5d..36a908475 100644 --- a/src/parcels/_core/xgrid.py +++ b/src/parcels/_core/xgrid.py @@ -7,6 +7,7 @@ import numpy.typing as npt import xarray as xr import xgcm +from dask import is_dask_collection import parcels._sgrid as sgrid import parcels._typing as ptyping @@ -207,6 +208,9 @@ def lon(self): _ = self.xgcm_grid.axes["X"] except KeyError: return np.zeros(1) + # ensure lon is loaded into memory for dask-backed datasets, as it is used in the search method + if is_dask_collection(self._ds["lon"].data): + self._ds["lon"].load() return self._ds["lon"].values @property @@ -221,6 +225,9 @@ def lat(self): _ = self.xgcm_grid.axes["Y"] except KeyError: return np.zeros(1) + # ensure lat is loaded into memory for dask-backed datasets, as it is used in the search method + if is_dask_collection(self._ds["lat"].data): + self._ds["lat"].load() return self._ds["lat"].values @property From 8b8fb2cc3dc5d2139af897cea2fe61b22a638072 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Wed, 15 Jul 2026 10:27:49 +0200 Subject: [PATCH 03/10] Adding Backend to fieldset repr To show which fields are WindowedArrays, which are Dask and which are NumPy --- src/parcels/_reprs.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/parcels/_reprs.py b/src/parcels/_reprs.py index b0a24ce17..a8b069273 100644 --- a/src/parcels/_reprs.py +++ b/src/parcels/_reprs.py @@ -8,7 +8,9 @@ import numpy as np import xarray as xr +from dask.base import is_dask_collection +from parcels._core._windowed_array import WindowedArray from parcels._python import isinstance_noimport if TYPE_CHECKING: @@ -190,6 +192,7 @@ class _FieldSetDescriptionRow: model_id: int | None name: str interp_method_or_value: str + backend: str | None = None def to_dict(self) -> dict[str, str]: return { @@ -197,6 +200,7 @@ def to_dict(self) -> dict[str, str]: "Type": self.type_, "Grid number": str(self.model_id) if self.model_id is not None else "-", "Interp method / value": self.interp_method_or_value, + "Backend": self.backend if self.backend is not None else "-", } @@ -213,6 +217,20 @@ def _print_time_interval(time_interval: TimeInterval | None) -> str: return repr((time_interval.left, time_interval.right)) +def _field_backend(field: Field | VectorField) -> str | None: + if hasattr(field, "data"): + if isinstance(field.data, WindowedArray): + return "WindowedArray" + elif is_dask_collection(field.data.data): + return "Dask" + elif isinstance(field.data.data, np.ndarray): + return "NumPy" + else: + return type(field.data).__name__ + else: + return None + + def fieldset_describe(fieldset: FieldSet) -> str: rows: list[_FieldSetDescriptionRow] = [] models: dict[int, int] = {} # mapping of memory ID to a human readable ID @@ -235,6 +253,7 @@ def fieldset_describe(fieldset: FieldSet) -> str: model_id=model_id, name=field.name, interp_method_or_value=repr(field.interp_method), + backend=_field_backend(field), ) ) for k, v in fieldset.context.items(): @@ -244,6 +263,7 @@ def fieldset_describe(fieldset: FieldSet) -> str: model_id=None, name=k, interp_method_or_value=repr(v), + backend=None, ) ) return ( From f4c3f8d2c07658f4191efa5cf6ac6b113bb7c189 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Wed, 15 Jul 2026 12:21:07 +0200 Subject: [PATCH 04/10] Adding unt test for backends --- tests/test_fieldset.py | 73 +++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 11 deletions(-) diff --git a/tests/test_fieldset.py b/tests/test_fieldset.py index 1c288b301..36ce561ab 100644 --- a/tests/test_fieldset.py +++ b/tests/test_fieldset.py @@ -7,6 +7,7 @@ import pandas as pd import pytest +import parcels.tutorial from parcels import Field, ParticleFile, ParticleSet, XGrid, convert from parcels._core.fieldset import FieldSet, _datetime_to_msg from parcels._core.model import _default_vector_field_components @@ -398,17 +399,17 @@ def test_fieldset_describe(fieldset_two_models: FieldSet): fieldset = fieldset_two_models io = StringIO() expected = """\ -| Name | Type | Grid number | Interp method / value | -|:---------------|:------------|:--------------|:------------------------| -| my_list | Context | - | [1, 2, 'hello'] | -| my_value | Context | - | 2.0 | -| U | Field | 0 | XLinear(...) | -| V | Field | 0 | XLinear(...) | -| UV | VectorField | 0 | XLinear_Velocity(...) | -| U_wind | Field | 1 | XLinear(...) | -| V_wind | Field | 1 | XLinear(...) | -| UV_wind | VectorField | 1 | XLinear_Velocity(...) | -| constant_field | Field | 2 | XConstantField(...) | +| Name | Type | Grid number | Interp method / value | Backend | +|:---------------|:------------|:--------------|:------------------------|:----------| +| my_list | Context | - | [1, 2, 'hello'] | - | +| my_value | Context | - | 2.0 | - | +| U | Field | 0 | XLinear(...) | NumPy | +| V | Field | 0 | XLinear(...) | NumPy | +| UV | VectorField | 0 | XLinear_Velocity(...) | - | +| U_wind | Field | 1 | XLinear(...) | NumPy | +| V_wind | Field | 1 | XLinear(...) | NumPy | +| UV_wind | VectorField | 1 | XLinear_Velocity(...) | - | +| constant_field | Field | 2 | XConstantField(...) | NumPy | mesh: flat time interval: (np.datetime64('2000-01-01T00:00:00.000000000'), np.datetime64('2001-01-01T00:00:00.000000000')) @@ -416,3 +417,53 @@ def test_fieldset_describe(fieldset_two_models: FieldSet): fieldset.describe(io) actual = io.getvalue() assert actual == expected + + +def test_fieldset_describe_backends(): + ds_u = parcels.tutorial.open_dataset("NemoNorthSeaORCA025-N006_data/U") + ds_v = parcels.tutorial.open_dataset("NemoNorthSeaORCA025-N006_data/V") + ds_w = parcels.tutorial.open_dataset("NemoNorthSeaORCA025-N006_data/W") + ds_coords = parcels.tutorial.open_dataset("NemoNorthSeaORCA025-N006_data/mesh_mask")[["glamf", "gphif"]] + + ds_fset = convert.nemo_to_sgrid( + fields={"U": ds_u["uo"], "V": ds_v["vo"], "W": ds_w["wo"]}, + coords=ds_coords, + ) + fieldset = FieldSet.from_sgrid_conventions(ds_fset) + + io = StringIO() + expected = """\ +| Name | Type | Grid number | Interp method / value | Backend | +|:-------|:------------|--------------:|:------------------------|:----------| +| U | Field | 0 | XLinear(...) | Dask | +| V | Field | 0 | XLinear(...) | Dask | +| W | Field | 0 | XLinear(...) | Dask | +| UV | VectorField | 0 | CGrid_Velocity(...) | - | +| UVW | VectorField | 0 | CGrid_Velocity(...) | - | + +mesh: spherical +time interval: (np.datetime64('2000-01-02T12:00:00.000000000'), np.datetime64('2000-01-27T12:00:00.000000000')) +""" + fieldset.describe(io) + actual = io.getvalue() + assert actual == expected + + # Also run with WindowedArray backend + fieldset = fieldset.to_windowed_arrays() + + io = StringIO() + expected = """\ +| Name | Type | Grid number | Interp method / value | Backend | +|:-------|:------------|--------------:|:------------------------|:--------------| +| U | Field | 0 | XLinear(...) | WindowedArray | +| V | Field | 0 | XLinear(...) | WindowedArray | +| W | Field | 0 | XLinear(...) | WindowedArray | +| UV | VectorField | 0 | CGrid_Velocity(...) | - | +| UVW | VectorField | 0 | CGrid_Velocity(...) | - | + +mesh: spherical +time interval: (np.datetime64('2000-01-02T12:00:00.000000000'), np.datetime64('2000-01-27T12:00:00.000000000')) +""" + fieldset.describe(io) + actual = io.getvalue() + assert actual == expected From b7a7d38657d38efcaa021baa21904749dac64009 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Thu, 16 Jul 2026 08:16:41 +0200 Subject: [PATCH 05/10] Moving lon/lat loading to to_windowed_arrays --- src/parcels/_core/model.py | 5 +++++ src/parcels/_core/xgrid.py | 7 ------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/parcels/_core/model.py b/src/parcels/_core/model.py index 93f403adb..89d34fa81 100644 --- a/src/parcels/_core/model.py +++ b/src/parcels/_core/model.py @@ -7,6 +7,7 @@ import cf_xarray # noqa: F401 import uxarray as ux import xarray as xr +from dask import is_dask_collection import parcels._sgrid as sgrid import parcels._typing as ptyping @@ -102,6 +103,10 @@ def to_windowed_arrays(self, *, max_levels: int | None = None) -> Self: and ``max_levels`` then bounds its size. """ windowed = self.__dict__.setdefault("_windowed", {}) + for dim in ["lon", "lat", "depth"]: + # ensure lon and lat are loaded into memory for dask-backed datasets + if is_dask_collection(self.data[dim]): + self.data[dim].load() for name in self.scalar_field_names: current = windowed.get(name, self.data[name]) windowed[name] = maybe_windowed(current, max_levels=max_levels) diff --git a/src/parcels/_core/xgrid.py b/src/parcels/_core/xgrid.py index 36a908475..91a48af5d 100644 --- a/src/parcels/_core/xgrid.py +++ b/src/parcels/_core/xgrid.py @@ -7,7 +7,6 @@ import numpy.typing as npt import xarray as xr import xgcm -from dask import is_dask_collection import parcels._sgrid as sgrid import parcels._typing as ptyping @@ -208,9 +207,6 @@ def lon(self): _ = self.xgcm_grid.axes["X"] except KeyError: return np.zeros(1) - # ensure lon is loaded into memory for dask-backed datasets, as it is used in the search method - if is_dask_collection(self._ds["lon"].data): - self._ds["lon"].load() return self._ds["lon"].values @property @@ -225,9 +221,6 @@ def lat(self): _ = self.xgcm_grid.axes["Y"] except KeyError: return np.zeros(1) - # ensure lat is loaded into memory for dask-backed datasets, as it is used in the search method - if is_dask_collection(self._ds["lat"].data): - self._ds["lat"].load() return self._ds["lat"].values @property From d8aeae0cc456a952cecd1114285e80270596446a Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Thu, 16 Jul 2026 08:23:29 +0200 Subject: [PATCH 06/10] Renaming Backend to Parcels backend Following suggestion by @VeckoTheGecko --- src/parcels/_reprs.py | 2 +- tests/test_fieldset.py | 49 +++++++++++++++++++++--------------------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/parcels/_reprs.py b/src/parcels/_reprs.py index a8b069273..9148adbe4 100644 --- a/src/parcels/_reprs.py +++ b/src/parcels/_reprs.py @@ -200,7 +200,7 @@ def to_dict(self) -> dict[str, str]: "Type": self.type_, "Grid number": str(self.model_id) if self.model_id is not None else "-", "Interp method / value": self.interp_method_or_value, - "Backend": self.backend if self.backend is not None else "-", + "Parcels backend": self.backend if self.backend is not None else "-", } diff --git a/tests/test_fieldset.py b/tests/test_fieldset.py index 36ce561ab..80fb04ac5 100644 --- a/tests/test_fieldset.py +++ b/tests/test_fieldset.py @@ -400,16 +400,17 @@ def test_fieldset_describe(fieldset_two_models: FieldSet): io = StringIO() expected = """\ | Name | Type | Grid number | Interp method / value | Backend | -|:---------------|:------------|:--------------|:------------------------|:----------| -| my_list | Context | - | [1, 2, 'hello'] | - | -| my_value | Context | - | 2.0 | - | -| U | Field | 0 | XLinear(...) | NumPy | -| V | Field | 0 | XLinear(...) | NumPy | -| UV | VectorField | 0 | XLinear_Velocity(...) | - | -| U_wind | Field | 1 | XLinear(...) | NumPy | -| V_wind | Field | 1 | XLinear(...) | NumPy | -| UV_wind | VectorField | 1 | XLinear_Velocity(...) | - | -| constant_field | Field | 2 | XConstantField(...) | NumPy | +| Name | Type | Grid number | Interp method / value | Parcels backend | +|:---------------|:------------|:--------------|:------------------------|:------------------| +| my_list | Context | - | [1, 2, 'hello'] | - | +| my_value | Context | - | 2.0 | - | +| U | Field | 0 | XLinear(...) | NumPy | +| V | Field | 0 | XLinear(...) | NumPy | +| UV | VectorField | 0 | XLinear_Velocity(...) | - | +| U_wind | Field | 1 | XLinear(...) | NumPy | +| V_wind | Field | 1 | XLinear(...) | NumPy | +| UV_wind | VectorField | 1 | XLinear_Velocity(...) | - | +| constant_field | Field | 2 | XConstantField(...) | NumPy | mesh: flat time interval: (np.datetime64('2000-01-01T00:00:00.000000000'), np.datetime64('2001-01-01T00:00:00.000000000')) @@ -433,13 +434,13 @@ def test_fieldset_describe_backends(): io = StringIO() expected = """\ -| Name | Type | Grid number | Interp method / value | Backend | -|:-------|:------------|--------------:|:------------------------|:----------| -| U | Field | 0 | XLinear(...) | Dask | -| V | Field | 0 | XLinear(...) | Dask | -| W | Field | 0 | XLinear(...) | Dask | -| UV | VectorField | 0 | CGrid_Velocity(...) | - | -| UVW | VectorField | 0 | CGrid_Velocity(...) | - | +| Name | Type | Grid number | Interp method / value | Parcels backend | +|:-------|:------------|--------------:|:------------------------|:------------------| +| U | Field | 0 | XLinear(...) | Dask | +| V | Field | 0 | XLinear(...) | Dask | +| W | Field | 0 | XLinear(...) | Dask | +| UV | VectorField | 0 | CGrid_Velocity(...) | - | +| UVW | VectorField | 0 | CGrid_Velocity(...) | - | mesh: spherical time interval: (np.datetime64('2000-01-02T12:00:00.000000000'), np.datetime64('2000-01-27T12:00:00.000000000')) @@ -453,13 +454,13 @@ def test_fieldset_describe_backends(): io = StringIO() expected = """\ -| Name | Type | Grid number | Interp method / value | Backend | -|:-------|:------------|--------------:|:------------------------|:--------------| -| U | Field | 0 | XLinear(...) | WindowedArray | -| V | Field | 0 | XLinear(...) | WindowedArray | -| W | Field | 0 | XLinear(...) | WindowedArray | -| UV | VectorField | 0 | CGrid_Velocity(...) | - | -| UVW | VectorField | 0 | CGrid_Velocity(...) | - | +| Name | Type | Grid number | Interp method / value | Parcels backend | +|:-------|:------------|--------------:|:------------------------|:------------------| +| U | Field | 0 | XLinear(...) | WindowedArray | +| V | Field | 0 | XLinear(...) | WindowedArray | +| W | Field | 0 | XLinear(...) | WindowedArray | +| UV | VectorField | 0 | CGrid_Velocity(...) | - | +| UVW | VectorField | 0 | CGrid_Velocity(...) | - | mesh: spherical time interval: (np.datetime64('2000-01-02T12:00:00.000000000'), np.datetime64('2000-01-27T12:00:00.000000000')) From b3dc1e02d831e75c703e5c4b97dd5a4180aa0233 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Thu, 16 Jul 2026 08:53:19 +0200 Subject: [PATCH 07/10] Also adding support for zarr backend in describe() --- src/parcels/_reprs.py | 3 +++ tests/test_fieldset.py | 25 +++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/parcels/_reprs.py b/src/parcels/_reprs.py index 9148adbe4..5a6ae2944 100644 --- a/src/parcels/_reprs.py +++ b/src/parcels/_reprs.py @@ -8,6 +8,7 @@ import numpy as np import xarray as xr +import zarr from dask.base import is_dask_collection from parcels._core._windowed_array import WindowedArray @@ -223,6 +224,8 @@ def _field_backend(field: Field | VectorField) -> str | None: return "WindowedArray" elif is_dask_collection(field.data.data): return "Dask" + elif isinstance(field.data.variable._data, zarr.Array): + return "Zarr" elif isinstance(field.data.data, np.ndarray): return "NumPy" else: diff --git a/tests/test_fieldset.py b/tests/test_fieldset.py index 80fb04ac5..5a333aa25 100644 --- a/tests/test_fieldset.py +++ b/tests/test_fieldset.py @@ -8,7 +8,7 @@ import pytest import parcels.tutorial -from parcels import Field, ParticleFile, ParticleSet, XGrid, convert +from parcels import Field, ParticleFile, ParticleSet, XGrid, convert, open_raw_zarr from parcels._core.fieldset import FieldSet, _datetime_to_msg from parcels._core.model import _default_vector_field_components from parcels._datasets.structured.generic import datasets as datasets_structured @@ -420,7 +420,7 @@ def test_fieldset_describe(fieldset_two_models: FieldSet): assert actual == expected -def test_fieldset_describe_backends(): +def test_fieldset_describe_backends(tmp_path): ds_u = parcels.tutorial.open_dataset("NemoNorthSeaORCA025-N006_data/U") ds_v = parcels.tutorial.open_dataset("NemoNorthSeaORCA025-N006_data/V") ds_w = parcels.tutorial.open_dataset("NemoNorthSeaORCA025-N006_data/W") @@ -462,6 +462,27 @@ def test_fieldset_describe_backends(): | UV | VectorField | 0 | CGrid_Velocity(...) | - | | UVW | VectorField | 0 | CGrid_Velocity(...) | - | +mesh: spherical +time interval: (np.datetime64('2000-01-02T12:00:00.000000000'), np.datetime64('2000-01-27T12:00:00.000000000')) +""" + fieldset.describe(io) + actual = io.getvalue() + assert actual == expected + + path = tmp_path / "ds.zarr" + ds_fset.to_zarr(path) + ds_zarr = open_raw_zarr(path) + fieldset = FieldSet.from_sgrid_conventions(ds_zarr) + io = StringIO() + expected = """\ +| Name | Type | Grid number | Interp method / value | Parcels backend | +|:-------|:------------|--------------:|:------------------------|:------------------| +| U | Field | 0 | XLinear(...) | Zarr | +| V | Field | 0 | XLinear(...) | Zarr | +| W | Field | 0 | XLinear(...) | Zarr | +| UV | VectorField | 0 | CGrid_Velocity(...) | - | +| UVW | VectorField | 0 | CGrid_Velocity(...) | - | + mesh: spherical time interval: (np.datetime64('2000-01-02T12:00:00.000000000'), np.datetime64('2000-01-27T12:00:00.000000000')) """ From eec8b16934c4b355b56b8ed9897a068b2d12888a Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Thu, 16 Jul 2026 10:09:42 +0200 Subject: [PATCH 08/10] Adding print statements for CI debugging As I can't reproduce the failing unit tests locally --- tests/test_fieldset.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_fieldset.py b/tests/test_fieldset.py index 5a333aa25..a7e5f4a74 100644 --- a/tests/test_fieldset.py +++ b/tests/test_fieldset.py @@ -431,6 +431,7 @@ def test_fieldset_describe_backends(tmp_path): coords=ds_coords, ) fieldset = FieldSet.from_sgrid_conventions(ds_fset) + print(fieldset.describe()) io = StringIO() expected = """\ @@ -451,6 +452,7 @@ def test_fieldset_describe_backends(tmp_path): # Also run with WindowedArray backend fieldset = fieldset.to_windowed_arrays() + print(fieldset.describe()) io = StringIO() expected = """\ @@ -473,6 +475,8 @@ def test_fieldset_describe_backends(tmp_path): ds_fset.to_zarr(path) ds_zarr = open_raw_zarr(path) fieldset = FieldSet.from_sgrid_conventions(ds_zarr) + print(fieldset.describe()) + io = StringIO() expected = """\ | Name | Type | Grid number | Interp method / value | Parcels backend | From 817f204913c9735ba4009b650b1ac7c11b029aa9 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Thu, 16 Jul 2026 10:22:07 +0200 Subject: [PATCH 09/10] fixing time_interval because of fewer NorthSea files Related to #2750 --- tests/test_fieldset.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/test_fieldset.py b/tests/test_fieldset.py index a7e5f4a74..5ec45ac0d 100644 --- a/tests/test_fieldset.py +++ b/tests/test_fieldset.py @@ -431,7 +431,6 @@ def test_fieldset_describe_backends(tmp_path): coords=ds_coords, ) fieldset = FieldSet.from_sgrid_conventions(ds_fset) - print(fieldset.describe()) io = StringIO() expected = """\ @@ -444,7 +443,7 @@ def test_fieldset_describe_backends(tmp_path): | UVW | VectorField | 0 | CGrid_Velocity(...) | - | mesh: spherical -time interval: (np.datetime64('2000-01-02T12:00:00.000000000'), np.datetime64('2000-01-27T12:00:00.000000000')) +time interval: (np.datetime64('2000-01-02T12:00:00.000000000'), np.datetime64('2000-01-12T12:00:00.000000000')) """ fieldset.describe(io) actual = io.getvalue() @@ -452,7 +451,6 @@ def test_fieldset_describe_backends(tmp_path): # Also run with WindowedArray backend fieldset = fieldset.to_windowed_arrays() - print(fieldset.describe()) io = StringIO() expected = """\ @@ -465,7 +463,7 @@ def test_fieldset_describe_backends(tmp_path): | UVW | VectorField | 0 | CGrid_Velocity(...) | - | mesh: spherical -time interval: (np.datetime64('2000-01-02T12:00:00.000000000'), np.datetime64('2000-01-27T12:00:00.000000000')) +time interval: (np.datetime64('2000-01-02T12:00:00.000000000'), np.datetime64('2000-01-12T12:00:00.000000000')) """ fieldset.describe(io) actual = io.getvalue() @@ -475,7 +473,6 @@ def test_fieldset_describe_backends(tmp_path): ds_fset.to_zarr(path) ds_zarr = open_raw_zarr(path) fieldset = FieldSet.from_sgrid_conventions(ds_zarr) - print(fieldset.describe()) io = StringIO() expected = """\ @@ -488,7 +485,7 @@ def test_fieldset_describe_backends(tmp_path): | UVW | VectorField | 0 | CGrid_Velocity(...) | - | mesh: spherical -time interval: (np.datetime64('2000-01-02T12:00:00.000000000'), np.datetime64('2000-01-27T12:00:00.000000000')) +time interval: (np.datetime64('2000-01-02T12:00:00.000000000'), np.datetime64('2000-01-12T12:00:00.000000000')) """ fieldset.describe(io) actual = io.getvalue() From 29f049c76523388268baacdb6e8bbc0de453bfe5 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Thu, 16 Jul 2026 11:01:45 +0200 Subject: [PATCH 10/10] Separate depth loading As not all fields have depth coordinate --- src/parcels/_core/model.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/parcels/_core/model.py b/src/parcels/_core/model.py index 89d34fa81..7a0945573 100644 --- a/src/parcels/_core/model.py +++ b/src/parcels/_core/model.py @@ -103,10 +103,12 @@ def to_windowed_arrays(self, *, max_levels: int | None = None) -> Self: and ``max_levels`` then bounds its size. """ windowed = self.__dict__.setdefault("_windowed", {}) - for dim in ["lon", "lat", "depth"]: + for dim in ["lon", "lat"]: # ensure lon and lat are loaded into memory for dask-backed datasets if is_dask_collection(self.data[dim]): self.data[dim].load() + if "depth" in self.data.dims and is_dask_collection(self.data["depth"]): + self.data["depth"].load() for name in self.scalar_field_names: current = windowed.get(name, self.data[name]) windowed[name] = maybe_windowed(current, max_levels=max_levels)