From 9142fbe8dd5ad01fd80b338d6d55bc6df681d656 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Thu, 9 Jul 2026 09:35:11 +0200 Subject: [PATCH 1/5] FEAT: Update FieldSet.describe() to print output --- src/parcels/_core/fieldset.py | 11 ++++++++--- src/parcels/_reprs.py | 3 ++- tests/test_fieldset.py | 8 ++++++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/parcels/_core/fieldset.py b/src/parcels/_core/fieldset.py index bf7f9df59..acaf8e88e 100644 --- a/src/parcels/_core/fieldset.py +++ b/src/parcels/_core/fieldset.py @@ -1,8 +1,9 @@ from __future__ import annotations import functools +import sys from collections.abc import Iterable -from typing import TYPE_CHECKING +from typing import IO, TYPE_CHECKING import cf_xarray # noqa: F401 import numpy as np @@ -285,9 +286,13 @@ def from_sgrid_conventions( model = StructuredModelData.from_sgrid_conventions(ds, mesh, vector_fields) return cls([model]) - def describe(self): + def describe(self, buf: IO | None = None) -> None: """Return a table description of a FieldSet, which fields it has and their interpolation methods.""" - return fieldset_describe(self) + if buf is None: + buf = sys.stdout + assert buf is not None + + buf.write(fieldset_describe(self)) def assert_compatible_fieldsets(left: FieldSet, right: FieldSet) -> None: diff --git a/src/parcels/_reprs.py b/src/parcels/_reprs.py index a5e60d9da..b0a24ce17 100644 --- a/src/parcels/_reprs.py +++ b/src/parcels/_reprs.py @@ -252,7 +252,8 @@ def fieldset_describe(fieldset: FieldSet) -> str: mesh: {fieldset.models[0].grid._mesh} -time interval: {_print_time_interval(fieldset.time_interval)}""" +time interval: {_print_time_interval(fieldset.time_interval)} +""" ) diff --git a/tests/test_fieldset.py b/tests/test_fieldset.py index 8cf7d4661..1c288b301 100644 --- a/tests/test_fieldset.py +++ b/tests/test_fieldset.py @@ -1,4 +1,5 @@ from datetime import timedelta +from io import StringIO import cf_xarray # noqa: F401 import cftime @@ -395,6 +396,7 @@ def test_fieldset_add_context_values(): ) def test_fieldset_describe(fieldset_two_models: FieldSet): fieldset = fieldset_two_models + io = StringIO() expected = """\ | Name | Type | Grid number | Interp method / value | |:---------------|:------------|:--------------|:------------------------| @@ -409,6 +411,8 @@ def test_fieldset_describe(fieldset_two_models: FieldSet): | constant_field | Field | 2 | XConstantField(...) | mesh: flat -time interval: (np.datetime64('2000-01-01T00:00:00.000000000'), np.datetime64('2001-01-01T00:00:00.000000000'))""" - actual = fieldset.describe() +time interval: (np.datetime64('2000-01-01T00:00:00.000000000'), np.datetime64('2001-01-01T00:00:00.000000000')) +""" + fieldset.describe(io) + actual = io.getvalue() assert actual == expected From 2518ad46fa7e5b859bbc51baf82c9fd51186e90c Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Thu, 9 Jul 2026 09:44:50 +0200 Subject: [PATCH 2/5] Update docstring --- src/parcels/_core/fieldset.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/parcels/_core/fieldset.py b/src/parcels/_core/fieldset.py index acaf8e88e..9ed2f9460 100644 --- a/src/parcels/_core/fieldset.py +++ b/src/parcels/_core/fieldset.py @@ -287,7 +287,15 @@ def from_sgrid_conventions( return cls([model]) def describe(self, buf: IO | None = None) -> None: - """Return a table description of a FieldSet, which fields it has and their interpolation methods.""" + """ + Summary of a FieldSet including available Fields, associated + interpolators, and context values. + + Parameters + ---------- + buf : file-like, default: sys.stdout + writable buffer + """ if buf is None: buf = sys.stdout assert buf is not None From 3eab0b0f5a1ea0563d5750d2ebeb43e98fb5d1df Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Thu, 9 Jul 2026 09:50:57 +0200 Subject: [PATCH 3/5] Adding fieldset.describe() calls to tutorials --- docs/getting_started/tutorial_quickstart.md | 4 ++-- docs/user_guide/examples/tutorial_fesom.ipynb | 6 +----- docs/user_guide/examples/tutorial_schism.ipynb | 7 +------ 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/docs/getting_started/tutorial_quickstart.md b/docs/getting_started/tutorial_quickstart.md index ebd3823e3..626ca5fce 100644 --- a/docs/getting_started/tutorial_quickstart.md +++ b/docs/getting_started/tutorial_quickstart.md @@ -52,11 +52,11 @@ ds_fset = parcels.convert.copernicusmarine_to_sgrid(fields=fields) fieldset = parcels.FieldSet.from_sgrid_conventions(ds_fset) ``` -You can inspect the `fieldset` by simply printing it: +You can inspect the `parcels.FieldSet` object with the `describe` method in order to see which `parcels.Field`s are included, and which grid and interpolation method is used for each field. This also gives information on the type of mesh and the time interval of the `parcels.FieldSet`: ```{code-cell} :tags: [hide-output] -print(fieldset) +fieldset.describe() ``` The subset contains a region of the Agulhas current along the southeastern coast of Africa: diff --git a/docs/user_guide/examples/tutorial_fesom.ipynb b/docs/user_guide/examples/tutorial_fesom.ipynb index 874d4ea37..3b2383092 100644 --- a/docs/user_guide/examples/tutorial_fesom.ipynb +++ b/docs/user_guide/examples/tutorial_fesom.ipynb @@ -148,11 +148,7 @@ "source": [ "fieldset = parcels.FieldSet.from_ugrid_conventions(ds, mesh=\"spherical\")\n", "\n", - "for name, field in fieldset.fields.items():\n", - " # TODO clean this up when #2683 is implemented\n", - " print(\n", - " f\"{name:>4s} -> {type(field).__name__:<11s} interp={field.interp_method.__class__.__name__}\"\n", - " )" + "fieldset.describe()" ] }, { diff --git a/docs/user_guide/examples/tutorial_schism.ipynb b/docs/user_guide/examples/tutorial_schism.ipynb index 69e065e56..9d4d06ad5 100644 --- a/docs/user_guide/examples/tutorial_schism.ipynb +++ b/docs/user_guide/examples/tutorial_schism.ipynb @@ -215,12 +215,7 @@ "source": [ "fieldset = parcels.FieldSet.from_ugrid_conventions(uxds, mesh=\"flat\")\n", "\n", - "for name, field in fieldset.fields.items():\n", - " # TODO clean this up when #2683 is implemented\n", - " print(\n", - " f\"{name:>4s} -> {type(field).__name__:<11s} interp={field.interp_method.__class__.__name__}\"\n", - " )\n", - "print(\"time interval:\", fieldset.time_interval)" + "fieldset.describe()" ] }, { From 62e6a96ae9c60e50b29b6ec5c5407795778477d4 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Thu, 9 Jul 2026 09:53:05 +0200 Subject: [PATCH 4/5] Don't hide output in tutorial_quickstart --- docs/getting_started/tutorial_quickstart.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/getting_started/tutorial_quickstart.md b/docs/getting_started/tutorial_quickstart.md index 626ca5fce..405a0ab70 100644 --- a/docs/getting_started/tutorial_quickstart.md +++ b/docs/getting_started/tutorial_quickstart.md @@ -55,7 +55,6 @@ fieldset = parcels.FieldSet.from_sgrid_conventions(ds_fset) You can inspect the `parcels.FieldSet` object with the `describe` method in order to see which `parcels.Field`s are included, and which grid and interpolation method is used for each field. This also gives information on the type of mesh and the time interval of the `parcels.FieldSet`: ```{code-cell} -:tags: [hide-output] fieldset.describe() ``` From 766b3e4d78727fda103ba93f0f0f66130436ae69 Mon Sep 17 00:00:00 2001 From: Erik van Sebille Date: Thu, 9 Jul 2026 09:59:07 +0200 Subject: [PATCH 5/5] Update fieldset printing in interp-notebook --- docs/user_guide/examples/tutorial_interpolation.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user_guide/examples/tutorial_interpolation.ipynb b/docs/user_guide/examples/tutorial_interpolation.ipynb index 8edefd70d..713274252 100644 --- a/docs/user_guide/examples/tutorial_interpolation.ipynb +++ b/docs/user_guide/examples/tutorial_interpolation.ipynb @@ -129,8 +129,8 @@ " fieldset.P.interp_method = (\n", " p_interp # setting the interpolation method for fieldset.P\n", " )\n", + " fieldset.describe()\n", "\n", - " print(fieldset.P.interp_method.__class__.__name__)\n", " xv, yv = np.meshgrid(np.linspace(0, 1, 8), np.linspace(0, 1, 8))\n", " pset[p_interp.__class__.__name__] = parcels.ParticleSet(\n", " fieldset, pclass=SampleParticle, x=xv.flatten(), y=yv.flatten()\n",