From e6aee518db17bad82d363df2376d2fa3950b87df Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 14:49:54 +0200 Subject: [PATCH 01/45] Move v3 tests to tests-v3 --- {tests => tests-v3}/test_advection.py | 0 {tests => tests-v3}/test_examples.py | 0 {tests => tests-v3}/test_fieldset.py | 0 {tests => tests-v3}/test_fieldset_sampling.py | 0 {tests => tests-v3}/test_interaction.py | 0 {tests => tests-v3}/test_interpolation.py | 0 {tests => tests-v3}/test_kernel_execution.py | 0 {tests => tests-v3}/test_kernel_language.py | 0 {tests => tests-v3}/test_mpirun.py | 0 {tests => tests-v3}/test_particles.py | 0 {tests => tests-v3}/test_particlesets.py | 0 {tests => tests-v3}/test_reprs.py | 0 {tests => tests-v3}/test_typing.py | 0 {tests => tests-v3}/tools/test_exampledata_utils.py | 0 {tests => tests-v3}/tools/test_helpers.py | 0 {tests => tests-v3}/tools/test_warnings.py | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename {tests => tests-v3}/test_advection.py (100%) rename {tests => tests-v3}/test_examples.py (100%) rename {tests => tests-v3}/test_fieldset.py (100%) rename {tests => tests-v3}/test_fieldset_sampling.py (100%) rename {tests => tests-v3}/test_interaction.py (100%) rename {tests => tests-v3}/test_interpolation.py (100%) rename {tests => tests-v3}/test_kernel_execution.py (100%) rename {tests => tests-v3}/test_kernel_language.py (100%) rename {tests => tests-v3}/test_mpirun.py (100%) rename {tests => tests-v3}/test_particles.py (100%) rename {tests => tests-v3}/test_particlesets.py (100%) rename {tests => tests-v3}/test_reprs.py (100%) rename {tests => tests-v3}/test_typing.py (100%) rename {tests => tests-v3}/tools/test_exampledata_utils.py (100%) rename {tests => tests-v3}/tools/test_helpers.py (100%) rename {tests => tests-v3}/tools/test_warnings.py (100%) diff --git a/tests/test_advection.py b/tests-v3/test_advection.py similarity index 100% rename from tests/test_advection.py rename to tests-v3/test_advection.py diff --git a/tests/test_examples.py b/tests-v3/test_examples.py similarity index 100% rename from tests/test_examples.py rename to tests-v3/test_examples.py diff --git a/tests/test_fieldset.py b/tests-v3/test_fieldset.py similarity index 100% rename from tests/test_fieldset.py rename to tests-v3/test_fieldset.py diff --git a/tests/test_fieldset_sampling.py b/tests-v3/test_fieldset_sampling.py similarity index 100% rename from tests/test_fieldset_sampling.py rename to tests-v3/test_fieldset_sampling.py diff --git a/tests/test_interaction.py b/tests-v3/test_interaction.py similarity index 100% rename from tests/test_interaction.py rename to tests-v3/test_interaction.py diff --git a/tests/test_interpolation.py b/tests-v3/test_interpolation.py similarity index 100% rename from tests/test_interpolation.py rename to tests-v3/test_interpolation.py diff --git a/tests/test_kernel_execution.py b/tests-v3/test_kernel_execution.py similarity index 100% rename from tests/test_kernel_execution.py rename to tests-v3/test_kernel_execution.py diff --git a/tests/test_kernel_language.py b/tests-v3/test_kernel_language.py similarity index 100% rename from tests/test_kernel_language.py rename to tests-v3/test_kernel_language.py diff --git a/tests/test_mpirun.py b/tests-v3/test_mpirun.py similarity index 100% rename from tests/test_mpirun.py rename to tests-v3/test_mpirun.py diff --git a/tests/test_particles.py b/tests-v3/test_particles.py similarity index 100% rename from tests/test_particles.py rename to tests-v3/test_particles.py diff --git a/tests/test_particlesets.py b/tests-v3/test_particlesets.py similarity index 100% rename from tests/test_particlesets.py rename to tests-v3/test_particlesets.py diff --git a/tests/test_reprs.py b/tests-v3/test_reprs.py similarity index 100% rename from tests/test_reprs.py rename to tests-v3/test_reprs.py diff --git a/tests/test_typing.py b/tests-v3/test_typing.py similarity index 100% rename from tests/test_typing.py rename to tests-v3/test_typing.py diff --git a/tests/tools/test_exampledata_utils.py b/tests-v3/tools/test_exampledata_utils.py similarity index 100% rename from tests/tools/test_exampledata_utils.py rename to tests-v3/tools/test_exampledata_utils.py diff --git a/tests/tools/test_helpers.py b/tests-v3/tools/test_helpers.py similarity index 100% rename from tests/tools/test_helpers.py rename to tests-v3/tools/test_helpers.py diff --git a/tests/tools/test_warnings.py b/tests-v3/tools/test_warnings.py similarity index 100% rename from tests/tools/test_warnings.py rename to tests-v3/tools/test_warnings.py From f55ae7f0b57a382bd9fbb802ac6380fa58660146 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 14:24:45 +0200 Subject: [PATCH 02/45] Add readme to tests/test_data --- tests/test_data/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/test_data/README.md diff --git a/tests/test_data/README.md b/tests/test_data/README.md new file mode 100644 index 0000000000..083506fb69 --- /dev/null +++ b/tests/test_data/README.md @@ -0,0 +1 @@ +Test data that was used primary in v3 (or in migrating from v3 to v4). In v4 this subpackage is superceded by the `parcels._datasets` package as well as `pooch` for fetching realistic data. From 3cbc95ff8ae8bad45e48f0452bfe9ade31131554 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 14:51:29 +0200 Subject: [PATCH 03/45] Move `tests/v4` tests to `tests` --- pyproject.toml | 4 ++-- tests/{v4 => }/test_advection.py | 0 tests/{v4 => }/test_basegrid.py | 0 tests/{v4 => }/test_datasets.py | 0 tests/{v4 => }/test_diffusion.py | 0 tests/{v4 => }/test_field.py | 0 tests/{v4 => }/test_fieldset.py | 0 tests/{v4 => }/test_index_search.py | 0 tests/{v4 => }/test_interpolation.py | 0 tests/{v4 => }/test_kernel.py | 0 tests/{v4 => }/test_particle.py | 0 tests/{v4 => }/test_particlefile.py | 0 tests/{v4 => }/test_particleset.py | 0 tests/{v4 => }/test_particleset_execute.py | 0 tests/{v4 => }/test_spatialhash.py | 0 tests/{v4 => }/test_structured_gcm.py | 0 tests/{v4 => }/test_utils.py | 0 tests/{v4 => }/test_uxarray_fieldset.py | 0 tests/{v4 => }/test_uxgrid.py | 0 tests/{v4 => }/test_xarray_fieldset.py | 0 tests/{v4 => }/test_xgrid.py | 0 tests/{v4 => }/utils/test_time.py | 0 tests/{v4 => }/utils/test_unstructured.py | 0 23 files changed, 2 insertions(+), 2 deletions(-) rename tests/{v4 => }/test_advection.py (100%) rename tests/{v4 => }/test_basegrid.py (100%) rename tests/{v4 => }/test_datasets.py (100%) rename tests/{v4 => }/test_diffusion.py (100%) rename tests/{v4 => }/test_field.py (100%) rename tests/{v4 => }/test_fieldset.py (100%) rename tests/{v4 => }/test_index_search.py (100%) rename tests/{v4 => }/test_interpolation.py (100%) rename tests/{v4 => }/test_kernel.py (100%) rename tests/{v4 => }/test_particle.py (100%) rename tests/{v4 => }/test_particlefile.py (100%) rename tests/{v4 => }/test_particleset.py (100%) rename tests/{v4 => }/test_particleset_execute.py (100%) rename tests/{v4 => }/test_spatialhash.py (100%) rename tests/{v4 => }/test_structured_gcm.py (100%) rename tests/{v4 => }/test_utils.py (100%) rename tests/{v4 => }/test_uxarray_fieldset.py (100%) rename tests/{v4 => }/test_uxgrid.py (100%) rename tests/{v4 => }/test_xarray_fieldset.py (100%) rename tests/{v4 => }/test_xgrid.py (100%) rename tests/{v4 => }/utils/test_time.py (100%) rename tests/{v4 => }/utils/test_unstructured.py (100%) diff --git a/pyproject.toml b/pyproject.toml index 06436fb899..5dc6626461 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,8 +51,8 @@ local_scheme = "no-local-version" [tool.pytest.ini_options] addopts = ["--strict-config", "--strict-markers"] xfail_strict = true -# testpaths = ["tests", "docs/examples"] # TODO v4: Re-enable once `tests/v4` separation is gone -testpaths = ["tests/v4"] +# testpaths = ["tests", "docs/examples"] # TODO v4: Re-enable once examples are back/fixed +testpaths = ["tests"] python_files = ["test_*.py", "example_*.py", "*tutorial*"] minversion = "7" markers = [ # can be skipped by doing `pytest -m "not slow"` etc. diff --git a/tests/v4/test_advection.py b/tests/test_advection.py similarity index 100% rename from tests/v4/test_advection.py rename to tests/test_advection.py diff --git a/tests/v4/test_basegrid.py b/tests/test_basegrid.py similarity index 100% rename from tests/v4/test_basegrid.py rename to tests/test_basegrid.py diff --git a/tests/v4/test_datasets.py b/tests/test_datasets.py similarity index 100% rename from tests/v4/test_datasets.py rename to tests/test_datasets.py diff --git a/tests/v4/test_diffusion.py b/tests/test_diffusion.py similarity index 100% rename from tests/v4/test_diffusion.py rename to tests/test_diffusion.py diff --git a/tests/v4/test_field.py b/tests/test_field.py similarity index 100% rename from tests/v4/test_field.py rename to tests/test_field.py diff --git a/tests/v4/test_fieldset.py b/tests/test_fieldset.py similarity index 100% rename from tests/v4/test_fieldset.py rename to tests/test_fieldset.py diff --git a/tests/v4/test_index_search.py b/tests/test_index_search.py similarity index 100% rename from tests/v4/test_index_search.py rename to tests/test_index_search.py diff --git a/tests/v4/test_interpolation.py b/tests/test_interpolation.py similarity index 100% rename from tests/v4/test_interpolation.py rename to tests/test_interpolation.py diff --git a/tests/v4/test_kernel.py b/tests/test_kernel.py similarity index 100% rename from tests/v4/test_kernel.py rename to tests/test_kernel.py diff --git a/tests/v4/test_particle.py b/tests/test_particle.py similarity index 100% rename from tests/v4/test_particle.py rename to tests/test_particle.py diff --git a/tests/v4/test_particlefile.py b/tests/test_particlefile.py similarity index 100% rename from tests/v4/test_particlefile.py rename to tests/test_particlefile.py diff --git a/tests/v4/test_particleset.py b/tests/test_particleset.py similarity index 100% rename from tests/v4/test_particleset.py rename to tests/test_particleset.py diff --git a/tests/v4/test_particleset_execute.py b/tests/test_particleset_execute.py similarity index 100% rename from tests/v4/test_particleset_execute.py rename to tests/test_particleset_execute.py diff --git a/tests/v4/test_spatialhash.py b/tests/test_spatialhash.py similarity index 100% rename from tests/v4/test_spatialhash.py rename to tests/test_spatialhash.py diff --git a/tests/v4/test_structured_gcm.py b/tests/test_structured_gcm.py similarity index 100% rename from tests/v4/test_structured_gcm.py rename to tests/test_structured_gcm.py diff --git a/tests/v4/test_utils.py b/tests/test_utils.py similarity index 100% rename from tests/v4/test_utils.py rename to tests/test_utils.py diff --git a/tests/v4/test_uxarray_fieldset.py b/tests/test_uxarray_fieldset.py similarity index 100% rename from tests/v4/test_uxarray_fieldset.py rename to tests/test_uxarray_fieldset.py diff --git a/tests/v4/test_uxgrid.py b/tests/test_uxgrid.py similarity index 100% rename from tests/v4/test_uxgrid.py rename to tests/test_uxgrid.py diff --git a/tests/v4/test_xarray_fieldset.py b/tests/test_xarray_fieldset.py similarity index 100% rename from tests/v4/test_xarray_fieldset.py rename to tests/test_xarray_fieldset.py diff --git a/tests/v4/test_xgrid.py b/tests/test_xgrid.py similarity index 100% rename from tests/v4/test_xgrid.py rename to tests/test_xgrid.py diff --git a/tests/v4/utils/test_time.py b/tests/utils/test_time.py similarity index 100% rename from tests/v4/utils/test_time.py rename to tests/utils/test_time.py diff --git a/tests/v4/utils/test_unstructured.py b/tests/utils/test_unstructured.py similarity index 100% rename from tests/v4/utils/test_unstructured.py rename to tests/utils/test_unstructured.py From 1ba933165e76111e147e5412cf3b870151e339ef Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 15:08:48 +0200 Subject: [PATCH 04/45] Rename application_kernels to kernels --- parcels/__init__.py | 2 +- parcels/field.py | 2 +- parcels/kernel.py | 4 ++-- .../EOSseawaterproperties.py | 0 .../TEOSseawaterdensity.py | 0 parcels/{application_kernels => kernels}/__init__.py | 0 .../{application_kernels => kernels}/advection.py | 0 .../advectiondiffusion.py | 0 .../{application_kernels => kernels}/interaction.py | 0 .../interpolation.py | 0 parcels/particleset.py | 2 +- tests-v3/test_interaction.py | 12 ++++++------ tests-v3/test_kernel_language.py | 4 ++-- tests/test_advection.py | 6 +++--- tests/test_diffusion.py | 4 ++-- tests/test_interpolation.py | 8 ++++---- tests/utils.py | 2 +- 17 files changed, 23 insertions(+), 23 deletions(-) rename parcels/{application_kernels => kernels}/EOSseawaterproperties.py (100%) rename parcels/{application_kernels => kernels}/TEOSseawaterdensity.py (100%) rename parcels/{application_kernels => kernels}/__init__.py (100%) rename parcels/{application_kernels => kernels}/advection.py (100%) rename parcels/{application_kernels => kernels}/advectiondiffusion.py (100%) rename parcels/{application_kernels => kernels}/interaction.py (100%) rename parcels/{application_kernels => kernels}/interpolation.py (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index 015a135b55..37bedbfc13 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -4,11 +4,11 @@ import warnings as _warnings -from parcels.application_kernels import * from parcels.field import * from parcels.fieldset import * from parcels.interaction import * from parcels.kernel import * +from parcels.kernels import * from parcels.particle import * from parcels.particlefile import * from parcels.particleset import * diff --git a/parcels/field.py b/parcels/field.py index 212c042c0a..d0de5666fd 100644 --- a/parcels/field.py +++ b/parcels/field.py @@ -11,7 +11,7 @@ from parcels._core.utils.time import TimeInterval from parcels._reprs import default_repr from parcels._typing import VectorType -from parcels.application_kernels.interpolation import ( +from parcels.kernels.interpolation import ( UXPiecewiseLinearNode, XLinear, ZeroInterpolator, diff --git a/parcels/kernel.py b/parcels/kernel.py index 2f71263516..e0dfffcc46 100644 --- a/parcels/kernel.py +++ b/parcels/kernel.py @@ -8,12 +8,12 @@ import numpy as np -from parcels.application_kernels.advection import ( +from parcels.basegrid import GridType +from parcels.kernels.advection import ( AdvectionAnalytical, AdvectionRK4, AdvectionRK45, ) -from parcels.basegrid import GridType from parcels.tools._helpers import _assert_same_function_signature from parcels.tools.statuscodes import ( StatusCode, diff --git a/parcels/application_kernels/EOSseawaterproperties.py b/parcels/kernels/EOSseawaterproperties.py similarity index 100% rename from parcels/application_kernels/EOSseawaterproperties.py rename to parcels/kernels/EOSseawaterproperties.py diff --git a/parcels/application_kernels/TEOSseawaterdensity.py b/parcels/kernels/TEOSseawaterdensity.py similarity index 100% rename from parcels/application_kernels/TEOSseawaterdensity.py rename to parcels/kernels/TEOSseawaterdensity.py diff --git a/parcels/application_kernels/__init__.py b/parcels/kernels/__init__.py similarity index 100% rename from parcels/application_kernels/__init__.py rename to parcels/kernels/__init__.py diff --git a/parcels/application_kernels/advection.py b/parcels/kernels/advection.py similarity index 100% rename from parcels/application_kernels/advection.py rename to parcels/kernels/advection.py diff --git a/parcels/application_kernels/advectiondiffusion.py b/parcels/kernels/advectiondiffusion.py similarity index 100% rename from parcels/application_kernels/advectiondiffusion.py rename to parcels/kernels/advectiondiffusion.py diff --git a/parcels/application_kernels/interaction.py b/parcels/kernels/interaction.py similarity index 100% rename from parcels/application_kernels/interaction.py rename to parcels/kernels/interaction.py diff --git a/parcels/application_kernels/interpolation.py b/parcels/kernels/interpolation.py similarity index 100% rename from parcels/application_kernels/interpolation.py rename to parcels/kernels/interpolation.py diff --git a/parcels/particleset.py b/parcels/particleset.py index 0590dc0679..7db1cd7936 100644 --- a/parcels/particleset.py +++ b/parcels/particleset.py @@ -11,8 +11,8 @@ from parcels._core.utils.time import TimeInterval, maybe_convert_python_timedelta_to_numpy from parcels._reprs import particleset_repr -from parcels.application_kernels.advection import AdvectionRK4 from parcels.kernel import Kernel +from parcels.kernels.advection import AdvectionRK4 from parcels.particle import KernelParticle, Particle, create_particle_data from parcels.tools.converters import convert_to_flat_array from parcels.tools.loggers import logger diff --git a/tests-v3/test_interaction.py b/tests-v3/test_interaction.py index c20fdda881..9b3c8e1d8b 100644 --- a/tests-v3/test_interaction.py +++ b/tests-v3/test_interaction.py @@ -2,12 +2,6 @@ import pytest from parcels import Field, FieldSet, ParticleSet -from parcels.application_kernels.advection import AdvectionRK4 -from parcels.application_kernels.interaction import ( - AsymmetricAttraction, - MergeWithNearestNeighbor, - NearestNeighborWithinRange, -) from parcels.interaction.neighborsearch import ( BruteFlatNeighborSearch, BruteSphericalNeighborSearch, @@ -16,6 +10,12 @@ KDTreeFlatNeighborSearch, ) from parcels.interaction.neighborsearch.basehash import BaseHashNeighborSearch +from parcels.kernels.advection import AdvectionRK4 +from parcels.kernels.interaction import ( + AsymmetricAttraction, + MergeWithNearestNeighbor, + NearestNeighborWithinRange, +) from parcels.particle import InteractionParticle, Variable from tests.common_kernels import DoNothing from tests.utils import create_fieldset_unit_mesh, create_flat_positions, create_spherical_positions diff --git a/tests-v3/test_kernel_language.py b/tests-v3/test_kernel_language.py index 76b3ad1ba0..d68446dbc5 100644 --- a/tests-v3/test_kernel_language.py +++ b/tests-v3/test_kernel_language.py @@ -12,13 +12,13 @@ ParticleSet, Variable, ) -from parcels.application_kernels.EOSseawaterproperties import ( +from parcels.kernels.EOSseawaterproperties import ( PressureFromLatDepth, PtempFromTemp, TempFromPtemp, UNESCODensity, ) -from parcels.application_kernels.TEOSseawaterdensity import PolyTEOS10_bsq +from parcels.kernels.TEOSseawaterdensity import PolyTEOS10_bsq from tests.common_kernels import DoNothing from tests.utils import create_fieldset_unit_mesh diff --git a/tests/test_advection.py b/tests/test_advection.py index 906c55a979..c609087f6c 100644 --- a/tests/test_advection.py +++ b/tests/test_advection.py @@ -12,11 +12,11 @@ simple_UV_dataset, stommel_gyre_dataset, ) -from parcels.application_kernels.advection import AdvectionEE, AdvectionRK4, AdvectionRK4_3D, AdvectionRK45 -from parcels.application_kernels.advectiondiffusion import AdvectionDiffusionEM, AdvectionDiffusionM1 -from parcels.application_kernels.interpolation import CGrid_Velocity, XLinear from parcels.field import Field, VectorField from parcels.fieldset import FieldSet +from parcels.kernels.advection import AdvectionEE, AdvectionRK4, AdvectionRK4_3D, AdvectionRK45 +from parcels.kernels.advectiondiffusion import AdvectionDiffusionEM, AdvectionDiffusionM1 +from parcels.kernels.interpolation import CGrid_Velocity, XLinear from parcels.particle import Particle, Variable from parcels.particlefile import ParticleFile from parcels.particleset import ParticleSet diff --git a/tests/test_diffusion.py b/tests/test_diffusion.py index 65c9aad008..40b36ac370 100644 --- a/tests/test_diffusion.py +++ b/tests/test_diffusion.py @@ -5,10 +5,10 @@ from scipy import stats from parcels._datasets.structured.generated import simple_UV_dataset -from parcels.application_kernels import AdvectionDiffusionEM, AdvectionDiffusionM1, DiffusionUniformKh -from parcels.application_kernels.interpolation import XLinear from parcels.field import Field, VectorField from parcels.fieldset import FieldSet +from parcels.kernels import AdvectionDiffusionEM, AdvectionDiffusionM1, DiffusionUniformKh +from parcels.kernels.interpolation import XLinear from parcels.particle import Particle, Variable from parcels.particleset import ParticleSet from parcels.xgrid import XGrid diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index a1e18e2489..590870846f 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -5,8 +5,10 @@ from parcels._datasets.structured.generated import simple_UV_dataset from parcels._datasets.unstructured.generic import datasets as datasets_unstructured from parcels._index_search import _search_time_index -from parcels.application_kernels.advection import AdvectionRK4_3D -from parcels.application_kernels.interpolation import ( +from parcels.field import Field, VectorField +from parcels.fieldset import FieldSet +from parcels.kernels.advection import AdvectionRK4_3D +from parcels.kernels.interpolation import ( UXPiecewiseLinearNode, XFreeslip, XLinear, @@ -14,8 +16,6 @@ XPartialslip, ZeroInterpolator, ) -from parcels.field import Field, VectorField -from parcels.fieldset import FieldSet from parcels.particle import Particle, Variable from parcels.particlefile import ParticleFile from parcels.particleset import ParticleSet diff --git a/tests/utils.py b/tests/utils.py index c89cbea45b..ec514a8a03 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -10,9 +10,9 @@ import parcels from parcels._datasets.structured.generated import simple_UV_dataset -from parcels.application_kernels.interpolation import XLinear from parcels.field import Field, VectorField from parcels.fieldset import FieldSet +from parcels.kernels.interpolation import XLinear from parcels.xgrid import _FIELD_DATA_ORDERING, XGrid, get_axis_from_dim_name PROJECT_ROOT = Path(__file__).resolve().parents[1] From b271bacfe44fbcd20286181f617c843a772d5e14 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 15:18:28 +0200 Subject: [PATCH 05/45] Remove wildcard imports from kernels subpackage Also consolidate imports --- parcels/kernel.py | 2 +- parcels/kernels/__init__.py | 59 +++++++++++++++++++++++++++++--- parcels/particleset.py | 2 +- tests-v3/test_interaction.py | 2 +- tests-v3/test_kernel_language.py | 4 +-- tests/test_advection.py | 4 +-- tests/test_interpolation.py | 2 +- 7 files changed, 63 insertions(+), 12 deletions(-) diff --git a/parcels/kernel.py b/parcels/kernel.py index e0dfffcc46..8b29a36312 100644 --- a/parcels/kernel.py +++ b/parcels/kernel.py @@ -9,7 +9,7 @@ import numpy as np from parcels.basegrid import GridType -from parcels.kernels.advection import ( +from parcels.kernels import ( AdvectionAnalytical, AdvectionRK4, AdvectionRK45, diff --git a/parcels/kernels/__init__.py b/parcels/kernels/__init__.py index cd933324ed..502ca1a23e 100644 --- a/parcels/kernels/__init__.py +++ b/parcels/kernels/__init__.py @@ -1,4 +1,55 @@ -from .advection import * -from .advectiondiffusion import * -from .interaction import * -from .interpolation import * +from .advection import ( + AdvectionRK4, + AdvectionRK4_3D, + AdvectionRK4_3D_CROCO, + AdvectionEE, + AdvectionRK45, + AdvectionAnalytical, +) +from .advectiondiffusion import ( + AdvectionDiffusionM1, + AdvectionDiffusionEM, + DiffusionUniformKh, +) +from .interaction import ( + NearestNeighborWithinRange, + MergeWithNearestNeighbor, + AsymmetricAttraction, +) +from .interpolation import ( + ZeroInterpolator, + ZeroInterpolator_Vector, + XLinear, + CGrid_Velocity, + CGrid_Tracer, + XFreeslip, + XPartialslip, + XNearest, + UXPiecewiseConstantFace, + UXPiecewiseLinearNode, +) + +__all__ = [ + "AdvectionRK4", + "AdvectionRK4_3D", + "AdvectionRK4_3D_CROCO", + "AdvectionEE", + "AdvectionRK45", + "AdvectionAnalytical", + "AdvectionDiffusionM1", + "AdvectionDiffusionEM", + "DiffusionUniformKh", + "NearestNeighborWithinRange", + "MergeWithNearestNeighbor", + "AsymmetricAttraction", + "ZeroInterpolator", + "ZeroInterpolator_Vector", + "XLinear", + "CGrid_Velocity", + "CGrid_Tracer", + "XFreeslip", + "XPartialslip", + "XNearest", + "UXPiecewiseConstantFace", + "UXPiecewiseLinearNode", +] diff --git a/parcels/particleset.py b/parcels/particleset.py index 7db1cd7936..8c7722b73c 100644 --- a/parcels/particleset.py +++ b/parcels/particleset.py @@ -12,7 +12,7 @@ from parcels._core.utils.time import TimeInterval, maybe_convert_python_timedelta_to_numpy from parcels._reprs import particleset_repr from parcels.kernel import Kernel -from parcels.kernels.advection import AdvectionRK4 +from parcels.kernels import AdvectionRK4 from parcels.particle import KernelParticle, Particle, create_particle_data from parcels.tools.converters import convert_to_flat_array from parcels.tools.loggers import logger diff --git a/tests-v3/test_interaction.py b/tests-v3/test_interaction.py index 9b3c8e1d8b..e1fc562cf1 100644 --- a/tests-v3/test_interaction.py +++ b/tests-v3/test_interaction.py @@ -10,7 +10,7 @@ KDTreeFlatNeighborSearch, ) from parcels.interaction.neighborsearch.basehash import BaseHashNeighborSearch -from parcels.kernels.advection import AdvectionRK4 +from parcels.kernels import AdvectionRK4 from parcels.kernels.interaction import ( AsymmetricAttraction, MergeWithNearestNeighbor, diff --git a/tests-v3/test_kernel_language.py b/tests-v3/test_kernel_language.py index d68446dbc5..d9019e4213 100644 --- a/tests-v3/test_kernel_language.py +++ b/tests-v3/test_kernel_language.py @@ -12,13 +12,13 @@ ParticleSet, Variable, ) -from parcels.kernels.EOSseawaterproperties import ( +from parcels.kernels import ( PressureFromLatDepth, PtempFromTemp, TempFromPtemp, UNESCODensity, ) -from parcels.kernels.TEOSseawaterdensity import PolyTEOS10_bsq +from parcels.kernels import PolyTEOS10_bsq from tests.common_kernels import DoNothing from tests.utils import create_fieldset_unit_mesh diff --git a/tests/test_advection.py b/tests/test_advection.py index c609087f6c..47c273a081 100644 --- a/tests/test_advection.py +++ b/tests/test_advection.py @@ -14,8 +14,8 @@ ) from parcels.field import Field, VectorField from parcels.fieldset import FieldSet -from parcels.kernels.advection import AdvectionEE, AdvectionRK4, AdvectionRK4_3D, AdvectionRK45 -from parcels.kernels.advectiondiffusion import AdvectionDiffusionEM, AdvectionDiffusionM1 +from parcels.kernels import AdvectionEE, AdvectionRK4, AdvectionRK4_3D, AdvectionRK45 +from parcels.kernels import AdvectionDiffusionEM, AdvectionDiffusionM1 from parcels.kernels.interpolation import CGrid_Velocity, XLinear from parcels.particle import Particle, Variable from parcels.particlefile import ParticleFile diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index 590870846f..43736c03b3 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -7,7 +7,7 @@ from parcels._index_search import _search_time_index from parcels.field import Field, VectorField from parcels.fieldset import FieldSet -from parcels.kernels.advection import AdvectionRK4_3D +from parcels.kernels import AdvectionRK4_3D from parcels.kernels.interpolation import ( UXPiecewiseLinearNode, XFreeslip, From c55256da1e045a523b4989d7abb0832b1d0fc17a Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 15:25:31 +0200 Subject: [PATCH 06/45] Move kernels/interpolation.py to interpolators.py --- parcels/field.py | 2 +- .../interpolation.py => interpolators.py} | 0 parcels/kernels/__init__.py | 42 ++++++------------- tests/test_advection.py | 2 +- tests/test_diffusion.py | 2 +- tests/test_field.py | 3 +- tests/test_interpolation.py | 2 +- tests/test_particleset_execute.py | 2 +- tests/test_uxarray_fieldset.py | 6 ++- tests/utils.py | 2 +- 10 files changed, 24 insertions(+), 39 deletions(-) rename parcels/{kernels/interpolation.py => interpolators.py} (100%) diff --git a/parcels/field.py b/parcels/field.py index d0de5666fd..cc80e56e82 100644 --- a/parcels/field.py +++ b/parcels/field.py @@ -11,7 +11,7 @@ from parcels._core.utils.time import TimeInterval from parcels._reprs import default_repr from parcels._typing import VectorType -from parcels.kernels.interpolation import ( +from parcels.interpolators import ( UXPiecewiseLinearNode, XLinear, ZeroInterpolator, diff --git a/parcels/kernels/interpolation.py b/parcels/interpolators.py similarity index 100% rename from parcels/kernels/interpolation.py rename to parcels/interpolators.py diff --git a/parcels/kernels/__init__.py b/parcels/kernels/__init__.py index 502ca1a23e..3a7fbc5b2b 100644 --- a/parcels/kernels/__init__.py +++ b/parcels/kernels/__init__.py @@ -16,40 +16,22 @@ MergeWithNearestNeighbor, AsymmetricAttraction, ) -from .interpolation import ( - ZeroInterpolator, - ZeroInterpolator_Vector, - XLinear, - CGrid_Velocity, - CGrid_Tracer, - XFreeslip, - XPartialslip, - XNearest, - UXPiecewiseConstantFace, - UXPiecewiseLinearNode, -) -__all__ = [ - "AdvectionRK4", - "AdvectionRK4_3D", - "AdvectionRK4_3D_CROCO", + +__all__ = [ # noqa: RUF022 + # advection + "AdvectionAnalytical", "AdvectionEE", + "AdvectionRK4_3D_CROCO", + "AdvectionRK4_3D", + "AdvectionRK4", "AdvectionRK45", - "AdvectionAnalytical", - "AdvectionDiffusionM1", + # advectiondiffusion "AdvectionDiffusionEM", + "AdvectionDiffusionM1", "DiffusionUniformKh", - "NearestNeighborWithinRange", - "MergeWithNearestNeighbor", + # interaction "AsymmetricAttraction", - "ZeroInterpolator", - "ZeroInterpolator_Vector", - "XLinear", - "CGrid_Velocity", - "CGrid_Tracer", - "XFreeslip", - "XPartialslip", - "XNearest", - "UXPiecewiseConstantFace", - "UXPiecewiseLinearNode", + "MergeWithNearestNeighbor", + "NearestNeighborWithinRange", ] diff --git a/tests/test_advection.py b/tests/test_advection.py index 47c273a081..152b493adf 100644 --- a/tests/test_advection.py +++ b/tests/test_advection.py @@ -16,7 +16,7 @@ from parcels.fieldset import FieldSet from parcels.kernels import AdvectionEE, AdvectionRK4, AdvectionRK4_3D, AdvectionRK45 from parcels.kernels import AdvectionDiffusionEM, AdvectionDiffusionM1 -from parcels.kernels.interpolation import CGrid_Velocity, XLinear +from parcels.interpolators import CGrid_Velocity, XLinear from parcels.particle import Particle, Variable from parcels.particlefile import ParticleFile from parcels.particleset import ParticleSet diff --git a/tests/test_diffusion.py b/tests/test_diffusion.py index 40b36ac370..ec66cb78b1 100644 --- a/tests/test_diffusion.py +++ b/tests/test_diffusion.py @@ -8,7 +8,7 @@ from parcels.field import Field, VectorField from parcels.fieldset import FieldSet from parcels.kernels import AdvectionDiffusionEM, AdvectionDiffusionM1, DiffusionUniformKh -from parcels.kernels.interpolation import XLinear +from parcels.interpolators import XLinear from parcels.particle import Particle, Variable from parcels.particleset import ParticleSet from parcels.xgrid import XGrid diff --git a/tests/test_field.py b/tests/test_field.py index 75c6f6dc98..d9208c8453 100644 --- a/tests/test_field.py +++ b/tests/test_field.py @@ -5,12 +5,13 @@ import uxarray as ux import xarray as xr -from parcels import Field, UXPiecewiseConstantFace, UXPiecewiseLinearNode, VectorField +from parcels import Field, VectorField from parcels._datasets.structured.generic import T as T_structured from parcels._datasets.structured.generic import datasets as datasets_structured from parcels._datasets.unstructured.generic import datasets as datasets_unstructured from parcels.uxgrid import UxGrid from parcels.xgrid import XGrid +from parcels.interpolators import UXPiecewiseConstantFace, UXPiecewiseLinearNode def test_field_init_param_types(): diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index 43736c03b3..7466ecf6ab 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -8,7 +8,7 @@ from parcels.field import Field, VectorField from parcels.fieldset import FieldSet from parcels.kernels import AdvectionRK4_3D -from parcels.kernels.interpolation import ( +from parcels.interpolators import ( UXPiecewiseLinearNode, XFreeslip, XLinear, diff --git a/tests/test_particleset_execute.py b/tests/test_particleset_execute.py index fbad3d5ece..7a8ccb85fb 100644 --- a/tests/test_particleset_execute.py +++ b/tests/test_particleset_execute.py @@ -11,10 +11,10 @@ Particle, ParticleSet, StatusCode, - UXPiecewiseConstantFace, Variable, VectorField, ) +from parcels.interpolators import UXPiecewiseConstantFace from parcels._datasets.structured.generated import simple_UV_dataset from parcels._datasets.structured.generic import datasets as datasets_structured from parcels._datasets.unstructured.generic import datasets as datasets_unstructured diff --git a/tests/test_uxarray_fieldset.py b/tests/test_uxarray_fieldset.py index 0ab13f8cae..e6fb7af693 100644 --- a/tests/test_uxarray_fieldset.py +++ b/tests/test_uxarray_fieldset.py @@ -7,11 +7,13 @@ FieldSet, Particle, ParticleSet, - UXPiecewiseConstantFace, - UXPiecewiseLinearNode, VectorField, download_example_dataset, ) +from parcels.interpolators import ( + UXPiecewiseConstantFace, + UXPiecewiseLinearNode, +) from parcels._datasets.unstructured.generic import datasets as datasets_unstructured from parcels.uxgrid import UxGrid diff --git a/tests/utils.py b/tests/utils.py index ec514a8a03..04ca73a356 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -12,7 +12,7 @@ from parcels._datasets.structured.generated import simple_UV_dataset from parcels.field import Field, VectorField from parcels.fieldset import FieldSet -from parcels.kernels.interpolation import XLinear +from parcels.interpolators import XLinear from parcels.xgrid import _FIELD_DATA_ORDERING, XGrid, get_axis_from_dim_name PROJECT_ROOT = Path(__file__).resolve().parents[1] From f7e29206b764f003cc172b96df2acc87d935b07e Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 15:30:50 +0200 Subject: [PATCH 07/45] Remove some wildcards --- parcels/__init__.py | 18 +++++++++++------- parcels/tools/__init__.py | 1 - 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/parcels/__init__.py b/parcels/__init__.py index 37bedbfc13..c3977371b8 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -4,14 +4,18 @@ import warnings as _warnings -from parcels.field import * -from parcels.fieldset import * -from parcels.interaction import * -from parcels.kernel import * +from parcels.field import Field, VectorField +from parcels.fieldset import FieldSet +from parcels.kernel import Kernel from parcels.kernels import * -from parcels.particle import * -from parcels.particlefile import * -from parcels.particleset import * +from parcels.particle import ( + KernelParticle, # ? remove? + Particle, + ParticleClass, + Variable, +) +from parcels.particlefile import ParticleFile +from parcels.particleset import ParticleSet from parcels.tools import * _warnings.warn( diff --git a/parcels/tools/__init__.py b/parcels/tools/__init__.py index 6909c6fb44..e8732cc3ab 100644 --- a/parcels/tools/__init__.py +++ b/parcels/tools/__init__.py @@ -3,5 +3,4 @@ from .interpolation_utils import * from .loggers import * from .statuscodes import * -from .timer import * from .warnings import * From ad3a55de704108cb79c09e82584def48bddabe5b Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 15:45:37 +0200 Subject: [PATCH 08/45] Remove kernels from `parcels` namespace --- parcels/__init__.py | 1 - tests/test_advection.py | 2 +- tests/test_kernel.py | 2 +- tests/test_particlefile.py | 3 ++- tests/test_particleset_execute.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/parcels/__init__.py b/parcels/__init__.py index c3977371b8..406069c14d 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -7,7 +7,6 @@ from parcels.field import Field, VectorField from parcels.fieldset import FieldSet from parcels.kernel import Kernel -from parcels.kernels import * from parcels.particle import ( KernelParticle, # ? remove? Particle, diff --git a/tests/test_advection.py b/tests/test_advection.py index 152b493adf..e1c602f60b 100644 --- a/tests/test_advection.py +++ b/tests/test_advection.py @@ -245,7 +245,7 @@ def test_radialrotation(npart=10): starttime = np.arange(np.timedelta64(0, "s"), npart * dt, dt) pset = parcels.ParticleSet(fieldset, lon=lon, lat=lat, time=starttime) - pset.execute(parcels.AdvectionRK4, endtime=np.timedelta64(10, "m"), dt=dt) + pset.execute(parcels.kernels.AdvectionRK4, endtime=np.timedelta64(10, "m"), dt=dt) theta = 2 * np.pi * (pset.time - starttime) / np.timedelta64(24 * 3600, "s") true_lon = (lon - 30.0) * np.cos(theta) + 30.0 diff --git a/tests/test_kernel.py b/tests/test_kernel.py index 3ece81a744..540e33114a 100644 --- a/tests/test_kernel.py +++ b/tests/test_kernel.py @@ -1,8 +1,8 @@ import numpy as np import pytest +from parcels.kernels import AdvectionRK4 from parcels import ( - AdvectionRK4, Field, FieldSet, ParticleSet, diff --git a/tests/test_particlefile.py b/tests/test_particlefile.py index 5937f59f7f..5ec91e7320 100755 --- a/tests/test_particlefile.py +++ b/tests/test_particlefile.py @@ -8,7 +8,8 @@ from zarr.storage import MemoryStore import parcels -from parcels import AdvectionRK4, Field, FieldSet, Particle, ParticleSet, Variable, VectorField +from parcels import Field, FieldSet, Particle, ParticleSet, Variable, VectorField +from parcels.kernels import AdvectionRK4 from parcels._core.utils.time import TimeInterval from parcels._datasets.structured.generic import datasets from parcels.particle import Particle, create_particle_data, get_default_particle diff --git a/tests/test_particleset_execute.py b/tests/test_particleset_execute.py index 7a8ccb85fb..049d4389d6 100644 --- a/tests/test_particleset_execute.py +++ b/tests/test_particleset_execute.py @@ -5,7 +5,6 @@ import pytest from parcels import ( - AdvectionEE, Field, FieldSet, Particle, @@ -14,6 +13,7 @@ Variable, VectorField, ) +from parcels.kernels import AdvectionEE from parcels.interpolators import UXPiecewiseConstantFace from parcels._datasets.structured.generated import simple_UV_dataset from parcels._datasets.structured.generic import datasets as datasets_structured From f17ebced20da701c92d5a06c1191314068888c7d Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 15:46:57 +0200 Subject: [PATCH 09/45] Make spatialhash private --- parcels/{spatialhash.py => _spatialhash.py} | 0 parcels/basegrid.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename parcels/{spatialhash.py => _spatialhash.py} (100%) diff --git a/parcels/spatialhash.py b/parcels/_spatialhash.py similarity index 100% rename from parcels/spatialhash.py rename to parcels/_spatialhash.py diff --git a/parcels/basegrid.py b/parcels/basegrid.py index 37d56f6127..9b353090ce 100644 --- a/parcels/basegrid.py +++ b/parcels/basegrid.py @@ -6,7 +6,7 @@ import numpy as np -from parcels.spatialhash import SpatialHash +from parcels._spatialhash import SpatialHash if TYPE_CHECKING: import numpy as np From ff4e8da161a2fd7cfd2a0cb1508cd01ccb31ebab Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 15:48:14 +0200 Subject: [PATCH 10/45] Move warnings out of tools and make private --- parcels/__init__.py | 10 ++++++++-- parcels/{tools/warnings.py => _warnings.py} | 0 parcels/kernel.py | 2 +- parcels/particleset.py | 2 +- parcels/tools/__init__.py | 1 - 5 files changed, 10 insertions(+), 5 deletions(-) rename parcels/{tools/warnings.py => _warnings.py} (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index 406069c14d..6a5d86d8fb 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -2,7 +2,7 @@ __version__ = version -import warnings as _warnings +import warnings as _stdlib_warnings from parcels.field import Field, VectorField from parcels.fieldset import FieldSet @@ -13,11 +13,17 @@ ParticleClass, Variable, ) +from parcels._warnings import ( + FieldSetWarning, + FileWarning, + KernelWarning, + ParticleSetWarning, +) from parcels.particlefile import ParticleFile from parcels.particleset import ParticleSet from parcels.tools import * -_warnings.warn( +_stdlib_warnings.warn( "This is an alpha version of Parcels v4. The API is not stable and may change without deprecation warnings.", UserWarning, stacklevel=2, diff --git a/parcels/tools/warnings.py b/parcels/_warnings.py similarity index 100% rename from parcels/tools/warnings.py rename to parcels/_warnings.py diff --git a/parcels/kernel.py b/parcels/kernel.py index 8b29a36312..44336bfd91 100644 --- a/parcels/kernel.py +++ b/parcels/kernel.py @@ -24,7 +24,7 @@ _raise_grid_searching_error, _raise_time_extrapolation_error, ) -from parcels.tools.warnings import KernelWarning +from parcels._warnings import KernelWarning if TYPE_CHECKING: from collections.abc import Callable diff --git a/parcels/particleset.py b/parcels/particleset.py index 8c7722b73c..dc4bfde94b 100644 --- a/parcels/particleset.py +++ b/parcels/particleset.py @@ -17,7 +17,7 @@ from parcels.tools.converters import convert_to_flat_array from parcels.tools.loggers import logger from parcels.tools.statuscodes import StatusCode -from parcels.tools.warnings import ParticleSetWarning +from parcels._warnings import ParticleSetWarning __all__ = ["ParticleSet"] diff --git a/parcels/tools/__init__.py b/parcels/tools/__init__.py index e8732cc3ab..04fc51adf3 100644 --- a/parcels/tools/__init__.py +++ b/parcels/tools/__init__.py @@ -3,4 +3,3 @@ from .interpolation_utils import * from .loggers import * from .statuscodes import * -from .warnings import * From 28aee5ef5640d57831d6101f661ba149cfb76063 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 15:54:00 +0200 Subject: [PATCH 11/45] Move logger out of tools --- parcels/__init__.py | 1 + parcels/{tools/loggers.py => _logger.py} | 0 parcels/fieldset.py | 2 +- parcels/particleset.py | 2 +- parcels/tools/__init__.py | 2 +- 5 files changed, 4 insertions(+), 3 deletions(-) rename parcels/{tools/loggers.py => _logger.py} (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index 6a5d86d8fb..2ebdf87598 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -21,6 +21,7 @@ ) from parcels.particlefile import ParticleFile from parcels.particleset import ParticleSet +from parcels._logger import logger from parcels.tools import * _stdlib_warnings.warn( diff --git a/parcels/tools/loggers.py b/parcels/_logger.py similarity index 100% rename from parcels/tools/loggers.py rename to parcels/_logger.py diff --git a/parcels/fieldset.py b/parcels/fieldset.py index 95df623493..909952a0f6 100644 --- a/parcels/fieldset.py +++ b/parcels/fieldset.py @@ -14,7 +14,7 @@ from parcels._typing import Mesh from parcels.field import Field, VectorField from parcels.tools.converters import Geographic, GeographicPolar -from parcels.tools.loggers import logger +from parcels import logger from parcels.xgrid import _DEFAULT_XGCM_KWARGS, XGrid if TYPE_CHECKING: diff --git a/parcels/particleset.py b/parcels/particleset.py index dc4bfde94b..9bdd7967a5 100644 --- a/parcels/particleset.py +++ b/parcels/particleset.py @@ -15,7 +15,7 @@ from parcels.kernels import AdvectionRK4 from parcels.particle import KernelParticle, Particle, create_particle_data from parcels.tools.converters import convert_to_flat_array -from parcels.tools.loggers import logger +from parcels import logger from parcels.tools.statuscodes import StatusCode from parcels._warnings import ParticleSetWarning diff --git a/parcels/tools/__init__.py b/parcels/tools/__init__.py index 04fc51adf3..2ded4a7c4a 100644 --- a/parcels/tools/__init__.py +++ b/parcels/tools/__init__.py @@ -1,5 +1,5 @@ from .converters import * from .exampledata_utils import * from .interpolation_utils import * -from .loggers import * +from .._logger import * from .statuscodes import * From a19966f8ef1c595deeec0ccf6f7fec535d345b2c Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 15:54:52 +0200 Subject: [PATCH 12/45] Make v4_compat_patch private --- parcels/tools/exampledata_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parcels/tools/exampledata_utils.py b/parcels/tools/exampledata_utils.py index 5513987770..eb6c106fc1 100644 --- a/parcels/tools/exampledata_utils.py +++ b/parcels/tools/exampledata_utils.py @@ -180,12 +180,12 @@ def download_example_dataset(dataset: str, data_home=None): for file_name in odie.registry: if file_name.startswith(dataset): should_patch = dataset == "GlobCurrent_example_data" - odie.fetch(file_name, processor=v4_compat_patch if should_patch else None) + odie.fetch(file_name, processor=_v4_compat_patch if should_patch else None) return dataset_folder -def v4_compat_patch(fname, action, pup): +def _v4_compat_patch(fname, action, pup): """ Patch the GlobCurrent example dataset to be compatible with v4. From 2b42a450b107e1139234e9a40012ab1594d07f43 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 15:56:48 +0200 Subject: [PATCH 13/45] Move exampledata_utils out of tools and call tutorials --- parcels/{tools => }/_v3to4.py | 0 parcels/tools/__init__.py | 2 +- parcels/{tools/exampledata_utils.py => tutorial.py} | 2 +- tests-v3/tools/test_exampledata_utils.py | 2 +- tests/test_index_search.py | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename parcels/{tools => }/_v3to4.py (100%) rename parcels/{tools/exampledata_utils.py => tutorial.py} (99%) diff --git a/parcels/tools/_v3to4.py b/parcels/_v3to4.py similarity index 100% rename from parcels/tools/_v3to4.py rename to parcels/_v3to4.py diff --git a/parcels/tools/__init__.py b/parcels/tools/__init__.py index 2ded4a7c4a..110dd89f04 100644 --- a/parcels/tools/__init__.py +++ b/parcels/tools/__init__.py @@ -1,5 +1,5 @@ from .converters import * -from .exampledata_utils import * +from ..tutorial import * from .interpolation_utils import * from .._logger import * from .statuscodes import * diff --git a/parcels/tools/exampledata_utils.py b/parcels/tutorial.py similarity index 99% rename from parcels/tools/exampledata_utils.py rename to parcels/tutorial.py index eb6c106fc1..00dc3bae61 100644 --- a/parcels/tools/exampledata_utils.py +++ b/parcels/tutorial.py @@ -5,7 +5,7 @@ import pooch import xarray as xr -from parcels.tools._v3to4 import patch_dataset_v4_compat +from parcels._v3to4 import patch_dataset_v4_compat __all__ = ["download_example_dataset", "list_example_datasets"] diff --git a/tests-v3/tools/test_exampledata_utils.py b/tests-v3/tools/test_exampledata_utils.py index 94ed9cf833..9037e4546e 100644 --- a/tests-v3/tools/test_exampledata_utils.py +++ b/tests-v3/tools/test_exampledata_utils.py @@ -1,7 +1,7 @@ import pytest import requests -from parcels.tools.exampledata_utils import ( +from parcels.tutorial import ( _get_pooch, download_example_dataset, list_example_datasets, diff --git a/tests/test_index_search.py b/tests/test_index_search.py index b664ae42f9..f2e4d13c95 100644 --- a/tests/test_index_search.py +++ b/tests/test_index_search.py @@ -6,7 +6,7 @@ from parcels._datasets.structured.generic import datasets from parcels._index_search import _search_indices_curvilinear_2d from parcels.field import Field -from parcels.tools.exampledata_utils import download_example_dataset +from parcels.tutorial import download_example_dataset from parcels.xgrid import XGrid From 827d68c320e5d23e08e53860c0b9215283f57fbd Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 16:03:59 +0200 Subject: [PATCH 14/45] Rename module tutorial to _tutorial Also update other modules --- parcels/__init__.py | 1 + parcels/{tutorial.py => _tutorial.py} | 0 parcels/fieldset.py | 2 +- parcels/particleset.py | 2 +- parcels/tools/__init__.py | 2 -- tests-v3/tools/test_exampledata_utils.py | 2 +- tests/test_index_search.py | 2 +- 7 files changed, 5 insertions(+), 6 deletions(-) rename parcels/{tutorial.py => _tutorial.py} (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index 2ebdf87598..f3a72055b9 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -23,6 +23,7 @@ from parcels.particleset import ParticleSet from parcels._logger import logger from parcels.tools import * +from parcels._tutorial import download_example_dataset, list_example_datasets _stdlib_warnings.warn( "This is an alpha version of Parcels v4. The API is not stable and may change without deprecation warnings.", diff --git a/parcels/tutorial.py b/parcels/_tutorial.py similarity index 100% rename from parcels/tutorial.py rename to parcels/_tutorial.py diff --git a/parcels/fieldset.py b/parcels/fieldset.py index 909952a0f6..df72b7f0ea 100644 --- a/parcels/fieldset.py +++ b/parcels/fieldset.py @@ -14,7 +14,7 @@ from parcels._typing import Mesh from parcels.field import Field, VectorField from parcels.tools.converters import Geographic, GeographicPolar -from parcels import logger +from parcels._logger import logger from parcels.xgrid import _DEFAULT_XGCM_KWARGS, XGrid if TYPE_CHECKING: diff --git a/parcels/particleset.py b/parcels/particleset.py index 9bdd7967a5..45d3464048 100644 --- a/parcels/particleset.py +++ b/parcels/particleset.py @@ -15,7 +15,7 @@ from parcels.kernels import AdvectionRK4 from parcels.particle import KernelParticle, Particle, create_particle_data from parcels.tools.converters import convert_to_flat_array -from parcels import logger +from parcels._logger import logger from parcels.tools.statuscodes import StatusCode from parcels._warnings import ParticleSetWarning diff --git a/parcels/tools/__init__.py b/parcels/tools/__init__.py index 110dd89f04..59d58a56d9 100644 --- a/parcels/tools/__init__.py +++ b/parcels/tools/__init__.py @@ -1,5 +1,3 @@ from .converters import * -from ..tutorial import * from .interpolation_utils import * -from .._logger import * from .statuscodes import * diff --git a/tests-v3/tools/test_exampledata_utils.py b/tests-v3/tools/test_exampledata_utils.py index 9037e4546e..3169a07c2e 100644 --- a/tests-v3/tools/test_exampledata_utils.py +++ b/tests-v3/tools/test_exampledata_utils.py @@ -1,7 +1,7 @@ import pytest import requests -from parcels.tutorial import ( +from parcels._tutorial import ( _get_pooch, download_example_dataset, list_example_datasets, diff --git a/tests/test_index_search.py b/tests/test_index_search.py index f2e4d13c95..a940216d58 100644 --- a/tests/test_index_search.py +++ b/tests/test_index_search.py @@ -6,7 +6,7 @@ from parcels._datasets.structured.generic import datasets from parcels._index_search import _search_indices_curvilinear_2d from parcels.field import Field -from parcels.tutorial import download_example_dataset +from parcels._tutorial import download_example_dataset from parcels.xgrid import XGrid From 9215a020e0f043d539641d9c0aae5dbfca26029d Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 16:06:51 +0200 Subject: [PATCH 15/45] Rename tools to utils --- parcels/__init__.py | 2 +- parcels/_index_search.py | 2 +- parcels/_interpolation.py | 2 +- parcels/field.py | 6 +++--- parcels/fieldset.py | 2 +- parcels/interaction/interactionkernel.py | 2 +- parcels/interpolators.py | 2 +- parcels/kernel.py | 4 ++-- parcels/kernels/advection.py | 4 ++-- parcels/kernels/interaction.py | 2 +- parcels/particle.py | 2 +- parcels/particlefile.py | 2 +- parcels/particleset.py | 4 ++-- parcels/{tools => utils}/__init__.py | 0 parcels/{tools => utils}/_helpers.py | 0 parcels/{tools => utils}/converters.py | 0 parcels/{tools => utils}/interpolation_utils.py | 0 parcels/{tools => utils}/statuscodes.py | 0 parcels/{tools => utils}/timer.py | 0 tests-v3/test_fieldset.py | 2 +- tests-v3/tools/test_helpers.py | 4 ++-- tests/common_kernels.py | 2 +- tests/test_advection.py | 2 +- tests/test_interpolation.py | 2 +- tests/test_particlefile.py | 2 +- tests/test_particleset_execute.py | 2 +- 26 files changed, 26 insertions(+), 26 deletions(-) rename parcels/{tools => utils}/__init__.py (100%) rename parcels/{tools => utils}/_helpers.py (100%) rename parcels/{tools => utils}/converters.py (100%) rename parcels/{tools => utils}/interpolation_utils.py (100%) rename parcels/{tools => utils}/statuscodes.py (100%) rename parcels/{tools => utils}/timer.py (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index f3a72055b9..a6316febcc 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -22,7 +22,7 @@ from parcels.particlefile import ParticleFile from parcels.particleset import ParticleSet from parcels._logger import logger -from parcels.tools import * +from parcels.utils import * from parcels._tutorial import download_example_dataset, list_example_datasets _stdlib_warnings.warn( diff --git a/parcels/_index_search.py b/parcels/_index_search.py index 08d73e560f..9bbc166233 100644 --- a/parcels/_index_search.py +++ b/parcels/_index_search.py @@ -5,7 +5,7 @@ import numpy as np -from parcels.tools.statuscodes import _raise_time_extrapolation_error +from parcels.utils.statuscodes import _raise_time_extrapolation_error if TYPE_CHECKING: from parcels.xgrid import XGrid diff --git a/parcels/_interpolation.py b/parcels/_interpolation.py index 88a2864dca..e38f0d0d0f 100644 --- a/parcels/_interpolation.py +++ b/parcels/_interpolation.py @@ -4,7 +4,7 @@ import numpy as np from parcels._typing import GridIndexingType -from parcels.tools._helpers import should_calculate_next_ti +from parcels.utils._helpers import should_calculate_next_ti @dataclass diff --git a/parcels/field.py b/parcels/field.py index cc80e56e82..046b2ab607 100644 --- a/parcels/field.py +++ b/parcels/field.py @@ -18,12 +18,12 @@ ZeroInterpolator_Vector, ) from parcels.particle import KernelParticle -from parcels.tools._helpers import _assert_same_function_signature -from parcels.tools.converters import ( +from parcels.utils._helpers import _assert_same_function_signature +from parcels.utils.converters import ( UnitConverter, unitconverters_map, ) -from parcels.tools.statuscodes import ( +from parcels.utils.statuscodes import ( AllParcelsErrorCodes, StatusCode, ) diff --git a/parcels/fieldset.py b/parcels/fieldset.py index df72b7f0ea..938f4f9a2f 100644 --- a/parcels/fieldset.py +++ b/parcels/fieldset.py @@ -13,7 +13,7 @@ from parcels._core.utils.time import is_compatible as datetime_is_compatible from parcels._typing import Mesh from parcels.field import Field, VectorField -from parcels.tools.converters import Geographic, GeographicPolar +from parcels.utils.converters import Geographic, GeographicPolar from parcels._logger import logger from parcels.xgrid import _DEFAULT_XGCM_KWARGS, XGrid diff --git a/parcels/interaction/interactionkernel.py b/parcels/interaction/interactionkernel.py index 039297f5d6..520894e962 100644 --- a/parcels/interaction/interactionkernel.py +++ b/parcels/interaction/interactionkernel.py @@ -7,7 +7,7 @@ from parcels._compat import MPI from parcels.field import VectorField from parcels.kernel import BaseKernel -from parcels.tools.statuscodes import StatusCode +from parcels.utils.statuscodes import StatusCode __all__ = ["InteractionKernel"] diff --git a/parcels/interpolators.py b/parcels/interpolators.py index 8caf5231a3..2759964397 100644 --- a/parcels/interpolators.py +++ b/parcels/interpolators.py @@ -8,7 +8,7 @@ import xarray as xr from dask import is_dask_collection -import parcels.tools.interpolation_utils as i_u +import parcels.utils.interpolation_utils as i_u if TYPE_CHECKING: from parcels.field import Field, VectorField diff --git a/parcels/kernel.py b/parcels/kernel.py index 44336bfd91..36b4101a30 100644 --- a/parcels/kernel.py +++ b/parcels/kernel.py @@ -14,8 +14,8 @@ AdvectionRK4, AdvectionRK45, ) -from parcels.tools._helpers import _assert_same_function_signature -from parcels.tools.statuscodes import ( +from parcels.utils._helpers import _assert_same_function_signature +from parcels.utils.statuscodes import ( StatusCode, _raise_field_interpolation_error, _raise_field_out_of_bound_error, diff --git a/parcels/kernels/advection.py b/parcels/kernels/advection.py index 1023f8d88e..fc907b3cb4 100644 --- a/parcels/kernels/advection.py +++ b/parcels/kernels/advection.py @@ -4,7 +4,7 @@ import numpy as np -from parcels.tools.statuscodes import StatusCode +from parcels.utils.statuscodes import StatusCode __all__ = [ "AdvectionAnalytical", @@ -193,7 +193,7 @@ def AdvectionAnalytical(particles, fieldset): # pragma: no cover """ import numpy as np - import parcels.tools.interpolation_utils as i_u + import parcels.utils.interpolation_utils as i_u tol = 1e-10 I_s = 10 # number of intermediate time steps diff --git a/parcels/kernels/interaction.py b/parcels/kernels/interaction.py index 41f4b18dd8..018cd657b7 100644 --- a/parcels/kernels/interaction.py +++ b/parcels/kernels/interaction.py @@ -2,7 +2,7 @@ import numpy as np -from parcels.tools.statuscodes import StatusCode +from parcels.utils.statuscodes import StatusCode __all__ = ["AsymmetricAttraction", "MergeWithNearestNeighbor", "NearestNeighborWithinRange"] diff --git a/parcels/particle.py b/parcels/particle.py index 59c3457087..d51fd8d281 100644 --- a/parcels/particle.py +++ b/parcels/particle.py @@ -10,7 +10,7 @@ from parcels._compat import _attrgetter_helper from parcels._core.utils.time import TimeInterval from parcels._reprs import _format_list_items_multiline -from parcels.tools.statuscodes import StatusCode +from parcels.utils.statuscodes import StatusCode __all__ = ["KernelParticle", "Particle", "ParticleClass", "Variable"] _TO_WRITE_OPTIONS = [True, False, "once"] diff --git a/parcels/particlefile.py b/parcels/particlefile.py index bcf865cee2..e02b4caa25 100644 --- a/parcels/particlefile.py +++ b/parcels/particlefile.py @@ -15,7 +15,7 @@ import parcels from parcels.particle import _SAME_AS_FIELDSET_TIME_INTERVAL, ParticleClass -from parcels.tools._helpers import timedelta_to_float +from parcels.utils._helpers import timedelta_to_float if TYPE_CHECKING: from parcels._core.utils.time import TimeInterval diff --git a/parcels/particleset.py b/parcels/particleset.py index 45d3464048..5038253b47 100644 --- a/parcels/particleset.py +++ b/parcels/particleset.py @@ -14,9 +14,9 @@ from parcels.kernel import Kernel from parcels.kernels import AdvectionRK4 from parcels.particle import KernelParticle, Particle, create_particle_data -from parcels.tools.converters import convert_to_flat_array +from parcels.utils.converters import convert_to_flat_array from parcels._logger import logger -from parcels.tools.statuscodes import StatusCode +from parcels.utils.statuscodes import StatusCode from parcels._warnings import ParticleSetWarning __all__ = ["ParticleSet"] diff --git a/parcels/tools/__init__.py b/parcels/utils/__init__.py similarity index 100% rename from parcels/tools/__init__.py rename to parcels/utils/__init__.py diff --git a/parcels/tools/_helpers.py b/parcels/utils/_helpers.py similarity index 100% rename from parcels/tools/_helpers.py rename to parcels/utils/_helpers.py diff --git a/parcels/tools/converters.py b/parcels/utils/converters.py similarity index 100% rename from parcels/tools/converters.py rename to parcels/utils/converters.py diff --git a/parcels/tools/interpolation_utils.py b/parcels/utils/interpolation_utils.py similarity index 100% rename from parcels/tools/interpolation_utils.py rename to parcels/utils/interpolation_utils.py diff --git a/parcels/tools/statuscodes.py b/parcels/utils/statuscodes.py similarity index 100% rename from parcels/tools/statuscodes.py rename to parcels/utils/statuscodes.py diff --git a/parcels/tools/timer.py b/parcels/utils/timer.py similarity index 100% rename from parcels/tools/timer.py rename to parcels/utils/timer.py diff --git a/tests-v3/test_fieldset.py b/tests-v3/test_fieldset.py index fd83a28bef..860f7e897e 100644 --- a/tests-v3/test_fieldset.py +++ b/tests-v3/test_fieldset.py @@ -13,7 +13,7 @@ Variable, ) from parcels.field import VectorField -from parcels.tools.converters import GeographicPolar, UnitConverter +from parcels.utils.converters import GeographicPolar, UnitConverter from tests.utils import TEST_DATA diff --git a/tests-v3/tools/test_helpers.py b/tests-v3/tools/test_helpers.py index 1403b679f0..a26c8fa8a3 100644 --- a/tests-v3/tools/test_helpers.py +++ b/tests-v3/tools/test_helpers.py @@ -3,8 +3,8 @@ import numpy as np import pytest -import parcels.tools._helpers as helpers -from parcels.tools._helpers import deprecated, deprecated_made_private, timedelta_to_float +import parcels.utils._helpers as helpers +from parcels.utils._helpers import deprecated, deprecated_made_private, timedelta_to_float def test_format_list_items_multiline(): diff --git a/tests/common_kernels.py b/tests/common_kernels.py index 58f674cf82..6606e03a10 100644 --- a/tests/common_kernels.py +++ b/tests/common_kernels.py @@ -2,7 +2,7 @@ import numpy as np -from parcels.tools.statuscodes import StatusCode +from parcels.utils.statuscodes import StatusCode def DoNothing(particles, fieldset): # pragma: no cover diff --git a/tests/test_advection.py b/tests/test_advection.py index e1c602f60b..a84a6e7183 100644 --- a/tests/test_advection.py +++ b/tests/test_advection.py @@ -20,7 +20,7 @@ from parcels.particle import Particle, Variable from parcels.particlefile import ParticleFile from parcels.particleset import ParticleSet -from parcels.tools.statuscodes import StatusCode +from parcels.utils.statuscodes import StatusCode from parcels.xgrid import XGrid from tests.utils import round_and_hash_float_array diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index 7466ecf6ab..e0b58e27ec 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -19,7 +19,7 @@ from parcels.particle import Particle, Variable from parcels.particlefile import ParticleFile from parcels.particleset import ParticleSet -from parcels.tools.statuscodes import StatusCode +from parcels.utils.statuscodes import StatusCode from parcels.uxgrid import UxGrid from parcels.xgrid import XGrid from tests.utils import TEST_DATA diff --git a/tests/test_particlefile.py b/tests/test_particlefile.py index 5ec91e7320..fd3587c0e7 100755 --- a/tests/test_particlefile.py +++ b/tests/test_particlefile.py @@ -14,7 +14,7 @@ from parcels._datasets.structured.generic import datasets from parcels.particle import Particle, create_particle_data, get_default_particle from parcels.particlefile import ParticleFile -from parcels.tools.statuscodes import StatusCode +from parcels.utils.statuscodes import StatusCode from parcels.xgrid import XGrid from tests.common_kernels import DoNothing diff --git a/tests/test_particleset_execute.py b/tests/test_particleset_execute.py index 049d4389d6..22f7645d0e 100644 --- a/tests/test_particleset_execute.py +++ b/tests/test_particleset_execute.py @@ -19,7 +19,7 @@ from parcels._datasets.structured.generic import datasets as datasets_structured from parcels._datasets.unstructured.generic import datasets as datasets_unstructured from parcels.particlefile import ParticleFile -from parcels.tools.statuscodes import FieldInterpolationError, FieldOutOfBoundError, TimeExtrapolationError +from parcels.utils.statuscodes import FieldInterpolationError, FieldOutOfBoundError, TimeExtrapolationError from parcels.uxgrid import UxGrid from parcels.xgrid import XGrid from tests import utils From 3cda55e4e66c46f74570d0b03c736391616e96dc Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 16:14:34 +0200 Subject: [PATCH 16/45] Move statuscodes to parcels root --- parcels/__init__.py | 1 + parcels/_index_search.py | 2 +- parcels/field.py | 2 +- parcels/interaction/interactionkernel.py | 2 +- parcels/kernel.py | 2 +- parcels/kernels/advection.py | 2 +- parcels/kernels/interaction.py | 2 +- parcels/particle.py | 2 +- parcels/particleset.py | 2 +- parcels/{utils => }/statuscodes.py | 0 parcels/utils/__init__.py | 1 - tests/common_kernels.py | 2 +- tests/test_advection.py | 2 +- tests/test_interpolation.py | 2 +- tests/test_particlefile.py | 2 +- tests/test_particleset_execute.py | 2 +- 16 files changed, 14 insertions(+), 14 deletions(-) rename parcels/{utils => }/statuscodes.py (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index a6316febcc..e3a9e2ffb5 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -23,6 +23,7 @@ from parcels.particleset import ParticleSet from parcels._logger import logger from parcels.utils import * +from parcels.statuscodes import StatusCode from parcels._tutorial import download_example_dataset, list_example_datasets _stdlib_warnings.warn( diff --git a/parcels/_index_search.py b/parcels/_index_search.py index 9bbc166233..1b288d8aef 100644 --- a/parcels/_index_search.py +++ b/parcels/_index_search.py @@ -5,7 +5,7 @@ import numpy as np -from parcels.utils.statuscodes import _raise_time_extrapolation_error +from parcels.statuscodes import _raise_time_extrapolation_error if TYPE_CHECKING: from parcels.xgrid import XGrid diff --git a/parcels/field.py b/parcels/field.py index 046b2ab607..0cc117348e 100644 --- a/parcels/field.py +++ b/parcels/field.py @@ -23,7 +23,7 @@ UnitConverter, unitconverters_map, ) -from parcels.utils.statuscodes import ( +from parcels.statuscodes import ( AllParcelsErrorCodes, StatusCode, ) diff --git a/parcels/interaction/interactionkernel.py b/parcels/interaction/interactionkernel.py index 520894e962..59acfb8797 100644 --- a/parcels/interaction/interactionkernel.py +++ b/parcels/interaction/interactionkernel.py @@ -7,7 +7,7 @@ from parcels._compat import MPI from parcels.field import VectorField from parcels.kernel import BaseKernel -from parcels.utils.statuscodes import StatusCode +from parcels.statuscodes import StatusCode __all__ = ["InteractionKernel"] diff --git a/parcels/kernel.py b/parcels/kernel.py index 36b4101a30..29dec50969 100644 --- a/parcels/kernel.py +++ b/parcels/kernel.py @@ -15,7 +15,7 @@ AdvectionRK45, ) from parcels.utils._helpers import _assert_same_function_signature -from parcels.utils.statuscodes import ( +from parcels.statuscodes import ( StatusCode, _raise_field_interpolation_error, _raise_field_out_of_bound_error, diff --git a/parcels/kernels/advection.py b/parcels/kernels/advection.py index fc907b3cb4..493ecae94b 100644 --- a/parcels/kernels/advection.py +++ b/parcels/kernels/advection.py @@ -4,7 +4,7 @@ import numpy as np -from parcels.utils.statuscodes import StatusCode +from parcels.statuscodes import StatusCode __all__ = [ "AdvectionAnalytical", diff --git a/parcels/kernels/interaction.py b/parcels/kernels/interaction.py index 018cd657b7..96f27b4e1b 100644 --- a/parcels/kernels/interaction.py +++ b/parcels/kernels/interaction.py @@ -2,7 +2,7 @@ import numpy as np -from parcels.utils.statuscodes import StatusCode +from parcels.statuscodes import StatusCode __all__ = ["AsymmetricAttraction", "MergeWithNearestNeighbor", "NearestNeighborWithinRange"] diff --git a/parcels/particle.py b/parcels/particle.py index d51fd8d281..f47e9cf862 100644 --- a/parcels/particle.py +++ b/parcels/particle.py @@ -10,7 +10,7 @@ from parcels._compat import _attrgetter_helper from parcels._core.utils.time import TimeInterval from parcels._reprs import _format_list_items_multiline -from parcels.utils.statuscodes import StatusCode +from parcels.statuscodes import StatusCode __all__ = ["KernelParticle", "Particle", "ParticleClass", "Variable"] _TO_WRITE_OPTIONS = [True, False, "once"] diff --git a/parcels/particleset.py b/parcels/particleset.py index 5038253b47..436d95f19e 100644 --- a/parcels/particleset.py +++ b/parcels/particleset.py @@ -16,7 +16,7 @@ from parcels.particle import KernelParticle, Particle, create_particle_data from parcels.utils.converters import convert_to_flat_array from parcels._logger import logger -from parcels.utils.statuscodes import StatusCode +from parcels.statuscodes import StatusCode from parcels._warnings import ParticleSetWarning __all__ = ["ParticleSet"] diff --git a/parcels/utils/statuscodes.py b/parcels/statuscodes.py similarity index 100% rename from parcels/utils/statuscodes.py rename to parcels/statuscodes.py diff --git a/parcels/utils/__init__.py b/parcels/utils/__init__.py index 59d58a56d9..60d42e1c44 100644 --- a/parcels/utils/__init__.py +++ b/parcels/utils/__init__.py @@ -1,3 +1,2 @@ from .converters import * from .interpolation_utils import * -from .statuscodes import * diff --git a/tests/common_kernels.py b/tests/common_kernels.py index 6606e03a10..625dc14534 100644 --- a/tests/common_kernels.py +++ b/tests/common_kernels.py @@ -2,7 +2,7 @@ import numpy as np -from parcels.utils.statuscodes import StatusCode +from parcels.statuscodes import StatusCode def DoNothing(particles, fieldset): # pragma: no cover diff --git a/tests/test_advection.py b/tests/test_advection.py index a84a6e7183..33ec7d01ae 100644 --- a/tests/test_advection.py +++ b/tests/test_advection.py @@ -20,7 +20,7 @@ from parcels.particle import Particle, Variable from parcels.particlefile import ParticleFile from parcels.particleset import ParticleSet -from parcels.utils.statuscodes import StatusCode +from parcels.statuscodes import StatusCode from parcels.xgrid import XGrid from tests.utils import round_and_hash_float_array diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index e0b58e27ec..d61bed92d6 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -19,7 +19,7 @@ from parcels.particle import Particle, Variable from parcels.particlefile import ParticleFile from parcels.particleset import ParticleSet -from parcels.utils.statuscodes import StatusCode +from parcels.statuscodes import StatusCode from parcels.uxgrid import UxGrid from parcels.xgrid import XGrid from tests.utils import TEST_DATA diff --git a/tests/test_particlefile.py b/tests/test_particlefile.py index fd3587c0e7..322194228c 100755 --- a/tests/test_particlefile.py +++ b/tests/test_particlefile.py @@ -14,7 +14,7 @@ from parcels._datasets.structured.generic import datasets from parcels.particle import Particle, create_particle_data, get_default_particle from parcels.particlefile import ParticleFile -from parcels.utils.statuscodes import StatusCode +from parcels.statuscodes import StatusCode from parcels.xgrid import XGrid from tests.common_kernels import DoNothing diff --git a/tests/test_particleset_execute.py b/tests/test_particleset_execute.py index 22f7645d0e..cf11c3501d 100644 --- a/tests/test_particleset_execute.py +++ b/tests/test_particleset_execute.py @@ -19,7 +19,7 @@ from parcels._datasets.structured.generic import datasets as datasets_structured from parcels._datasets.unstructured.generic import datasets as datasets_unstructured from parcels.particlefile import ParticleFile -from parcels.utils.statuscodes import FieldInterpolationError, FieldOutOfBoundError, TimeExtrapolationError +from parcels.statuscodes import FieldInterpolationError, FieldOutOfBoundError, TimeExtrapolationError from parcels.uxgrid import UxGrid from parcels.xgrid import XGrid from tests import utils From 6b04226d939697f86deaf2dc39ab2000061dfa47 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 26 Sep 2025 16:18:30 +0200 Subject: [PATCH 17/45] Refactor deprecation helpers out into decorators --- parcels/utils/_decorators.py | 64 ++++++++++++++++++++++++++++++++++ parcels/utils/_helpers.py | 51 --------------------------- tests-v3/tools/test_helpers.py | 3 +- 3 files changed, 66 insertions(+), 52 deletions(-) create mode 100644 parcels/utils/_decorators.py diff --git a/parcels/utils/_decorators.py b/parcels/utils/_decorators.py new file mode 100644 index 0000000000..1a1c382ebb --- /dev/null +++ b/parcels/utils/_decorators.py @@ -0,0 +1,64 @@ +"""Utilities to help with deprecations.""" + +from __future__ import annotations + +import functools +import inspect +import warnings +from collections.abc import Callable +from datetime import timedelta + +import numpy as np + +PACKAGE = "Parcels" + + +def deprecated(msg: str = "") -> Callable: + """Decorator marking a function as being deprecated + + Parameters + ---------- + msg : str, optional + Custom message to append to the deprecation warning. + + Examples + -------- + ``` + @deprecated("Please use `another_function` instead") + def some_old_function(x, y): + return x + y + + @deprecated() + def some_other_old_function(x, y): + return x + y + ``` + """ + if msg: + msg = " " + msg + + def decorator(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + msg_formatted = ( + f"`{func.__qualname__}` is deprecated and will be removed in a future release of {PACKAGE}.{msg}" + ) + + warnings.warn(msg_formatted, category=DeprecationWarning, stacklevel=3) + return func(*args, **kwargs) + + _patch_docstring(wrapper, f"\n\n.. deprecated:: {msg}") + return wrapper + + return decorator + + +def deprecated_made_private(func: Callable) -> Callable: + return deprecated( + "It has moved to the internal API as it is not expected to be directly used by " + "the end-user. If you feel that you use this code directly in your scripts, please " + "comment on our tracking issue at https://github.com/OceanParcels/Parcels/issues/1695.", + )(func) + + +def _patch_docstring(obj: Callable, extra: str) -> None: + obj.__doc__ = f"{obj.__doc__ or ''}{extra}".strip() diff --git a/parcels/utils/_helpers.py b/parcels/utils/_helpers.py index 7432572767..833aa4ee5b 100644 --- a/parcels/utils/_helpers.py +++ b/parcels/utils/_helpers.py @@ -13,57 +13,6 @@ PACKAGE = "Parcels" -def deprecated(msg: str = "") -> Callable: - """Decorator marking a function as being deprecated - - Parameters - ---------- - msg : str, optional - Custom message to append to the deprecation warning. - - Examples - -------- - ``` - @deprecated("Please use `another_function` instead") - def some_old_function(x, y): - return x + y - - @deprecated() - def some_other_old_function(x, y): - return x + y - ``` - """ - if msg: - msg = " " + msg - - def decorator(func): - @functools.wraps(func) - def wrapper(*args, **kwargs): - msg_formatted = ( - f"`{func.__qualname__}` is deprecated and will be removed in a future release of {PACKAGE}.{msg}" - ) - - warnings.warn(msg_formatted, category=DeprecationWarning, stacklevel=3) - return func(*args, **kwargs) - - patch_docstring(wrapper, f"\n\n.. deprecated:: {msg}") - return wrapper - - return decorator - - -def deprecated_made_private(func: Callable) -> Callable: - return deprecated( - "It has moved to the internal API as it is not expected to be directly used by " - "the end-user. If you feel that you use this code directly in your scripts, please " - "comment on our tracking issue at https://github.com/OceanParcels/Parcels/issues/1695.", - )(func) - - -def patch_docstring(obj: Callable, extra: str) -> None: - obj.__doc__ = f"{obj.__doc__ or ''}{extra}".strip() - - def timedelta_to_float(dt: float | timedelta | np.timedelta64) -> float: """Convert a timedelta to a float in seconds.""" if isinstance(dt, timedelta): diff --git a/tests-v3/tools/test_helpers.py b/tests-v3/tools/test_helpers.py index a26c8fa8a3..455269eedf 100644 --- a/tests-v3/tools/test_helpers.py +++ b/tests-v3/tools/test_helpers.py @@ -4,7 +4,8 @@ import pytest import parcels.utils._helpers as helpers -from parcels.utils._helpers import deprecated, deprecated_made_private, timedelta_to_float +from parcels.utils._helpers import timedelta_to_float +from parcels.utils._decorators import deprecated, deprecated_made_private def test_format_list_items_multiline(): From 2a02407cf1722b21cbb5a06b1447b13660deaa3a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 14:26:00 +0000 Subject: [PATCH 18/45] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- parcels/__init__.py | 18 +++++++++--------- parcels/field.py | 8 ++++---- parcels/fieldset.py | 2 +- parcels/kernel.py | 4 ++-- parcels/kernels/__init__.py | 11 +++++------ parcels/particleset.py | 6 +++--- parcels/utils/_decorators.py | 4 ---- parcels/utils/_helpers.py | 2 -- tests-v3/test_kernel_language.py | 2 +- tests-v3/tools/test_helpers.py | 2 +- tests/test_advection.py | 10 ++++++++-- tests/test_diffusion.py | 2 +- tests/test_field.py | 2 +- tests/test_index_search.py | 2 +- tests/test_interpolation.py | 2 +- tests/test_kernel.py | 2 +- tests/test_particlefile.py | 2 +- tests/test_particleset_execute.py | 4 ++-- tests/test_uxarray_fieldset.py | 2 +- 19 files changed, 43 insertions(+), 44 deletions(-) diff --git a/parcels/__init__.py b/parcels/__init__.py index e3a9e2ffb5..03afbe2615 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -4,6 +4,14 @@ import warnings as _stdlib_warnings +from parcels._logger import logger +from parcels._tutorial import download_example_dataset, list_example_datasets +from parcels._warnings import ( + FieldSetWarning, + FileWarning, + KernelWarning, + ParticleSetWarning, +) from parcels.field import Field, VectorField from parcels.fieldset import FieldSet from parcels.kernel import Kernel @@ -13,18 +21,10 @@ ParticleClass, Variable, ) -from parcels._warnings import ( - FieldSetWarning, - FileWarning, - KernelWarning, - ParticleSetWarning, -) from parcels.particlefile import ParticleFile from parcels.particleset import ParticleSet -from parcels._logger import logger -from parcels.utils import * from parcels.statuscodes import StatusCode -from parcels._tutorial import download_example_dataset, list_example_datasets +from parcels.utils import * _stdlib_warnings.warn( "This is an alpha version of Parcels v4. The API is not stable and may change without deprecation warnings.", diff --git a/parcels/field.py b/parcels/field.py index 0cc117348e..9eed80071e 100644 --- a/parcels/field.py +++ b/parcels/field.py @@ -18,15 +18,15 @@ ZeroInterpolator_Vector, ) from parcels.particle import KernelParticle +from parcels.statuscodes import ( + AllParcelsErrorCodes, + StatusCode, +) from parcels.utils._helpers import _assert_same_function_signature from parcels.utils.converters import ( UnitConverter, unitconverters_map, ) -from parcels.statuscodes import ( - AllParcelsErrorCodes, - StatusCode, -) from parcels.uxgrid import UxGrid from parcels.xgrid import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS, XGrid, _transpose_xfield_data_to_tzyx diff --git a/parcels/fieldset.py b/parcels/fieldset.py index 938f4f9a2f..ada48b0166 100644 --- a/parcels/fieldset.py +++ b/parcels/fieldset.py @@ -11,10 +11,10 @@ from parcels._core.utils.time import get_datetime_type_calendar from parcels._core.utils.time import is_compatible as datetime_is_compatible +from parcels._logger import logger from parcels._typing import Mesh from parcels.field import Field, VectorField from parcels.utils.converters import Geographic, GeographicPolar -from parcels._logger import logger from parcels.xgrid import _DEFAULT_XGCM_KWARGS, XGrid if TYPE_CHECKING: diff --git a/parcels/kernel.py b/parcels/kernel.py index 29dec50969..fbdb81c9cf 100644 --- a/parcels/kernel.py +++ b/parcels/kernel.py @@ -8,13 +8,13 @@ import numpy as np +from parcels._warnings import KernelWarning from parcels.basegrid import GridType from parcels.kernels import ( AdvectionAnalytical, AdvectionRK4, AdvectionRK45, ) -from parcels.utils._helpers import _assert_same_function_signature from parcels.statuscodes import ( StatusCode, _raise_field_interpolation_error, @@ -24,7 +24,7 @@ _raise_grid_searching_error, _raise_time_extrapolation_error, ) -from parcels._warnings import KernelWarning +from parcels.utils._helpers import _assert_same_function_signature if TYPE_CHECKING: from collections.abc import Callable diff --git a/parcels/kernels/__init__.py b/parcels/kernels/__init__.py index 3a7fbc5b2b..02e3e1f2f7 100644 --- a/parcels/kernels/__init__.py +++ b/parcels/kernels/__init__.py @@ -1,23 +1,22 @@ from .advection import ( + AdvectionAnalytical, + AdvectionEE, AdvectionRK4, AdvectionRK4_3D, AdvectionRK4_3D_CROCO, - AdvectionEE, AdvectionRK45, - AdvectionAnalytical, ) from .advectiondiffusion import ( - AdvectionDiffusionM1, AdvectionDiffusionEM, + AdvectionDiffusionM1, DiffusionUniformKh, ) from .interaction import ( - NearestNeighborWithinRange, - MergeWithNearestNeighbor, AsymmetricAttraction, + MergeWithNearestNeighbor, + NearestNeighborWithinRange, ) - __all__ = [ # noqa: RUF022 # advection "AdvectionAnalytical", diff --git a/parcels/particleset.py b/parcels/particleset.py index 436d95f19e..97039d85c2 100644 --- a/parcels/particleset.py +++ b/parcels/particleset.py @@ -10,14 +10,14 @@ from zarr.storage import DirectoryStore from parcels._core.utils.time import TimeInterval, maybe_convert_python_timedelta_to_numpy +from parcels._logger import logger from parcels._reprs import particleset_repr +from parcels._warnings import ParticleSetWarning from parcels.kernel import Kernel from parcels.kernels import AdvectionRK4 from parcels.particle import KernelParticle, Particle, create_particle_data -from parcels.utils.converters import convert_to_flat_array -from parcels._logger import logger from parcels.statuscodes import StatusCode -from parcels._warnings import ParticleSetWarning +from parcels.utils.converters import convert_to_flat_array __all__ = ["ParticleSet"] diff --git a/parcels/utils/_decorators.py b/parcels/utils/_decorators.py index 1a1c382ebb..697696a190 100644 --- a/parcels/utils/_decorators.py +++ b/parcels/utils/_decorators.py @@ -3,12 +3,8 @@ from __future__ import annotations import functools -import inspect import warnings from collections.abc import Callable -from datetime import timedelta - -import numpy as np PACKAGE = "Parcels" diff --git a/parcels/utils/_helpers.py b/parcels/utils/_helpers.py index 833aa4ee5b..0b078110e0 100644 --- a/parcels/utils/_helpers.py +++ b/parcels/utils/_helpers.py @@ -2,9 +2,7 @@ from __future__ import annotations -import functools import inspect -import warnings from collections.abc import Callable from datetime import timedelta diff --git a/tests-v3/test_kernel_language.py b/tests-v3/test_kernel_language.py index d9019e4213..cbca1c2b74 100644 --- a/tests-v3/test_kernel_language.py +++ b/tests-v3/test_kernel_language.py @@ -13,12 +13,12 @@ Variable, ) from parcels.kernels import ( + PolyTEOS10_bsq, PressureFromLatDepth, PtempFromTemp, TempFromPtemp, UNESCODensity, ) -from parcels.kernels import PolyTEOS10_bsq from tests.common_kernels import DoNothing from tests.utils import create_fieldset_unit_mesh diff --git a/tests-v3/tools/test_helpers.py b/tests-v3/tools/test_helpers.py index 455269eedf..cce52ee3f5 100644 --- a/tests-v3/tools/test_helpers.py +++ b/tests-v3/tools/test_helpers.py @@ -4,8 +4,8 @@ import pytest import parcels.utils._helpers as helpers -from parcels.utils._helpers import timedelta_to_float from parcels.utils._decorators import deprecated, deprecated_made_private +from parcels.utils._helpers import timedelta_to_float def test_format_list_items_multiline(): diff --git a/tests/test_advection.py b/tests/test_advection.py index 33ec7d01ae..404c11c7ac 100644 --- a/tests/test_advection.py +++ b/tests/test_advection.py @@ -14,9 +14,15 @@ ) from parcels.field import Field, VectorField from parcels.fieldset import FieldSet -from parcels.kernels import AdvectionEE, AdvectionRK4, AdvectionRK4_3D, AdvectionRK45 -from parcels.kernels import AdvectionDiffusionEM, AdvectionDiffusionM1 from parcels.interpolators import CGrid_Velocity, XLinear +from parcels.kernels import ( + AdvectionDiffusionEM, + AdvectionDiffusionM1, + AdvectionEE, + AdvectionRK4, + AdvectionRK4_3D, + AdvectionRK45, +) from parcels.particle import Particle, Variable from parcels.particlefile import ParticleFile from parcels.particleset import ParticleSet diff --git a/tests/test_diffusion.py b/tests/test_diffusion.py index ec66cb78b1..525cb9a700 100644 --- a/tests/test_diffusion.py +++ b/tests/test_diffusion.py @@ -7,8 +7,8 @@ from parcels._datasets.structured.generated import simple_UV_dataset from parcels.field import Field, VectorField from parcels.fieldset import FieldSet -from parcels.kernels import AdvectionDiffusionEM, AdvectionDiffusionM1, DiffusionUniformKh from parcels.interpolators import XLinear +from parcels.kernels import AdvectionDiffusionEM, AdvectionDiffusionM1, DiffusionUniformKh from parcels.particle import Particle, Variable from parcels.particleset import ParticleSet from parcels.xgrid import XGrid diff --git a/tests/test_field.py b/tests/test_field.py index d9208c8453..e65c818fc8 100644 --- a/tests/test_field.py +++ b/tests/test_field.py @@ -9,9 +9,9 @@ from parcels._datasets.structured.generic import T as T_structured from parcels._datasets.structured.generic import datasets as datasets_structured from parcels._datasets.unstructured.generic import datasets as datasets_unstructured +from parcels.interpolators import UXPiecewiseConstantFace, UXPiecewiseLinearNode from parcels.uxgrid import UxGrid from parcels.xgrid import XGrid -from parcels.interpolators import UXPiecewiseConstantFace, UXPiecewiseLinearNode def test_field_init_param_types(): diff --git a/tests/test_index_search.py b/tests/test_index_search.py index a940216d58..c43616a99b 100644 --- a/tests/test_index_search.py +++ b/tests/test_index_search.py @@ -5,8 +5,8 @@ from parcels._datasets.structured.generic import datasets from parcels._index_search import _search_indices_curvilinear_2d -from parcels.field import Field from parcels._tutorial import download_example_dataset +from parcels.field import Field from parcels.xgrid import XGrid diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index d61bed92d6..90acaed494 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -7,7 +7,6 @@ from parcels._index_search import _search_time_index from parcels.field import Field, VectorField from parcels.fieldset import FieldSet -from parcels.kernels import AdvectionRK4_3D from parcels.interpolators import ( UXPiecewiseLinearNode, XFreeslip, @@ -16,6 +15,7 @@ XPartialslip, ZeroInterpolator, ) +from parcels.kernels import AdvectionRK4_3D from parcels.particle import Particle, Variable from parcels.particlefile import ParticleFile from parcels.particleset import ParticleSet diff --git a/tests/test_kernel.py b/tests/test_kernel.py index 540e33114a..018c998352 100644 --- a/tests/test_kernel.py +++ b/tests/test_kernel.py @@ -1,7 +1,6 @@ import numpy as np import pytest -from parcels.kernels import AdvectionRK4 from parcels import ( Field, FieldSet, @@ -9,6 +8,7 @@ ) from parcels._datasets.structured.generic import datasets as datasets_structured from parcels.kernel import Kernel +from parcels.kernels import AdvectionRK4 from parcels.particle import Particle from parcels.xgrid import XGrid from tests.common_kernels import MoveEast, MoveNorth diff --git a/tests/test_particlefile.py b/tests/test_particlefile.py index 322194228c..137a04297a 100755 --- a/tests/test_particlefile.py +++ b/tests/test_particlefile.py @@ -9,9 +9,9 @@ import parcels from parcels import Field, FieldSet, Particle, ParticleSet, Variable, VectorField -from parcels.kernels import AdvectionRK4 from parcels._core.utils.time import TimeInterval from parcels._datasets.structured.generic import datasets +from parcels.kernels import AdvectionRK4 from parcels.particle import Particle, create_particle_data, get_default_particle from parcels.particlefile import ParticleFile from parcels.statuscodes import StatusCode diff --git a/tests/test_particleset_execute.py b/tests/test_particleset_execute.py index cf11c3501d..e951d67e04 100644 --- a/tests/test_particleset_execute.py +++ b/tests/test_particleset_execute.py @@ -13,11 +13,11 @@ Variable, VectorField, ) -from parcels.kernels import AdvectionEE -from parcels.interpolators import UXPiecewiseConstantFace from parcels._datasets.structured.generated import simple_UV_dataset from parcels._datasets.structured.generic import datasets as datasets_structured from parcels._datasets.unstructured.generic import datasets as datasets_unstructured +from parcels.interpolators import UXPiecewiseConstantFace +from parcels.kernels import AdvectionEE from parcels.particlefile import ParticleFile from parcels.statuscodes import FieldInterpolationError, FieldOutOfBoundError, TimeExtrapolationError from parcels.uxgrid import UxGrid diff --git a/tests/test_uxarray_fieldset.py b/tests/test_uxarray_fieldset.py index e6fb7af693..5ec6f9a226 100644 --- a/tests/test_uxarray_fieldset.py +++ b/tests/test_uxarray_fieldset.py @@ -10,11 +10,11 @@ VectorField, download_example_dataset, ) +from parcels._datasets.unstructured.generic import datasets as datasets_unstructured from parcels.interpolators import ( UXPiecewiseConstantFace, UXPiecewiseLinearNode, ) -from parcels._datasets.unstructured.generic import datasets as datasets_unstructured from parcels.uxgrid import UxGrid From 2e75aa35e060fa2bb9e704be1e18d1c5bd45d013 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 13:01:50 +0200 Subject: [PATCH 19/45] Move converters out of utils --- parcels/__init__.py | 10 ++++++++++ parcels/{utils => }/converters.py | 0 parcels/field.py | 2 +- parcels/fieldset.py | 2 +- parcels/particleset.py | 2 +- parcels/utils/__init__.py | 1 - 6 files changed, 13 insertions(+), 4 deletions(-) rename parcels/{utils => }/converters.py (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index 03afbe2615..e31fd41513 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -26,6 +26,16 @@ from parcels.statuscodes import StatusCode from parcels.utils import * +from parcels.converters import ( + Geographic, + GeographicPolar, + GeographicPolarSquare, + GeographicSquare, + UnitConverter, + convert_to_flat_array, + unitconverters_map, +) + _stdlib_warnings.warn( "This is an alpha version of Parcels v4. The API is not stable and may change without deprecation warnings.", UserWarning, diff --git a/parcels/utils/converters.py b/parcels/converters.py similarity index 100% rename from parcels/utils/converters.py rename to parcels/converters.py diff --git a/parcels/field.py b/parcels/field.py index 9eed80071e..f8993597bd 100644 --- a/parcels/field.py +++ b/parcels/field.py @@ -23,7 +23,7 @@ StatusCode, ) from parcels.utils._helpers import _assert_same_function_signature -from parcels.utils.converters import ( +from parcels.converters import ( UnitConverter, unitconverters_map, ) diff --git a/parcels/fieldset.py b/parcels/fieldset.py index ada48b0166..4ddb710708 100644 --- a/parcels/fieldset.py +++ b/parcels/fieldset.py @@ -14,7 +14,7 @@ from parcels._logger import logger from parcels._typing import Mesh from parcels.field import Field, VectorField -from parcels.utils.converters import Geographic, GeographicPolar +from parcels.converters import Geographic, GeographicPolar from parcels.xgrid import _DEFAULT_XGCM_KWARGS, XGrid if TYPE_CHECKING: diff --git a/parcels/particleset.py b/parcels/particleset.py index 97039d85c2..28fa9f824a 100644 --- a/parcels/particleset.py +++ b/parcels/particleset.py @@ -17,7 +17,7 @@ from parcels.kernels import AdvectionRK4 from parcels.particle import KernelParticle, Particle, create_particle_data from parcels.statuscodes import StatusCode -from parcels.utils.converters import convert_to_flat_array +from parcels.converters import convert_to_flat_array __all__ = ["ParticleSet"] diff --git a/parcels/utils/__init__.py b/parcels/utils/__init__.py index 60d42e1c44..592d28b9bc 100644 --- a/parcels/utils/__init__.py +++ b/parcels/utils/__init__.py @@ -1,2 +1 @@ -from .converters import * from .interpolation_utils import * From 1f1c39108421244321a33f393a61eb8ccca2bfae Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 13:03:11 +0200 Subject: [PATCH 20/45] Make _convert_to_flat_array and _unitconverters_map private --- parcels/__init__.py | 2 -- parcels/converters.py | 8 ++++---- parcels/field.py | 6 +++--- parcels/particleset.py | 12 ++++++------ 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/parcels/__init__.py b/parcels/__init__.py index e31fd41513..f68a386234 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -32,8 +32,6 @@ GeographicPolarSquare, GeographicSquare, UnitConverter, - convert_to_flat_array, - unitconverters_map, ) _stdlib_warnings.warn( diff --git a/parcels/converters.py b/parcels/converters.py index 68c3810b6c..35fddc18bc 100644 --- a/parcels/converters.py +++ b/parcels/converters.py @@ -11,12 +11,12 @@ "GeographicPolarSquare", "GeographicSquare", "UnitConverter", - "convert_to_flat_array", - "unitconverters_map", + "_convert_to_flat_array", + "_unitconverters_map", ] -def convert_to_flat_array(var: npt.ArrayLike) -> npt.NDArray: +def _convert_to_flat_array(var: npt.ArrayLike) -> npt.NDArray: """Convert lists and single integers/floats to one-dimensional numpy arrays Parameters @@ -96,7 +96,7 @@ def to_source(self, value, z, y, x): return value * pow(1000.0 * 1.852 * 60.0 * np.cos(y * pi / 180), 2) -unitconverters_map = { +_unitconverters_map = { "U": GeographicPolar(), "V": Geographic(), "Kh_zonal": GeographicPolarSquare(), diff --git a/parcels/field.py b/parcels/field.py index f8993597bd..5b1f467ebe 100644 --- a/parcels/field.py +++ b/parcels/field.py @@ -25,7 +25,7 @@ from parcels.utils._helpers import _assert_same_function_signature from parcels.converters import ( UnitConverter, - unitconverters_map, + _unitconverters_map, ) from parcels.uxgrid import UxGrid from parcels.xgrid import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS, XGrid, _transpose_xfield_data_to_tzyx @@ -143,10 +143,10 @@ def __init__( self.igrid = -1 # Default the grid index to -1 - if self.grid._mesh == "flat" or (self.name not in unitconverters_map.keys()): + if self.grid._mesh == "flat" or (self.name not in _unitconverters_map.keys()): self.units = UnitConverter() elif self.grid._mesh == "spherical": - self.units = unitconverters_map[self.name] + self.units = _unitconverters_map[self.name] if self.data.shape[0] > 1: if "time" not in self.data.coords: diff --git a/parcels/particleset.py b/parcels/particleset.py index 28fa9f824a..0b8347965d 100644 --- a/parcels/particleset.py +++ b/parcels/particleset.py @@ -17,7 +17,7 @@ from parcels.kernels import AdvectionRK4 from parcels.particle import KernelParticle, Particle, create_particle_data from parcels.statuscodes import StatusCode -from parcels.converters import convert_to_flat_array +from parcels.converters import _convert_to_flat_array __all__ = ["ParticleSet"] @@ -78,9 +78,9 @@ def __init__( self._interaction_kernel = None self.fieldset = fieldset - lon = np.empty(shape=0) if lon is None else convert_to_flat_array(lon) - lat = np.empty(shape=0) if lat is None else convert_to_flat_array(lat) - time = np.empty(shape=0) if time is None else convert_to_flat_array(time) + lon = np.empty(shape=0) if lon is None else _convert_to_flat_array(lon) + lat = np.empty(shape=0) if lat is None else _convert_to_flat_array(lat) + time = np.empty(shape=0) if time is None else _convert_to_flat_array(time) if trajectory_ids is None: trajectory_ids = np.arange(lon.size) @@ -92,7 +92,7 @@ def __init__( mindepth = min(mindepth, field.grid.depth[0]) depth = np.ones(lon.size) * mindepth else: - depth = convert_to_flat_array(depth) + depth = _convert_to_flat_array(depth) assert lon.size == lat.size and lon.size == depth.size, "lon, lat, depth don't all have the same lenghts" if time is None or len(time) == 0: @@ -114,7 +114,7 @@ def __init__( for kwvar in kwargs: if kwvar not in ["partition_function"]: - kwargs[kwvar] = convert_to_flat_array(kwargs[kwvar]) + kwargs[kwvar] = _convert_to_flat_array(kwargs[kwvar]) assert lon.size == kwargs[kwvar].size, ( f"{kwvar} and positions (lon, lat, depth) don't have the same lengths." ) From 4158fddddf60280f2a043c75f3df494e69bb67d9 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 13:04:48 +0200 Subject: [PATCH 21/45] Delete empty utils submodules --- parcels/_core/utils/common.py | 0 parcels/_core/utils/structured.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 parcels/_core/utils/common.py delete mode 100644 parcels/_core/utils/structured.py diff --git a/parcels/_core/utils/common.py b/parcels/_core/utils/common.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/parcels/_core/utils/structured.py b/parcels/_core/utils/structured.py deleted file mode 100644 index e69de29bb2..0000000000 From 02d1389857090dee19ad7739306d30fd638581dc Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 13:11:04 +0200 Subject: [PATCH 22/45] Move kernels to _core --- parcels/__init__.py | 1 + parcels/{ => _core}/kernels/EOSseawaterproperties.py | 0 parcels/{ => _core}/kernels/TEOSseawaterdensity.py | 0 parcels/{ => _core}/kernels/__init__.py | 0 parcels/{ => _core}/kernels/advection.py | 0 parcels/{ => _core}/kernels/advectiondiffusion.py | 0 parcels/{ => _core}/kernels/interaction.py | 0 parcels/kernel.py | 2 +- parcels/particleset.py | 2 +- 9 files changed, 3 insertions(+), 2 deletions(-) rename parcels/{ => _core}/kernels/EOSseawaterproperties.py (100%) rename parcels/{ => _core}/kernels/TEOSseawaterdensity.py (100%) rename parcels/{ => _core}/kernels/__init__.py (100%) rename parcels/{ => _core}/kernels/advection.py (100%) rename parcels/{ => _core}/kernels/advectiondiffusion.py (100%) rename parcels/{ => _core}/kernels/interaction.py (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index f68a386234..0fd0232a0f 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -33,6 +33,7 @@ GeographicSquare, UnitConverter, ) +import parcels._core.kernels as kernels _stdlib_warnings.warn( "This is an alpha version of Parcels v4. The API is not stable and may change without deprecation warnings.", diff --git a/parcels/kernels/EOSseawaterproperties.py b/parcels/_core/kernels/EOSseawaterproperties.py similarity index 100% rename from parcels/kernels/EOSseawaterproperties.py rename to parcels/_core/kernels/EOSseawaterproperties.py diff --git a/parcels/kernels/TEOSseawaterdensity.py b/parcels/_core/kernels/TEOSseawaterdensity.py similarity index 100% rename from parcels/kernels/TEOSseawaterdensity.py rename to parcels/_core/kernels/TEOSseawaterdensity.py diff --git a/parcels/kernels/__init__.py b/parcels/_core/kernels/__init__.py similarity index 100% rename from parcels/kernels/__init__.py rename to parcels/_core/kernels/__init__.py diff --git a/parcels/kernels/advection.py b/parcels/_core/kernels/advection.py similarity index 100% rename from parcels/kernels/advection.py rename to parcels/_core/kernels/advection.py diff --git a/parcels/kernels/advectiondiffusion.py b/parcels/_core/kernels/advectiondiffusion.py similarity index 100% rename from parcels/kernels/advectiondiffusion.py rename to parcels/_core/kernels/advectiondiffusion.py diff --git a/parcels/kernels/interaction.py b/parcels/_core/kernels/interaction.py similarity index 100% rename from parcels/kernels/interaction.py rename to parcels/_core/kernels/interaction.py diff --git a/parcels/kernel.py b/parcels/kernel.py index fbdb81c9cf..38e895064c 100644 --- a/parcels/kernel.py +++ b/parcels/kernel.py @@ -10,7 +10,7 @@ from parcels._warnings import KernelWarning from parcels.basegrid import GridType -from parcels.kernels import ( +from parcels._core.kernels import ( AdvectionAnalytical, AdvectionRK4, AdvectionRK45, diff --git a/parcels/particleset.py b/parcels/particleset.py index 0b8347965d..ebd2f5d003 100644 --- a/parcels/particleset.py +++ b/parcels/particleset.py @@ -14,7 +14,7 @@ from parcels._reprs import particleset_repr from parcels._warnings import ParticleSetWarning from parcels.kernel import Kernel -from parcels.kernels import AdvectionRK4 +from parcels._core.kernels import AdvectionRK4 from parcels.particle import KernelParticle, Particle, create_particle_data from parcels.statuscodes import StatusCode from parcels.converters import _convert_to_flat_array From f0dbaba8173879414bd801dfc918cef6725534ea Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 13:18:51 +0200 Subject: [PATCH 23/45] Move basegrid, xgrid, and uxgrid into _core subpackage --- parcels/__init__.py | 3 +++ parcels/{ => _core}/basegrid.py | 1 + parcels/{ => _core}/uxgrid.py | 4 ++-- parcels/{ => _core}/xgrid.py | 2 +- parcels/_spatialhash.py | 16 +++++++++------- parcels/field.py | 4 ++-- parcels/fieldset.py | 2 +- parcels/interpolators.py | 4 ++-- parcels/kernel.py | 2 +- tests/test_advection.py | 2 +- tests/test_basegrid.py | 2 +- tests/test_datasets.py | 2 +- tests/test_diffusion.py | 2 +- tests/test_field.py | 4 ++-- tests/test_fieldset.py | 2 +- tests/test_index_search.py | 2 +- tests/test_interpolation.py | 4 ++-- tests/test_kernel.py | 2 +- tests/test_particlefile.py | 2 +- tests/test_particleset.py | 2 +- tests/test_particleset_execute.py | 4 ++-- tests/test_spatialhash.py | 2 +- tests/test_uxarray_fieldset.py | 2 +- tests/test_uxgrid.py | 2 +- tests/test_xgrid.py | 2 +- tests/utils.py | 2 +- 26 files changed, 42 insertions(+), 36 deletions(-) rename parcels/{ => _core}/basegrid.py (99%) rename parcels/{ => _core}/uxgrid.py (97%) rename parcels/{ => _core}/xgrid.py (99%) diff --git a/parcels/__init__.py b/parcels/__init__.py index 0fd0232a0f..be67b5cfd3 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -34,6 +34,9 @@ UnitConverter, ) import parcels._core.kernels as kernels +from parcels._core.xgrid import XGrid +from parcels._core.uxgrid import UxGrid +from parcels._core.basegrid import BaseGrid _stdlib_warnings.warn( "This is an alpha version of Parcels v4. The API is not stable and may change without deprecation warnings.", diff --git a/parcels/basegrid.py b/parcels/_core/basegrid.py similarity index 99% rename from parcels/basegrid.py rename to parcels/_core/basegrid.py index 9b353090ce..a43f578eff 100644 --- a/parcels/basegrid.py +++ b/parcels/_core/basegrid.py @@ -1,3 +1,4 @@ + from __future__ import annotations from abc import ABC, abstractmethod diff --git a/parcels/uxgrid.py b/parcels/_core/uxgrid.py similarity index 97% rename from parcels/uxgrid.py rename to parcels/_core/uxgrid.py index 3aa91e1777..aa552885c2 100644 --- a/parcels/uxgrid.py +++ b/parcels/_core/uxgrid.py @@ -7,9 +7,9 @@ from parcels._index_search import GRID_SEARCH_ERROR, uxgrid_point_in_cell from parcels._typing import assert_valid_mesh -from parcels.xgrid import _search_1d_array +from parcels._core.xgrid import _search_1d_array -from .basegrid import BaseGrid +from parcels._core.basegrid import BaseGrid _UXGRID_AXES = Literal["Z", "FACE"] diff --git a/parcels/xgrid.py b/parcels/_core/xgrid.py similarity index 99% rename from parcels/xgrid.py rename to parcels/_core/xgrid.py index 83bbb46f74..22b763e828 100644 --- a/parcels/xgrid.py +++ b/parcels/_core/xgrid.py @@ -9,7 +9,7 @@ from parcels._index_search import _search_indices_curvilinear_2d from parcels._typing import assert_valid_mesh -from parcels.basegrid import BaseGrid +from parcels._core.basegrid import BaseGrid _XGRID_AXES = Literal["X", "Y", "Z"] _XGRID_AXES_ORDERING: Sequence[_XGRID_AXES] = "ZYX" diff --git a/parcels/_spatialhash.py b/parcels/_spatialhash.py index 5e4aaa4aa1..4f91d811d3 100644 --- a/parcels/_spatialhash.py +++ b/parcels/_spatialhash.py @@ -2,17 +2,19 @@ import parcels from parcels._index_search import GRID_SEARCH_ERROR, _latlon_rad_to_xyz, curvilinear_point_in_cell, uxgrid_point_in_cell +from parcels._core.uxgrid import UxGrid +from parcels._core.xgrid import XGrid class SpatialHash: """Custom data structure that is used for performing grid searches using Spatial Hashing. This class constructs an overlying - uniformly spaced rectilinear grid, called the "hash grid" on top parcels.xgrid.XGrid. It is particularly useful for grid searching + uniformly spaced rectilinear grid, called the "hash grid" on top parcels.XGrid. It is particularly useful for grid searching on curvilinear grids. Faces in the Xgrid are related to the cells in the hash grid by determining the hash cells the bounding box of the unstructured face cells overlap with. Parameters ---------- - grid : parcels.xgrid.XGrid + grid : parcels.XGrid Source grid used to construct the hash grid and hash table Note @@ -25,17 +27,17 @@ def __init__( grid, bitwidth=1023, ): - if isinstance(grid, parcels.xgrid.XGrid): + if isinstance(grid, XGrid): self._point_in_cell = curvilinear_point_in_cell - elif isinstance(grid, parcels.uxgrid.UxGrid): + elif isinstance(grid, UxGrid): self._point_in_cell = uxgrid_point_in_cell else: - raise ValueError("Expected `grid` to be a parcels.xgrid.XGrid or parcels.uxgrid.UxGrid") + raise ValueError("Expected `grid` to be a parcels.XGrid or parcels.UxGrid") self._source_grid = grid self._bitwidth = bitwidth # Max integer to use per coordinate in quantization (10 bits = 0..1023) - if isinstance(grid, parcels.xgrid.XGrid): + if isinstance(grid, XGrid): if self._source_grid._mesh == "spherical": # Boundaries of the hash grid are the unit cube self._xmin = -1.0 @@ -120,7 +122,7 @@ def __init__( self._zlow = np.zeros_like(self._xlow) self._zhigh = np.zeros_like(self._xlow) - elif isinstance(grid, parcels.uxgrid.UxGrid): + elif isinstance(grid, UxGrid): if self._source_grid._mesh == "spherical": # Boundaries of the hash grid are the unit cube self._xmin = -1.0 diff --git a/parcels/field.py b/parcels/field.py index 5b1f467ebe..2e43515fbe 100644 --- a/parcels/field.py +++ b/parcels/field.py @@ -27,8 +27,8 @@ UnitConverter, _unitconverters_map, ) -from parcels.uxgrid import UxGrid -from parcels.xgrid import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS, XGrid, _transpose_xfield_data_to_tzyx +from parcels._core.uxgrid import UxGrid +from parcels._core.xgrid import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS, XGrid, _transpose_xfield_data_to_tzyx from ._index_search import GRID_SEARCH_ERROR, _search_time_index diff --git a/parcels/fieldset.py b/parcels/fieldset.py index 4ddb710708..43b1f353b6 100644 --- a/parcels/fieldset.py +++ b/parcels/fieldset.py @@ -19,7 +19,7 @@ if TYPE_CHECKING: from parcels._typing import TimeLike - from parcels.basegrid import BaseGrid + from parcels._core.basegrid import BaseGrid __all__ = ["FieldSet"] diff --git a/parcels/interpolators.py b/parcels/interpolators.py index 2759964397..f315c031aa 100644 --- a/parcels/interpolators.py +++ b/parcels/interpolators.py @@ -12,8 +12,8 @@ if TYPE_CHECKING: from parcels.field import Field, VectorField - from parcels.uxgrid import _UXGRID_AXES - from parcels.xgrid import _XGRID_AXES + from parcels._core.uxgrid import _UXGRID_AXES + from parcels._core.xgrid import _XGRID_AXES __all__ = [ "CGrid_Tracer", diff --git a/parcels/kernel.py b/parcels/kernel.py index 38e895064c..df249dd76b 100644 --- a/parcels/kernel.py +++ b/parcels/kernel.py @@ -9,7 +9,7 @@ import numpy as np from parcels._warnings import KernelWarning -from parcels.basegrid import GridType +from parcels._core.basegrid import GridType from parcels._core.kernels import ( AdvectionAnalytical, AdvectionRK4, diff --git a/tests/test_advection.py b/tests/test_advection.py index 404c11c7ac..c2d74d1405 100644 --- a/tests/test_advection.py +++ b/tests/test_advection.py @@ -27,7 +27,7 @@ from parcels.particlefile import ParticleFile from parcels.particleset import ParticleSet from parcels.statuscodes import StatusCode -from parcels.xgrid import XGrid +from parcels import XGrid from tests.utils import round_and_hash_float_array kernel = { diff --git a/tests/test_basegrid.py b/tests/test_basegrid.py index 5f18b162af..de11f00e23 100644 --- a/tests/test_basegrid.py +++ b/tests/test_basegrid.py @@ -5,7 +5,7 @@ import numpy as np import pytest -from parcels.basegrid import BaseGrid +from parcels._core.basegrid import BaseGrid class MockGrid(BaseGrid): diff --git a/tests/test_datasets.py b/tests/test_datasets.py index e6a550d960..4825e0b98a 100644 --- a/tests/test_datasets.py +++ b/tests/test_datasets.py @@ -1,7 +1,7 @@ import xgcm from parcels._datasets.structured.generic import datasets -from parcels.xgrid import _DEFAULT_XGCM_KWARGS +from parcels._core.xgrid import _DEFAULT_XGCM_KWARGS def test_left_indexed_dataset(): diff --git a/tests/test_diffusion.py b/tests/test_diffusion.py index 525cb9a700..33502d472f 100644 --- a/tests/test_diffusion.py +++ b/tests/test_diffusion.py @@ -11,7 +11,7 @@ from parcels.kernels import AdvectionDiffusionEM, AdvectionDiffusionM1, DiffusionUniformKh from parcels.particle import Particle, Variable from parcels.particleset import ParticleSet -from parcels.xgrid import XGrid +from parcels import XGrid from tests.utils import create_fieldset_zeros_conversion diff --git a/tests/test_field.py b/tests/test_field.py index e65c818fc8..18376830e3 100644 --- a/tests/test_field.py +++ b/tests/test_field.py @@ -10,8 +10,8 @@ from parcels._datasets.structured.generic import datasets as datasets_structured from parcels._datasets.unstructured.generic import datasets as datasets_unstructured from parcels.interpolators import UXPiecewiseConstantFace, UXPiecewiseLinearNode -from parcels.uxgrid import UxGrid -from parcels.xgrid import XGrid +from parcels import UxGrid +from parcels import XGrid def test_field_init_param_types(): diff --git a/tests/test_fieldset.py b/tests/test_fieldset.py index 0787886be1..b976342af7 100644 --- a/tests/test_fieldset.py +++ b/tests/test_fieldset.py @@ -11,7 +11,7 @@ from parcels._datasets.structured.generic import datasets as datasets_structured from parcels.field import Field, VectorField from parcels.fieldset import CalendarError, FieldSet, _datetime_to_msg -from parcels.xgrid import XGrid +from parcels import XGrid from tests import utils ds = datasets_structured["ds_2d_left"] diff --git a/tests/test_index_search.py b/tests/test_index_search.py index c43616a99b..2c46e5c614 100644 --- a/tests/test_index_search.py +++ b/tests/test_index_search.py @@ -7,7 +7,7 @@ from parcels._index_search import _search_indices_curvilinear_2d from parcels._tutorial import download_example_dataset from parcels.field import Field -from parcels.xgrid import XGrid +from parcels import XGrid @pytest.fixture diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index 90acaed494..08413995ab 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -20,8 +20,8 @@ from parcels.particlefile import ParticleFile from parcels.particleset import ParticleSet from parcels.statuscodes import StatusCode -from parcels.uxgrid import UxGrid -from parcels.xgrid import XGrid +from parcels import UxGrid +from parcels import XGrid from tests.utils import TEST_DATA diff --git a/tests/test_kernel.py b/tests/test_kernel.py index 018c998352..cf1624272b 100644 --- a/tests/test_kernel.py +++ b/tests/test_kernel.py @@ -10,7 +10,7 @@ from parcels.kernel import Kernel from parcels.kernels import AdvectionRK4 from parcels.particle import Particle -from parcels.xgrid import XGrid +from parcels import XGrid from tests.common_kernels import MoveEast, MoveNorth diff --git a/tests/test_particlefile.py b/tests/test_particlefile.py index 137a04297a..d01be764a6 100755 --- a/tests/test_particlefile.py +++ b/tests/test_particlefile.py @@ -15,7 +15,7 @@ from parcels.particle import Particle, create_particle_data, get_default_particle from parcels.particlefile import ParticleFile from parcels.statuscodes import StatusCode -from parcels.xgrid import XGrid +from parcels import XGrid from tests.common_kernels import DoNothing diff --git a/tests/test_particleset.py b/tests/test_particleset.py index b99b708b25..2a1dde102a 100644 --- a/tests/test_particleset.py +++ b/tests/test_particleset.py @@ -15,7 +15,7 @@ Variable, ) from parcels._datasets.structured.generic import datasets as datasets_structured -from parcels.xgrid import XGrid +from parcels import XGrid from tests.common_kernels import DoNothing from tests.utils import round_and_hash_float_array diff --git a/tests/test_particleset_execute.py b/tests/test_particleset_execute.py index e951d67e04..06334fc291 100644 --- a/tests/test_particleset_execute.py +++ b/tests/test_particleset_execute.py @@ -20,8 +20,8 @@ from parcels.kernels import AdvectionEE from parcels.particlefile import ParticleFile from parcels.statuscodes import FieldInterpolationError, FieldOutOfBoundError, TimeExtrapolationError -from parcels.uxgrid import UxGrid -from parcels.xgrid import XGrid +from parcels import UxGrid +from parcels import XGrid from tests import utils from tests.common_kernels import DoNothing diff --git a/tests/test_spatialhash.py b/tests/test_spatialhash.py index bdec911735..27ec55bfb5 100644 --- a/tests/test_spatialhash.py +++ b/tests/test_spatialhash.py @@ -1,7 +1,7 @@ import numpy as np from parcels._datasets.structured.generic import datasets -from parcels.xgrid import XGrid +from parcels import XGrid def test_spatialhash_init(): diff --git a/tests/test_uxarray_fieldset.py b/tests/test_uxarray_fieldset.py index 5ec6f9a226..3732dbb104 100644 --- a/tests/test_uxarray_fieldset.py +++ b/tests/test_uxarray_fieldset.py @@ -15,7 +15,7 @@ UXPiecewiseConstantFace, UXPiecewiseLinearNode, ) -from parcels.uxgrid import UxGrid +from parcels import UxGrid @pytest.fixture diff --git a/tests/test_uxgrid.py b/tests/test_uxgrid.py index 9c675b278b..758d540089 100644 --- a/tests/test_uxgrid.py +++ b/tests/test_uxgrid.py @@ -1,7 +1,7 @@ import pytest from parcels._datasets.unstructured.generic import datasets as uxdatasets -from parcels.uxgrid import UxGrid +from parcels import UxGrid @pytest.mark.parametrize("uxds", [pytest.param(uxds, id=key) for key, uxds in uxdatasets.items()]) diff --git a/tests/test_xgrid.py b/tests/test_xgrid.py index eb9e8524e8..5ceb07b992 100644 --- a/tests/test_xgrid.py +++ b/tests/test_xgrid.py @@ -7,7 +7,7 @@ from numpy.testing import assert_allclose from parcels._datasets.structured.generic import X, Y, Z, datasets -from parcels.xgrid import ( +from parcels._core.xgrid import ( LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS, XGrid, diff --git a/tests/utils.py b/tests/utils.py index 04ca73a356..6bae31a633 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -13,7 +13,7 @@ from parcels.field import Field, VectorField from parcels.fieldset import FieldSet from parcels.interpolators import XLinear -from parcels.xgrid import _FIELD_DATA_ORDERING, XGrid, get_axis_from_dim_name +from parcels._core.xgrid import _FIELD_DATA_ORDERING, XGrid, get_axis_from_dim_name PROJECT_ROOT = Path(__file__).resolve().parents[1] TEST_ROOT = PROJECT_ROOT / "tests" From 4a588981ea9617c4327243e785ed2437d30d8866 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 13:33:09 +0200 Subject: [PATCH 24/45] Create array utils module and constants module --- parcels/_core/constants.py | 3 +++ parcels/_core/utils/array.py | 47 ++++++++++++++++++++++++++++++++++ parcels/_core/uxgrid.py | 2 +- parcels/_core/xgrid.py | 49 +----------------------------------- parcels/field.py | 2 +- tests/test_xgrid.py | 5 ++-- 6 files changed, 55 insertions(+), 53 deletions(-) create mode 100644 parcels/_core/constants.py create mode 100644 parcels/_core/utils/array.py diff --git a/parcels/_core/constants.py b/parcels/_core/constants.py new file mode 100644 index 0000000000..411373170c --- /dev/null +++ b/parcels/_core/constants.py @@ -0,0 +1,3 @@ +# Used in the searching of 1D arrays for time and space +LEFT_OUT_OF_BOUNDS = -2 +RIGHT_OUT_OF_BOUNDS = -1 diff --git a/parcels/_core/utils/array.py b/parcels/_core/utils/array.py new file mode 100644 index 0000000000..4c0eaaa833 --- /dev/null +++ b/parcels/_core/utils/array.py @@ -0,0 +1,47 @@ +import numpy as np +from parcels._core.constants import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS + + +def _search_1d_array( + arr: np.array, + x: float, +) -> tuple[int, int]: + """ + Searches for particle locations in a 1D array and returns barycentric coordinate along dimension. + + Assumptions: + - array is strictly monotonically increasing. + + Parameters + ---------- + arr : np.array + 1D array to search in. + x : float + Position in the 1D array to search for. + + Returns + ------- + array of int + Index of the element just before the position x in the array. Note that this index is -2 if the index is left out of bounds and -1 if the index is right out of bounds. + array of float + Barycentric coordinate. + """ + # TODO v4: We probably rework this to deal with 0D arrays before this point (as we already know field dimensionality) + if len(arr) < 2: + return np.zeros(shape=x.shape, dtype=np.int32), np.zeros_like(x) + index = np.searchsorted(arr, x, side="right") - 1 + # Use broadcasting to avoid repeated array access + arr_index = arr[index] + arr_next = arr[np.clip(index + 1, 1, len(arr) - 1)] # Ensure we don't go out of bounds + bcoord = (x - arr_index) / (arr_next - arr_index) + + # TODO check how we can avoid searchsorted when grid spacing is uniform + # dx = arr[1] - arr[0] + # index = ((x - arr[0]) / dx).astype(int) + # index = np.clip(index, 0, len(arr) - 2) + # bcoord = (x - arr[index]) / dx + + index = np.where(x < arr[0], LEFT_OUT_OF_BOUNDS, index) + index = np.where(x >= arr[-1], RIGHT_OUT_OF_BOUNDS, index) + + return np.atleast_1d(index), np.atleast_1d(bcoord) diff --git a/parcels/_core/uxgrid.py b/parcels/_core/uxgrid.py index aa552885c2..ab7a78173c 100644 --- a/parcels/_core/uxgrid.py +++ b/parcels/_core/uxgrid.py @@ -7,7 +7,7 @@ from parcels._index_search import GRID_SEARCH_ERROR, uxgrid_point_in_cell from parcels._typing import assert_valid_mesh -from parcels._core.xgrid import _search_1d_array +from parcels._core.utils.array import _search_1d_array from parcels._core.basegrid import BaseGrid diff --git a/parcels/_core/xgrid.py b/parcels/_core/xgrid.py index 22b763e828..7dad60ec57 100644 --- a/parcels/_core/xgrid.py +++ b/parcels/_core/xgrid.py @@ -10,6 +10,7 @@ from parcels._index_search import _search_indices_curvilinear_2d from parcels._typing import assert_valid_mesh from parcels._core.basegrid import BaseGrid +from parcels._core.utils.array import _search_1d_array _XGRID_AXES = Literal["X", "Y", "Z"] _XGRID_AXES_ORDERING: Sequence[_XGRID_AXES] = "ZYX" @@ -22,9 +23,6 @@ _DEFAULT_XGCM_KWARGS = {"periodic": False} -LEFT_OUT_OF_BOUNDS = -2 -RIGHT_OUT_OF_BOUNDS = -1 - def get_cell_count_along_dim(ds: xr.Dataset, axis: xgcm.Axis) -> int: first_coord = list(axis.coords.items())[0] @@ -477,51 +475,6 @@ def assert_valid_lat_lon(da_lat, da_lon, axes: _XGCM_AXES): ) -def _search_1d_array( - arr: np.array, - x: float, -) -> tuple[int, int]: - """ - Searches for particle locations in a 1D array and returns barycentric coordinate along dimension. - - Assumptions: - - array is strictly monotonically increasing. - - Parameters - ---------- - arr : np.array - 1D array to search in. - x : float - Position in the 1D array to search for. - - Returns - ------- - array of int - Index of the element just before the position x in the array. Note that this index is -2 if the index is left out of bounds and -1 if the index is right out of bounds. - array of float - Barycentric coordinate. - """ - # TODO v4: We probably rework this to deal with 0D arrays before this point (as we already know field dimensionality) - if len(arr) < 2: - return np.zeros(shape=x.shape, dtype=np.int32), np.zeros_like(x) - index = np.searchsorted(arr, x, side="right") - 1 - # Use broadcasting to avoid repeated array access - arr_index = arr[index] - arr_next = arr[np.clip(index + 1, 1, len(arr) - 1)] # Ensure we don't go out of bounds - bcoord = (x - arr_index) / (arr_next - arr_index) - - # TODO check how we can avoid searchsorted when grid spacing is uniform - # dx = arr[1] - arr[0] - # index = ((x - arr[0]) / dx).astype(int) - # index = np.clip(index, 0, len(arr) - 2) - # bcoord = (x - arr[index]) / dx - - index = np.where(x < arr[0], LEFT_OUT_OF_BOUNDS, index) - index = np.where(x >= arr[-1], RIGHT_OUT_OF_BOUNDS, index) - - return np.atleast_1d(index), np.atleast_1d(bcoord) - - def _convert_center_pos_to_fpoint( *, index: int, bcoord: float, xgcm_position: _XGCM_AXIS_POSITION, f_points_xgcm_position: _XGCM_AXIS_POSITION ) -> tuple[int, float]: diff --git a/parcels/field.py b/parcels/field.py index 2e43515fbe..01cd5d5278 100644 --- a/parcels/field.py +++ b/parcels/field.py @@ -28,7 +28,7 @@ _unitconverters_map, ) from parcels._core.uxgrid import UxGrid -from parcels._core.xgrid import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS, XGrid, _transpose_xfield_data_to_tzyx +from parcels._core.xgrid import XGrid, _transpose_xfield_data_to_tzyx from ._index_search import GRID_SEARCH_ERROR, _search_time_index diff --git a/tests/test_xgrid.py b/tests/test_xgrid.py index 5ceb07b992..1e3130fbba 100644 --- a/tests/test_xgrid.py +++ b/tests/test_xgrid.py @@ -8,12 +8,11 @@ from parcels._datasets.structured.generic import X, Y, Z, datasets from parcels._core.xgrid import ( - LEFT_OUT_OF_BOUNDS, - RIGHT_OUT_OF_BOUNDS, XGrid, - _search_1d_array, _transpose_xfield_data_to_tzyx, ) +from parcels._core.constants import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS +from parcels._core.utils.array import _search_1d_array from tests import utils GridTestCase = namedtuple("GridTestCase", ["ds", "attr", "expected"]) From 3ca20b217fec61ceaab751a8fc0f9930b1dc3030 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 13:38:47 +0200 Subject: [PATCH 25/45] Avoid circular imports from isinstance checks --- parcels/_python.py | 28 ++++++++++++++++++++++++++++ parcels/_spatialhash.py | 11 +++++------ 2 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 parcels/_python.py diff --git a/parcels/_python.py b/parcels/_python.py new file mode 100644 index 0000000000..91f5b46458 --- /dev/null +++ b/parcels/_python.py @@ -0,0 +1,28 @@ +# Generic Python helpers + + +def isinstance_noimport(obj, class_or_tuple): + """A version of isinstance that does not require importing the class. + This is useful to avoid circular imports. + """ + return ( + type(obj).__name__ == class_or_tuple + if isinstance(class_or_tuple, str) + else type(obj).__name__ in class_or_tuple + ) + + +def test_isinstance_noimport(): + class A: + pass + + class B: + pass + + a = A() + b = B() + + assert isinstance_noimport(a, "A") + assert not isinstance_noimport(a, "B") + assert isinstance_noimport(b, ("A", "B")) + assert not isinstance_noimport(b, "C") diff --git a/parcels/_spatialhash.py b/parcels/_spatialhash.py index 4f91d811d3..dbbdbbd536 100644 --- a/parcels/_spatialhash.py +++ b/parcels/_spatialhash.py @@ -2,8 +2,7 @@ import parcels from parcels._index_search import GRID_SEARCH_ERROR, _latlon_rad_to_xyz, curvilinear_point_in_cell, uxgrid_point_in_cell -from parcels._core.uxgrid import UxGrid -from parcels._core.xgrid import XGrid +from parcels._python import isinstance_noimport class SpatialHash: @@ -27,9 +26,9 @@ def __init__( grid, bitwidth=1023, ): - if isinstance(grid, XGrid): + if isinstance_noimport(grid, "XGrid"): self._point_in_cell = curvilinear_point_in_cell - elif isinstance(grid, UxGrid): + elif isinstance_noimport(grid, "UxGrid"): self._point_in_cell = uxgrid_point_in_cell else: raise ValueError("Expected `grid` to be a parcels.XGrid or parcels.UxGrid") @@ -37,7 +36,7 @@ def __init__( self._source_grid = grid self._bitwidth = bitwidth # Max integer to use per coordinate in quantization (10 bits = 0..1023) - if isinstance(grid, XGrid): + if isinstance_noimport(grid, "XGrid"): if self._source_grid._mesh == "spherical": # Boundaries of the hash grid are the unit cube self._xmin = -1.0 @@ -122,7 +121,7 @@ def __init__( self._zlow = np.zeros_like(self._xlow) self._zhigh = np.zeros_like(self._xlow) - elif isinstance(grid, UxGrid): + elif isinstance_noimport(grid, "UxGrid"): if self._source_grid._mesh == "spherical": # Boundaries of the hash grid are the unit cube self._xmin = -1.0 From 04389ba02672c44f29f70199245abf9f8d9f77b9 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 13:42:17 +0200 Subject: [PATCH 26/45] update broken import --- parcels/fieldset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parcels/fieldset.py b/parcels/fieldset.py index 43b1f353b6..1081706876 100644 --- a/parcels/fieldset.py +++ b/parcels/fieldset.py @@ -15,7 +15,7 @@ from parcels._typing import Mesh from parcels.field import Field, VectorField from parcels.converters import Geographic, GeographicPolar -from parcels.xgrid import _DEFAULT_XGCM_KWARGS, XGrid +from parcels._core.xgrid import _DEFAULT_XGCM_KWARGS, XGrid if TYPE_CHECKING: from parcels._typing import TimeLike From 6ed7f669573e3fe466c7155919a82754f6438c45 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 13:46:23 +0200 Subject: [PATCH 27/45] Move kernels out of parcels._core back to parcels Before it wasn't possible to do: from parcels.kernels import AdvectionRK4 but you could do import parcels.kernels parcels.kernels.AdvectionRK4 I think its because the former expects the subpackage to exist at that file location or something along those lines - not 100% sure. Taking kernels out of core (this is quite standalone anyway, which is similar to the other items outside of core) --- parcels/__init__.py | 1 - parcels/kernel.py | 2 +- parcels/{_core => }/kernels/EOSseawaterproperties.py | 0 parcels/{_core => }/kernels/TEOSseawaterdensity.py | 0 parcels/{_core => }/kernels/__init__.py | 0 parcels/{_core => }/kernels/advection.py | 0 parcels/{_core => }/kernels/advectiondiffusion.py | 0 parcels/{_core => }/kernels/interaction.py | 0 parcels/particleset.py | 2 +- 9 files changed, 2 insertions(+), 3 deletions(-) rename parcels/{_core => }/kernels/EOSseawaterproperties.py (100%) rename parcels/{_core => }/kernels/TEOSseawaterdensity.py (100%) rename parcels/{_core => }/kernels/__init__.py (100%) rename parcels/{_core => }/kernels/advection.py (100%) rename parcels/{_core => }/kernels/advectiondiffusion.py (100%) rename parcels/{_core => }/kernels/interaction.py (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index be67b5cfd3..5439529fd0 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -33,7 +33,6 @@ GeographicSquare, UnitConverter, ) -import parcels._core.kernels as kernels from parcels._core.xgrid import XGrid from parcels._core.uxgrid import UxGrid from parcels._core.basegrid import BaseGrid diff --git a/parcels/kernel.py b/parcels/kernel.py index df249dd76b..312ab41023 100644 --- a/parcels/kernel.py +++ b/parcels/kernel.py @@ -10,7 +10,7 @@ from parcels._warnings import KernelWarning from parcels._core.basegrid import GridType -from parcels._core.kernels import ( +from parcels.kernels import ( AdvectionAnalytical, AdvectionRK4, AdvectionRK45, diff --git a/parcels/_core/kernels/EOSseawaterproperties.py b/parcels/kernels/EOSseawaterproperties.py similarity index 100% rename from parcels/_core/kernels/EOSseawaterproperties.py rename to parcels/kernels/EOSseawaterproperties.py diff --git a/parcels/_core/kernels/TEOSseawaterdensity.py b/parcels/kernels/TEOSseawaterdensity.py similarity index 100% rename from parcels/_core/kernels/TEOSseawaterdensity.py rename to parcels/kernels/TEOSseawaterdensity.py diff --git a/parcels/_core/kernels/__init__.py b/parcels/kernels/__init__.py similarity index 100% rename from parcels/_core/kernels/__init__.py rename to parcels/kernels/__init__.py diff --git a/parcels/_core/kernels/advection.py b/parcels/kernels/advection.py similarity index 100% rename from parcels/_core/kernels/advection.py rename to parcels/kernels/advection.py diff --git a/parcels/_core/kernels/advectiondiffusion.py b/parcels/kernels/advectiondiffusion.py similarity index 100% rename from parcels/_core/kernels/advectiondiffusion.py rename to parcels/kernels/advectiondiffusion.py diff --git a/parcels/_core/kernels/interaction.py b/parcels/kernels/interaction.py similarity index 100% rename from parcels/_core/kernels/interaction.py rename to parcels/kernels/interaction.py diff --git a/parcels/particleset.py b/parcels/particleset.py index ebd2f5d003..0b8347965d 100644 --- a/parcels/particleset.py +++ b/parcels/particleset.py @@ -14,7 +14,7 @@ from parcels._reprs import particleset_repr from parcels._warnings import ParticleSetWarning from parcels.kernel import Kernel -from parcels._core.kernels import AdvectionRK4 +from parcels.kernels import AdvectionRK4 from parcels.particle import KernelParticle, Particle, create_particle_data from parcels.statuscodes import StatusCode from parcels.converters import _convert_to_flat_array From 42d837aa666d4a70aae2cee1ae34a10ec1b7fece Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 13:48:41 +0200 Subject: [PATCH 28/45] Update import --- parcels/field.py | 1 + 1 file changed, 1 insertion(+) diff --git a/parcels/field.py b/parcels/field.py index 01cd5d5278..f14ece16d6 100644 --- a/parcels/field.py +++ b/parcels/field.py @@ -29,6 +29,7 @@ ) from parcels._core.uxgrid import UxGrid from parcels._core.xgrid import XGrid, _transpose_xfield_data_to_tzyx +from parcels._core.constants import RIGHT_OUT_OF_BOUNDS, LEFT_OUT_OF_BOUNDS from ._index_search import GRID_SEARCH_ERROR, _search_time_index From c1309ba728131aa06db85c9dbd3e0f4af9e71387 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 13:53:31 +0200 Subject: [PATCH 29/45] Move Field to _core --- parcels/__init__.py | 2 +- parcels/{ => _core}/field.py | 2 +- parcels/_index_search.py | 2 +- parcels/fieldset.py | 2 +- parcels/interaction/interactionkernel.py | 2 +- parcels/interpolators.py | 2 +- tests/test_advection.py | 2 +- tests/test_diffusion.py | 2 +- tests/test_fieldset.py | 2 +- tests/test_index_search.py | 2 +- tests/test_interpolation.py | 2 +- tests/utils.py | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) rename parcels/{ => _core}/field.py (99%) diff --git a/parcels/__init__.py b/parcels/__init__.py index 5439529fd0..6ca8aa7e00 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -12,7 +12,7 @@ KernelWarning, ParticleSetWarning, ) -from parcels.field import Field, VectorField +from parcels._core.field import Field, VectorField from parcels.fieldset import FieldSet from parcels.kernel import Kernel from parcels.particle import ( diff --git a/parcels/field.py b/parcels/_core/field.py similarity index 99% rename from parcels/field.py rename to parcels/_core/field.py index f14ece16d6..c90a4414f0 100644 --- a/parcels/field.py +++ b/parcels/_core/field.py @@ -31,7 +31,7 @@ from parcels._core.xgrid import XGrid, _transpose_xfield_data_to_tzyx from parcels._core.constants import RIGHT_OUT_OF_BOUNDS, LEFT_OUT_OF_BOUNDS -from ._index_search import GRID_SEARCH_ERROR, _search_time_index +from .._index_search import GRID_SEARCH_ERROR, _search_time_index __all__ = ["Field", "VectorField"] diff --git a/parcels/_index_search.py b/parcels/_index_search.py index 1b288d8aef..a7794c10bf 100644 --- a/parcels/_index_search.py +++ b/parcels/_index_search.py @@ -10,7 +10,7 @@ if TYPE_CHECKING: from parcels.xgrid import XGrid - from .field import Field + from parcels._core.field import Field GRID_SEARCH_ERROR = -3 diff --git a/parcels/fieldset.py b/parcels/fieldset.py index 1081706876..6f382e9e59 100644 --- a/parcels/fieldset.py +++ b/parcels/fieldset.py @@ -13,7 +13,7 @@ from parcels._core.utils.time import is_compatible as datetime_is_compatible from parcels._logger import logger from parcels._typing import Mesh -from parcels.field import Field, VectorField +from parcels._core.field import Field, VectorField from parcels.converters import Geographic, GeographicPolar from parcels._core.xgrid import _DEFAULT_XGCM_KWARGS, XGrid diff --git a/parcels/interaction/interactionkernel.py b/parcels/interaction/interactionkernel.py index 59acfb8797..39051e587f 100644 --- a/parcels/interaction/interactionkernel.py +++ b/parcels/interaction/interactionkernel.py @@ -5,7 +5,7 @@ import numpy as np from parcels._compat import MPI -from parcels.field import VectorField +from parcels._core.field import VectorField from parcels.kernel import BaseKernel from parcels.statuscodes import StatusCode diff --git a/parcels/interpolators.py b/parcels/interpolators.py index f315c031aa..4a2f9ad293 100644 --- a/parcels/interpolators.py +++ b/parcels/interpolators.py @@ -11,7 +11,7 @@ import parcels.utils.interpolation_utils as i_u if TYPE_CHECKING: - from parcels.field import Field, VectorField + from parcels._core.field import Field, VectorField from parcels._core.uxgrid import _UXGRID_AXES from parcels._core.xgrid import _XGRID_AXES diff --git a/tests/test_advection.py b/tests/test_advection.py index c2d74d1405..9461cdedd0 100644 --- a/tests/test_advection.py +++ b/tests/test_advection.py @@ -12,7 +12,7 @@ simple_UV_dataset, stommel_gyre_dataset, ) -from parcels.field import Field, VectorField +from parcels import Field, VectorField from parcels.fieldset import FieldSet from parcels.interpolators import CGrid_Velocity, XLinear from parcels.kernels import ( diff --git a/tests/test_diffusion.py b/tests/test_diffusion.py index 33502d472f..583c98ebec 100644 --- a/tests/test_diffusion.py +++ b/tests/test_diffusion.py @@ -5,7 +5,7 @@ from scipy import stats from parcels._datasets.structured.generated import simple_UV_dataset -from parcels.field import Field, VectorField +from parcels import Field, VectorField from parcels.fieldset import FieldSet from parcels.interpolators import XLinear from parcels.kernels import AdvectionDiffusionEM, AdvectionDiffusionM1, DiffusionUniformKh diff --git a/tests/test_fieldset.py b/tests/test_fieldset.py index b976342af7..f0598c2039 100644 --- a/tests/test_fieldset.py +++ b/tests/test_fieldset.py @@ -9,7 +9,7 @@ from parcels._datasets.structured.circulation_models import datasets as datasets_circulation_models from parcels._datasets.structured.generic import T as T_structured from parcels._datasets.structured.generic import datasets as datasets_structured -from parcels.field import Field, VectorField +from parcels import Field, VectorField from parcels.fieldset import CalendarError, FieldSet, _datetime_to_msg from parcels import XGrid from tests import utils diff --git a/tests/test_index_search.py b/tests/test_index_search.py index 2c46e5c614..07c4792118 100644 --- a/tests/test_index_search.py +++ b/tests/test_index_search.py @@ -6,7 +6,7 @@ from parcels._datasets.structured.generic import datasets from parcels._index_search import _search_indices_curvilinear_2d from parcels._tutorial import download_example_dataset -from parcels.field import Field +from parcels import Field from parcels import XGrid diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index 08413995ab..2e68ffdbcc 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -5,7 +5,7 @@ from parcels._datasets.structured.generated import simple_UV_dataset from parcels._datasets.unstructured.generic import datasets as datasets_unstructured from parcels._index_search import _search_time_index -from parcels.field import Field, VectorField +from parcels import Field, VectorField from parcels.fieldset import FieldSet from parcels.interpolators import ( UXPiecewiseLinearNode, diff --git a/tests/utils.py b/tests/utils.py index 6bae31a633..9c226de778 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -10,7 +10,7 @@ import parcels from parcels._datasets.structured.generated import simple_UV_dataset -from parcels.field import Field, VectorField +from parcels import Field, VectorField from parcels.fieldset import FieldSet from parcels.interpolators import XLinear from parcels._core.xgrid import _FIELD_DATA_ORDERING, XGrid, get_axis_from_dim_name From 2a1595c8d46a608bed6e3f134dd5a2265e2a1ad3 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 13:55:51 +0200 Subject: [PATCH 30/45] Move fieldset to _core --- parcels/__init__.py | 2 +- parcels/{ => _core}/fieldset.py | 0 tests/test_advection.py | 2 +- tests/test_diffusion.py | 2 +- tests/test_fieldset.py | 2 +- tests/test_interpolation.py | 2 +- tests/utils.py | 2 +- 7 files changed, 6 insertions(+), 6 deletions(-) rename parcels/{ => _core}/fieldset.py (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index 6ca8aa7e00..51afcfbe44 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -13,7 +13,7 @@ ParticleSetWarning, ) from parcels._core.field import Field, VectorField -from parcels.fieldset import FieldSet +from parcels._core.fieldset import FieldSet from parcels.kernel import Kernel from parcels.particle import ( KernelParticle, # ? remove? diff --git a/parcels/fieldset.py b/parcels/_core/fieldset.py similarity index 100% rename from parcels/fieldset.py rename to parcels/_core/fieldset.py diff --git a/tests/test_advection.py b/tests/test_advection.py index 9461cdedd0..e434f8bac1 100644 --- a/tests/test_advection.py +++ b/tests/test_advection.py @@ -13,7 +13,7 @@ stommel_gyre_dataset, ) from parcels import Field, VectorField -from parcels.fieldset import FieldSet +from parcels import FieldSet from parcels.interpolators import CGrid_Velocity, XLinear from parcels.kernels import ( AdvectionDiffusionEM, diff --git a/tests/test_diffusion.py b/tests/test_diffusion.py index 583c98ebec..fb37faa06b 100644 --- a/tests/test_diffusion.py +++ b/tests/test_diffusion.py @@ -6,7 +6,7 @@ from parcels._datasets.structured.generated import simple_UV_dataset from parcels import Field, VectorField -from parcels.fieldset import FieldSet +from parcels import FieldSet from parcels.interpolators import XLinear from parcels.kernels import AdvectionDiffusionEM, AdvectionDiffusionM1, DiffusionUniformKh from parcels.particle import Particle, Variable diff --git a/tests/test_fieldset.py b/tests/test_fieldset.py index f0598c2039..0fa7576c5e 100644 --- a/tests/test_fieldset.py +++ b/tests/test_fieldset.py @@ -10,7 +10,7 @@ from parcels._datasets.structured.generic import T as T_structured from parcels._datasets.structured.generic import datasets as datasets_structured from parcels import Field, VectorField -from parcels.fieldset import CalendarError, FieldSet, _datetime_to_msg +from parcels._core.fieldset import CalendarError, FieldSet, _datetime_to_msg from parcels import XGrid from tests import utils diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index 2e68ffdbcc..c269a25226 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -6,7 +6,7 @@ from parcels._datasets.unstructured.generic import datasets as datasets_unstructured from parcels._index_search import _search_time_index from parcels import Field, VectorField -from parcels.fieldset import FieldSet +from parcels import FieldSet from parcels.interpolators import ( UXPiecewiseLinearNode, XFreeslip, diff --git a/tests/utils.py b/tests/utils.py index 9c226de778..6f30ea3f12 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -11,7 +11,7 @@ import parcels from parcels._datasets.structured.generated import simple_UV_dataset from parcels import Field, VectorField -from parcels.fieldset import FieldSet +from parcels import FieldSet from parcels.interpolators import XLinear from parcels._core.xgrid import _FIELD_DATA_ORDERING, XGrid, get_axis_from_dim_name From bd5051cc0a42cf0d2fba569794cbd32491dd586e Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 13:58:02 +0200 Subject: [PATCH 31/45] Move particleset to core --- parcels/__init__.py | 2 +- parcels/{ => _core}/particleset.py | 0 parcels/particlefile.py | 2 +- tests/test_advection.py | 2 +- tests/test_diffusion.py | 2 +- tests/test_interpolation.py | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename parcels/{ => _core}/particleset.py (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index 51afcfbe44..517ddd03f4 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -22,7 +22,7 @@ Variable, ) from parcels.particlefile import ParticleFile -from parcels.particleset import ParticleSet +from parcels._core.particleset import ParticleSet from parcels.statuscodes import StatusCode from parcels.utils import * diff --git a/parcels/particleset.py b/parcels/_core/particleset.py similarity index 100% rename from parcels/particleset.py rename to parcels/_core/particleset.py diff --git a/parcels/particlefile.py b/parcels/particlefile.py index e02b4caa25..f355033acf 100644 --- a/parcels/particlefile.py +++ b/parcels/particlefile.py @@ -20,7 +20,7 @@ if TYPE_CHECKING: from parcels._core.utils.time import TimeInterval from parcels.particle import Variable - from parcels.particleset import ParticleSet + from parcels._core.particleset import ParticleSet __all__ = ["ParticleFile"] diff --git a/tests/test_advection.py b/tests/test_advection.py index e434f8bac1..d764c24e7a 100644 --- a/tests/test_advection.py +++ b/tests/test_advection.py @@ -25,7 +25,7 @@ ) from parcels.particle import Particle, Variable from parcels.particlefile import ParticleFile -from parcels.particleset import ParticleSet +from parcels import ParticleSet from parcels.statuscodes import StatusCode from parcels import XGrid from tests.utils import round_and_hash_float_array diff --git a/tests/test_diffusion.py b/tests/test_diffusion.py index fb37faa06b..30a8b14237 100644 --- a/tests/test_diffusion.py +++ b/tests/test_diffusion.py @@ -10,7 +10,7 @@ from parcels.interpolators import XLinear from parcels.kernels import AdvectionDiffusionEM, AdvectionDiffusionM1, DiffusionUniformKh from parcels.particle import Particle, Variable -from parcels.particleset import ParticleSet +from parcels import ParticleSet from parcels import XGrid from tests.utils import create_fieldset_zeros_conversion diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index c269a25226..5ea072eb09 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -18,7 +18,7 @@ from parcels.kernels import AdvectionRK4_3D from parcels.particle import Particle, Variable from parcels.particlefile import ParticleFile -from parcels.particleset import ParticleSet +from parcels import ParticleSet from parcels.statuscodes import StatusCode from parcels import UxGrid from parcels import XGrid From dce1dd1b1b3a358b84e9810a7c737a405517d7d4 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 13:59:12 +0200 Subject: [PATCH 32/45] Move particlefile to _core --- parcels/__init__.py | 2 +- parcels/{ => _core}/particlefile.py | 0 tests-v3/tools/test_warnings.py | 2 +- tests/test_advection.py | 2 +- tests/test_interpolation.py | 2 +- tests/test_particlefile.py | 2 +- tests/test_particleset_execute.py | 2 +- 7 files changed, 6 insertions(+), 6 deletions(-) rename parcels/{ => _core}/particlefile.py (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index 517ddd03f4..d66ee0d1dd 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -21,7 +21,7 @@ ParticleClass, Variable, ) -from parcels.particlefile import ParticleFile +from parcels._core.particlefile import ParticleFile from parcels._core.particleset import ParticleSet from parcels.statuscodes import StatusCode from parcels.utils import * diff --git a/parcels/particlefile.py b/parcels/_core/particlefile.py similarity index 100% rename from parcels/particlefile.py rename to parcels/_core/particlefile.py diff --git a/tests-v3/tools/test_warnings.py b/tests-v3/tools/test_warnings.py index 1570d44bfa..42563a074a 100644 --- a/tests-v3/tools/test_warnings.py +++ b/tests-v3/tools/test_warnings.py @@ -11,7 +11,7 @@ ParticleSet, ParticleSetWarning, ) -from parcels.particlefile import ParticleFile +from parcels import ParticleFile from tests.utils import TEST_DATA diff --git a/tests/test_advection.py b/tests/test_advection.py index d764c24e7a..5ff55033df 100644 --- a/tests/test_advection.py +++ b/tests/test_advection.py @@ -24,7 +24,7 @@ AdvectionRK45, ) from parcels.particle import Particle, Variable -from parcels.particlefile import ParticleFile +from parcels import ParticleFile from parcels import ParticleSet from parcels.statuscodes import StatusCode from parcels import XGrid diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index 5ea072eb09..f970af28d7 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -17,7 +17,7 @@ ) from parcels.kernels import AdvectionRK4_3D from parcels.particle import Particle, Variable -from parcels.particlefile import ParticleFile +from parcels import ParticleFile from parcels import ParticleSet from parcels.statuscodes import StatusCode from parcels import UxGrid diff --git a/tests/test_particlefile.py b/tests/test_particlefile.py index d01be764a6..b035bc0e5f 100755 --- a/tests/test_particlefile.py +++ b/tests/test_particlefile.py @@ -13,7 +13,7 @@ from parcels._datasets.structured.generic import datasets from parcels.kernels import AdvectionRK4 from parcels.particle import Particle, create_particle_data, get_default_particle -from parcels.particlefile import ParticleFile +from parcels import ParticleFile from parcels.statuscodes import StatusCode from parcels import XGrid from tests.common_kernels import DoNothing diff --git a/tests/test_particleset_execute.py b/tests/test_particleset_execute.py index 06334fc291..0fd085a392 100644 --- a/tests/test_particleset_execute.py +++ b/tests/test_particleset_execute.py @@ -18,7 +18,7 @@ from parcels._datasets.unstructured.generic import datasets as datasets_unstructured from parcels.interpolators import UXPiecewiseConstantFace from parcels.kernels import AdvectionEE -from parcels.particlefile import ParticleFile +from parcels import ParticleFile from parcels.statuscodes import FieldInterpolationError, FieldOutOfBoundError, TimeExtrapolationError from parcels import UxGrid from parcels import XGrid From 57f0232a6b1efbed140586bab1119680ebcf1529 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 14:09:14 +0200 Subject: [PATCH 33/45] Move spatialhash to _core --- parcels/_core/basegrid.py | 2 +- parcels/{_spatialhash.py => _core/spatialhash.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename parcels/{_spatialhash.py => _core/spatialhash.py} (100%) diff --git a/parcels/_core/basegrid.py b/parcels/_core/basegrid.py index a43f578eff..d6933bf4a5 100644 --- a/parcels/_core/basegrid.py +++ b/parcels/_core/basegrid.py @@ -7,7 +7,7 @@ import numpy as np -from parcels._spatialhash import SpatialHash +from parcels._core.spatialhash import SpatialHash if TYPE_CHECKING: import numpy as np diff --git a/parcels/_spatialhash.py b/parcels/_core/spatialhash.py similarity index 100% rename from parcels/_spatialhash.py rename to parcels/_core/spatialhash.py From 96d6586782147641783eea4a4284e6b0fdc28cbc Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 14:11:55 +0200 Subject: [PATCH 34/45] Move particle to _core --- parcels/__init__.py | 2 +- parcels/_core/field.py | 2 +- parcels/{ => _core}/particle.py | 0 parcels/_core/particlefile.py | 4 ++-- parcels/_core/particleset.py | 2 +- tests-v3/test_interaction.py | 2 +- tests/test_advection.py | 2 +- tests/test_diffusion.py | 2 +- tests/test_interpolation.py | 2 +- tests/test_kernel.py | 2 +- tests/test_particle.py | 8 +++++++- tests/test_particlefile.py | 2 +- 12 files changed, 18 insertions(+), 12 deletions(-) rename parcels/{ => _core}/particle.py (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index d66ee0d1dd..12949b6e12 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -15,7 +15,7 @@ from parcels._core.field import Field, VectorField from parcels._core.fieldset import FieldSet from parcels.kernel import Kernel -from parcels.particle import ( +from parcels._core.particle import ( KernelParticle, # ? remove? Particle, ParticleClass, diff --git a/parcels/_core/field.py b/parcels/_core/field.py index c90a4414f0..7c677634cd 100644 --- a/parcels/_core/field.py +++ b/parcels/_core/field.py @@ -17,7 +17,7 @@ ZeroInterpolator, ZeroInterpolator_Vector, ) -from parcels.particle import KernelParticle +from parcels._core.particle import KernelParticle from parcels.statuscodes import ( AllParcelsErrorCodes, StatusCode, diff --git a/parcels/particle.py b/parcels/_core/particle.py similarity index 100% rename from parcels/particle.py rename to parcels/_core/particle.py diff --git a/parcels/_core/particlefile.py b/parcels/_core/particlefile.py index f355033acf..10c3af1d00 100644 --- a/parcels/_core/particlefile.py +++ b/parcels/_core/particlefile.py @@ -14,12 +14,12 @@ from zarr.storage import DirectoryStore import parcels -from parcels.particle import _SAME_AS_FIELDSET_TIME_INTERVAL, ParticleClass +from parcels._core.particle import _SAME_AS_FIELDSET_TIME_INTERVAL, ParticleClass from parcels.utils._helpers import timedelta_to_float if TYPE_CHECKING: from parcels._core.utils.time import TimeInterval - from parcels.particle import Variable + from parcels._core.particle import Variable from parcels._core.particleset import ParticleSet __all__ = ["ParticleFile"] diff --git a/parcels/_core/particleset.py b/parcels/_core/particleset.py index 0b8347965d..6a19f5eb2e 100644 --- a/parcels/_core/particleset.py +++ b/parcels/_core/particleset.py @@ -15,7 +15,7 @@ from parcels._warnings import ParticleSetWarning from parcels.kernel import Kernel from parcels.kernels import AdvectionRK4 -from parcels.particle import KernelParticle, Particle, create_particle_data +from parcels._core.particle import KernelParticle, Particle, create_particle_data from parcels.statuscodes import StatusCode from parcels.converters import _convert_to_flat_array diff --git a/tests-v3/test_interaction.py b/tests-v3/test_interaction.py index e1fc562cf1..7c1493677f 100644 --- a/tests-v3/test_interaction.py +++ b/tests-v3/test_interaction.py @@ -16,7 +16,7 @@ MergeWithNearestNeighbor, NearestNeighborWithinRange, ) -from parcels.particle import InteractionParticle, Variable +from parcels._core.particle import InteractionParticle, Variable from tests.common_kernels import DoNothing from tests.utils import create_fieldset_unit_mesh, create_flat_positions, create_spherical_positions diff --git a/tests/test_advection.py b/tests/test_advection.py index 5ff55033df..30053651a7 100644 --- a/tests/test_advection.py +++ b/tests/test_advection.py @@ -23,7 +23,7 @@ AdvectionRK4_3D, AdvectionRK45, ) -from parcels.particle import Particle, Variable +from parcels import Particle, Variable from parcels import ParticleFile from parcels import ParticleSet from parcels.statuscodes import StatusCode diff --git a/tests/test_diffusion.py b/tests/test_diffusion.py index 30a8b14237..8d993d5302 100644 --- a/tests/test_diffusion.py +++ b/tests/test_diffusion.py @@ -9,7 +9,7 @@ from parcels import FieldSet from parcels.interpolators import XLinear from parcels.kernels import AdvectionDiffusionEM, AdvectionDiffusionM1, DiffusionUniformKh -from parcels.particle import Particle, Variable +from parcels import Particle, Variable from parcels import ParticleSet from parcels import XGrid from tests.utils import create_fieldset_zeros_conversion diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index f970af28d7..b72ac6d7a7 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -16,7 +16,7 @@ ZeroInterpolator, ) from parcels.kernels import AdvectionRK4_3D -from parcels.particle import Particle, Variable +from parcels import Particle, Variable from parcels import ParticleFile from parcels import ParticleSet from parcels.statuscodes import StatusCode diff --git a/tests/test_kernel.py b/tests/test_kernel.py index cf1624272b..6fffe821d8 100644 --- a/tests/test_kernel.py +++ b/tests/test_kernel.py @@ -9,7 +9,7 @@ from parcels._datasets.structured.generic import datasets as datasets_structured from parcels.kernel import Kernel from parcels.kernels import AdvectionRK4 -from parcels.particle import Particle +from parcels import Particle from parcels import XGrid from tests.common_kernels import MoveEast, MoveNorth diff --git a/tests/test_particle.py b/tests/test_particle.py index 3ca0a6c131..50fc40d819 100644 --- a/tests/test_particle.py +++ b/tests/test_particle.py @@ -3,7 +3,13 @@ from parcels._core.utils.time import TimeInterval from parcels._datasets.structured.generic import TIME -from parcels.particle import _SAME_AS_FIELDSET_TIME_INTERVAL, Particle, ParticleClass, Variable, create_particle_data +from parcels._core.particle import ( + _SAME_AS_FIELDSET_TIME_INTERVAL, + Particle, + ParticleClass, + Variable, + create_particle_data, +) def test_variable_init(): diff --git a/tests/test_particlefile.py b/tests/test_particlefile.py index b035bc0e5f..6f7db9b311 100755 --- a/tests/test_particlefile.py +++ b/tests/test_particlefile.py @@ -12,7 +12,7 @@ from parcels._core.utils.time import TimeInterval from parcels._datasets.structured.generic import datasets from parcels.kernels import AdvectionRK4 -from parcels.particle import Particle, create_particle_data, get_default_particle +from parcels._core.particle import Particle, create_particle_data, get_default_particle from parcels import ParticleFile from parcels.statuscodes import StatusCode from parcels import XGrid From a090999224661fa5c4385a61cadc3c84bf598b30 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 14:13:53 +0200 Subject: [PATCH 35/45] Move kernel to _core --- parcels/__init__.py | 2 +- parcels/{ => _core}/kernel.py | 0 parcels/_core/particleset.py | 2 +- tests/test_kernel.py | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename parcels/{ => _core}/kernel.py (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index 12949b6e12..342b119dc1 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -14,7 +14,7 @@ ) from parcels._core.field import Field, VectorField from parcels._core.fieldset import FieldSet -from parcels.kernel import Kernel +from parcels._core.kernel import Kernel from parcels._core.particle import ( KernelParticle, # ? remove? Particle, diff --git a/parcels/kernel.py b/parcels/_core/kernel.py similarity index 100% rename from parcels/kernel.py rename to parcels/_core/kernel.py diff --git a/parcels/_core/particleset.py b/parcels/_core/particleset.py index 6a19f5eb2e..4226d8bd97 100644 --- a/parcels/_core/particleset.py +++ b/parcels/_core/particleset.py @@ -13,7 +13,7 @@ from parcels._logger import logger from parcels._reprs import particleset_repr from parcels._warnings import ParticleSetWarning -from parcels.kernel import Kernel +from parcels._core.kernel import Kernel from parcels.kernels import AdvectionRK4 from parcels._core.particle import KernelParticle, Particle, create_particle_data from parcels.statuscodes import StatusCode diff --git a/tests/test_kernel.py b/tests/test_kernel.py index 6fffe821d8..11cab1e038 100644 --- a/tests/test_kernel.py +++ b/tests/test_kernel.py @@ -7,7 +7,7 @@ ParticleSet, ) from parcels._datasets.structured.generic import datasets as datasets_structured -from parcels.kernel import Kernel +from parcels import Kernel from parcels.kernels import AdvectionRK4 from parcels import Particle from parcels import XGrid From 46ca289b61587422b3debd391385a723802a2ba4 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 14:18:51 +0200 Subject: [PATCH 36/45] Move statuscodes to core --- parcels/__init__.py | 10 +++++++++- parcels/_core/field.py | 2 +- parcels/_core/kernel.py | 2 +- parcels/_core/particle.py | 2 +- parcels/_core/particleset.py | 2 +- parcels/{ => _core}/statuscodes.py | 0 parcels/_index_search.py | 2 +- parcels/interaction/interactionkernel.py | 2 +- parcels/kernels/advection.py | 2 +- parcels/kernels/interaction.py | 2 +- tests/common_kernels.py | 2 +- tests/test_advection.py | 2 +- tests/test_interpolation.py | 2 +- tests/test_particlefile.py | 2 +- tests/test_particleset_execute.py | 2 +- 15 files changed, 22 insertions(+), 14 deletions(-) rename parcels/{ => _core}/statuscodes.py (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index 342b119dc1..30fe427df1 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -23,7 +23,15 @@ ) from parcels._core.particlefile import ParticleFile from parcels._core.particleset import ParticleSet -from parcels.statuscodes import StatusCode +from parcels._core.statuscodes import ( + AllParcelsErrorCodes, + FieldOutOfBoundError, + FieldSamplingError, + KernelError, + StatusCode, + FieldInterpolationError, + TimeExtrapolationError, +) from parcels.utils import * from parcels.converters import ( diff --git a/parcels/_core/field.py b/parcels/_core/field.py index 7c677634cd..412f71928b 100644 --- a/parcels/_core/field.py +++ b/parcels/_core/field.py @@ -18,7 +18,7 @@ ZeroInterpolator_Vector, ) from parcels._core.particle import KernelParticle -from parcels.statuscodes import ( +from parcels._core.statuscodes import ( AllParcelsErrorCodes, StatusCode, ) diff --git a/parcels/_core/kernel.py b/parcels/_core/kernel.py index 312ab41023..551de3bc70 100644 --- a/parcels/_core/kernel.py +++ b/parcels/_core/kernel.py @@ -15,7 +15,7 @@ AdvectionRK4, AdvectionRK45, ) -from parcels.statuscodes import ( +from parcels._core.statuscodes import ( StatusCode, _raise_field_interpolation_error, _raise_field_out_of_bound_error, diff --git a/parcels/_core/particle.py b/parcels/_core/particle.py index f47e9cf862..93c6be0dee 100644 --- a/parcels/_core/particle.py +++ b/parcels/_core/particle.py @@ -10,7 +10,7 @@ from parcels._compat import _attrgetter_helper from parcels._core.utils.time import TimeInterval from parcels._reprs import _format_list_items_multiline -from parcels.statuscodes import StatusCode +from parcels._core.statuscodes import StatusCode __all__ = ["KernelParticle", "Particle", "ParticleClass", "Variable"] _TO_WRITE_OPTIONS = [True, False, "once"] diff --git a/parcels/_core/particleset.py b/parcels/_core/particleset.py index 4226d8bd97..4dcb0d55b5 100644 --- a/parcels/_core/particleset.py +++ b/parcels/_core/particleset.py @@ -16,7 +16,7 @@ from parcels._core.kernel import Kernel from parcels.kernels import AdvectionRK4 from parcels._core.particle import KernelParticle, Particle, create_particle_data -from parcels.statuscodes import StatusCode +from parcels._core.statuscodes import StatusCode from parcels.converters import _convert_to_flat_array __all__ = ["ParticleSet"] diff --git a/parcels/statuscodes.py b/parcels/_core/statuscodes.py similarity index 100% rename from parcels/statuscodes.py rename to parcels/_core/statuscodes.py diff --git a/parcels/_index_search.py b/parcels/_index_search.py index a7794c10bf..123774a0dc 100644 --- a/parcels/_index_search.py +++ b/parcels/_index_search.py @@ -5,7 +5,7 @@ import numpy as np -from parcels.statuscodes import _raise_time_extrapolation_error +from parcels._core.statuscodes import _raise_time_extrapolation_error if TYPE_CHECKING: from parcels.xgrid import XGrid diff --git a/parcels/interaction/interactionkernel.py b/parcels/interaction/interactionkernel.py index 39051e587f..d21b7773b4 100644 --- a/parcels/interaction/interactionkernel.py +++ b/parcels/interaction/interactionkernel.py @@ -7,7 +7,7 @@ from parcels._compat import MPI from parcels._core.field import VectorField from parcels.kernel import BaseKernel -from parcels.statuscodes import StatusCode +from parcels._core.statuscodes import StatusCode __all__ = ["InteractionKernel"] diff --git a/parcels/kernels/advection.py b/parcels/kernels/advection.py index 493ecae94b..8d21392903 100644 --- a/parcels/kernels/advection.py +++ b/parcels/kernels/advection.py @@ -4,7 +4,7 @@ import numpy as np -from parcels.statuscodes import StatusCode +from parcels._core.statuscodes import StatusCode __all__ = [ "AdvectionAnalytical", diff --git a/parcels/kernels/interaction.py b/parcels/kernels/interaction.py index 96f27b4e1b..2eb919ef9d 100644 --- a/parcels/kernels/interaction.py +++ b/parcels/kernels/interaction.py @@ -2,7 +2,7 @@ import numpy as np -from parcels.statuscodes import StatusCode +from parcels._core.statuscodes import StatusCode __all__ = ["AsymmetricAttraction", "MergeWithNearestNeighbor", "NearestNeighborWithinRange"] diff --git a/tests/common_kernels.py b/tests/common_kernels.py index 625dc14534..53e3c7310b 100644 --- a/tests/common_kernels.py +++ b/tests/common_kernels.py @@ -2,7 +2,7 @@ import numpy as np -from parcels.statuscodes import StatusCode +from parcels import StatusCode def DoNothing(particles, fieldset): # pragma: no cover diff --git a/tests/test_advection.py b/tests/test_advection.py index 30053651a7..06e3718e20 100644 --- a/tests/test_advection.py +++ b/tests/test_advection.py @@ -26,7 +26,7 @@ from parcels import Particle, Variable from parcels import ParticleFile from parcels import ParticleSet -from parcels.statuscodes import StatusCode +from parcels import StatusCode from parcels import XGrid from tests.utils import round_and_hash_float_array diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index b72ac6d7a7..3232562959 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -19,7 +19,7 @@ from parcels import Particle, Variable from parcels import ParticleFile from parcels import ParticleSet -from parcels.statuscodes import StatusCode +from parcels import StatusCode from parcels import UxGrid from parcels import XGrid from tests.utils import TEST_DATA diff --git a/tests/test_particlefile.py b/tests/test_particlefile.py index 6f7db9b311..57337a6b34 100755 --- a/tests/test_particlefile.py +++ b/tests/test_particlefile.py @@ -14,7 +14,7 @@ from parcels.kernels import AdvectionRK4 from parcels._core.particle import Particle, create_particle_data, get_default_particle from parcels import ParticleFile -from parcels.statuscodes import StatusCode +from parcels import StatusCode from parcels import XGrid from tests.common_kernels import DoNothing diff --git a/tests/test_particleset_execute.py b/tests/test_particleset_execute.py index 0fd085a392..7ae97488df 100644 --- a/tests/test_particleset_execute.py +++ b/tests/test_particleset_execute.py @@ -19,7 +19,7 @@ from parcels.interpolators import UXPiecewiseConstantFace from parcels.kernels import AdvectionEE from parcels import ParticleFile -from parcels.statuscodes import FieldInterpolationError, FieldOutOfBoundError, TimeExtrapolationError +from parcels import FieldInterpolationError, FieldOutOfBoundError, TimeExtrapolationError from parcels import UxGrid from parcels import XGrid from tests import utils From dce831de351010b518f6c7f33eeb1d4119fd60a8 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 14:20:22 +0200 Subject: [PATCH 37/45] Move warnings to _core --- parcels/__init__.py | 2 +- parcels/_core/kernel.py | 2 +- parcels/_core/particleset.py | 2 +- parcels/{_warnings.py => _core/warnings.py} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename parcels/{_warnings.py => _core/warnings.py} (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index 30fe427df1..a32f46fdfa 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -6,7 +6,7 @@ from parcels._logger import logger from parcels._tutorial import download_example_dataset, list_example_datasets -from parcels._warnings import ( +from parcels._core.warnings import ( FieldSetWarning, FileWarning, KernelWarning, diff --git a/parcels/_core/kernel.py b/parcels/_core/kernel.py index 551de3bc70..c4b0585237 100644 --- a/parcels/_core/kernel.py +++ b/parcels/_core/kernel.py @@ -8,7 +8,7 @@ import numpy as np -from parcels._warnings import KernelWarning +from parcels._core.warnings import KernelWarning from parcels._core.basegrid import GridType from parcels.kernels import ( AdvectionAnalytical, diff --git a/parcels/_core/particleset.py b/parcels/_core/particleset.py index 4dcb0d55b5..82583e0e08 100644 --- a/parcels/_core/particleset.py +++ b/parcels/_core/particleset.py @@ -12,7 +12,7 @@ from parcels._core.utils.time import TimeInterval, maybe_convert_python_timedelta_to_numpy from parcels._logger import logger from parcels._reprs import particleset_repr -from parcels._warnings import ParticleSetWarning +from parcels._core.warnings import ParticleSetWarning from parcels._core.kernel import Kernel from parcels.kernels import AdvectionRK4 from parcels._core.particle import KernelParticle, Particle, create_particle_data diff --git a/parcels/_warnings.py b/parcels/_core/warnings.py similarity index 100% rename from parcels/_warnings.py rename to parcels/_core/warnings.py From f858d7f776a91f9dc20058ee806f387619192dec Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 14:24:35 +0200 Subject: [PATCH 38/45] Move converters to _core --- parcels/__init__.py | 2 +- parcels/{ => _core}/converters.py | 0 parcels/_core/field.py | 2 +- parcels/_core/fieldset.py | 2 +- parcels/_core/particleset.py | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename parcels/{ => _core}/converters.py (100%) diff --git a/parcels/__init__.py b/parcels/__init__.py index a32f46fdfa..fbfa100936 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -34,7 +34,7 @@ ) from parcels.utils import * -from parcels.converters import ( +from parcels._core.converters import ( Geographic, GeographicPolar, GeographicPolarSquare, diff --git a/parcels/converters.py b/parcels/_core/converters.py similarity index 100% rename from parcels/converters.py rename to parcels/_core/converters.py diff --git a/parcels/_core/field.py b/parcels/_core/field.py index 412f71928b..d970ba7fef 100644 --- a/parcels/_core/field.py +++ b/parcels/_core/field.py @@ -23,7 +23,7 @@ StatusCode, ) from parcels.utils._helpers import _assert_same_function_signature -from parcels.converters import ( +from parcels._core.converters import ( UnitConverter, _unitconverters_map, ) diff --git a/parcels/_core/fieldset.py b/parcels/_core/fieldset.py index 6f382e9e59..50c4598e64 100644 --- a/parcels/_core/fieldset.py +++ b/parcels/_core/fieldset.py @@ -14,7 +14,7 @@ from parcels._logger import logger from parcels._typing import Mesh from parcels._core.field import Field, VectorField -from parcels.converters import Geographic, GeographicPolar +from parcels._core.converters import Geographic, GeographicPolar from parcels._core.xgrid import _DEFAULT_XGCM_KWARGS, XGrid if TYPE_CHECKING: diff --git a/parcels/_core/particleset.py b/parcels/_core/particleset.py index 82583e0e08..5e78d8a10a 100644 --- a/parcels/_core/particleset.py +++ b/parcels/_core/particleset.py @@ -17,7 +17,7 @@ from parcels.kernels import AdvectionRK4 from parcels._core.particle import KernelParticle, Particle, create_particle_data from parcels._core.statuscodes import StatusCode -from parcels.converters import _convert_to_flat_array +from parcels._core.converters import _convert_to_flat_array __all__ = ["ParticleSet"] From 499ff47e07f2b56184e244e32f82a1e68210e061 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 14:29:31 +0200 Subject: [PATCH 39/45] Move index_search to _core --- parcels/_core/field.py | 2 +- parcels/{_index_search.py => _core/index_search.py} | 0 parcels/_core/spatialhash.py | 2 +- parcels/_core/uxgrid.py | 2 +- parcels/_core/xgrid.py | 2 +- tests/test_index_search.py | 2 +- tests/test_interpolation.py | 2 +- 7 files changed, 6 insertions(+), 6 deletions(-) rename parcels/{_index_search.py => _core/index_search.py} (100%) diff --git a/parcels/_core/field.py b/parcels/_core/field.py index d970ba7fef..6d423ad338 100644 --- a/parcels/_core/field.py +++ b/parcels/_core/field.py @@ -31,7 +31,7 @@ from parcels._core.xgrid import XGrid, _transpose_xfield_data_to_tzyx from parcels._core.constants import RIGHT_OUT_OF_BOUNDS, LEFT_OUT_OF_BOUNDS -from .._index_search import GRID_SEARCH_ERROR, _search_time_index +from parcels._core.index_search import GRID_SEARCH_ERROR, _search_time_index __all__ = ["Field", "VectorField"] diff --git a/parcels/_index_search.py b/parcels/_core/index_search.py similarity index 100% rename from parcels/_index_search.py rename to parcels/_core/index_search.py diff --git a/parcels/_core/spatialhash.py b/parcels/_core/spatialhash.py index dbbdbbd536..879ef254d3 100644 --- a/parcels/_core/spatialhash.py +++ b/parcels/_core/spatialhash.py @@ -1,7 +1,7 @@ import numpy as np import parcels -from parcels._index_search import GRID_SEARCH_ERROR, _latlon_rad_to_xyz, curvilinear_point_in_cell, uxgrid_point_in_cell +from parcels._core.index_search import GRID_SEARCH_ERROR, _latlon_rad_to_xyz, curvilinear_point_in_cell, uxgrid_point_in_cell from parcels._python import isinstance_noimport diff --git a/parcels/_core/uxgrid.py b/parcels/_core/uxgrid.py index ab7a78173c..769a173ba4 100644 --- a/parcels/_core/uxgrid.py +++ b/parcels/_core/uxgrid.py @@ -5,7 +5,7 @@ import numpy as np import uxarray as ux -from parcels._index_search import GRID_SEARCH_ERROR, uxgrid_point_in_cell +from parcels._core.index_search import GRID_SEARCH_ERROR, uxgrid_point_in_cell from parcels._typing import assert_valid_mesh from parcels._core.utils.array import _search_1d_array diff --git a/parcels/_core/xgrid.py b/parcels/_core/xgrid.py index 7dad60ec57..34e8450339 100644 --- a/parcels/_core/xgrid.py +++ b/parcels/_core/xgrid.py @@ -7,7 +7,7 @@ import xarray as xr import xgcm -from parcels._index_search import _search_indices_curvilinear_2d +from parcels._core.index_search import _search_indices_curvilinear_2d from parcels._typing import assert_valid_mesh from parcels._core.basegrid import BaseGrid from parcels._core.utils.array import _search_1d_array diff --git a/tests/test_index_search.py b/tests/test_index_search.py index 07c4792118..1c6a74b45d 100644 --- a/tests/test_index_search.py +++ b/tests/test_index_search.py @@ -4,7 +4,7 @@ import xgcm from parcels._datasets.structured.generic import datasets -from parcels._index_search import _search_indices_curvilinear_2d +from parcels._core.index_search import _search_indices_curvilinear_2d from parcels._tutorial import download_example_dataset from parcels import Field from parcels import XGrid diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index 3232562959..8728eec9d8 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -4,7 +4,7 @@ from parcels._datasets.structured.generated import simple_UV_dataset from parcels._datasets.unstructured.generic import datasets as datasets_unstructured -from parcels._index_search import _search_time_index +from parcels._core.index_search import _search_time_index from parcels import Field, VectorField from parcels import FieldSet from parcels.interpolators import ( From 8b2c18dd3599bb4ada9d77657d890440d4ba946a Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 14:31:29 +0200 Subject: [PATCH 40/45] Run pre-commit --- parcels/__init__.py | 35 ++++++++++++------------ parcels/_core/basegrid.py | 1 - parcels/_core/field.py | 27 +++++++++--------- parcels/_core/fieldset.py | 8 +++--- parcels/_core/index_search.py | 3 +- parcels/_core/kernel.py | 12 ++++---- parcels/_core/particle.py | 2 +- parcels/_core/particlefile.py | 2 +- parcels/_core/particleset.py | 10 +++---- parcels/_core/spatialhash.py | 8 ++++-- parcels/_core/utils/array.py | 1 + parcels/_core/uxgrid.py | 5 ++-- parcels/_core/xgrid.py | 4 +-- parcels/interaction/interactionkernel.py | 2 +- tests-v3/test_interaction.py | 2 +- tests-v3/tools/test_warnings.py | 2 +- tests/test_advection.py | 8 +----- tests/test_datasets.py | 2 +- tests/test_diffusion.py | 6 +--- tests/test_field.py | 4 +-- tests/test_fieldset.py | 5 ++-- tests/test_index_search.py | 5 ++-- tests/test_interpolation.py | 22 +++++++++------ tests/test_kernel.py | 6 ++-- tests/test_particle.py | 4 +-- tests/test_particlefile.py | 7 ++--- tests/test_particleset.py | 2 +- tests/test_particleset_execute.py | 10 ++++--- tests/test_spatialhash.py | 2 +- tests/test_uxarray_fieldset.py | 2 +- tests/test_uxgrid.py | 2 +- tests/test_xgrid.py | 6 ++-- tests/utils.py | 5 ++-- 33 files changed, 105 insertions(+), 117 deletions(-) diff --git a/parcels/__init__.py b/parcels/__init__.py index fbfa100936..dcb2fab8a9 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -4,13 +4,13 @@ import warnings as _stdlib_warnings -from parcels._logger import logger -from parcels._tutorial import download_example_dataset, list_example_datasets -from parcels._core.warnings import ( - FieldSetWarning, - FileWarning, - KernelWarning, - ParticleSetWarning, +from parcels._core.basegrid import BaseGrid +from parcels._core.converters import ( + Geographic, + GeographicPolar, + GeographicPolarSquare, + GeographicSquare, + UnitConverter, ) from parcels._core.field import Field, VectorField from parcels._core.fieldset import FieldSet @@ -25,25 +25,24 @@ from parcels._core.particleset import ParticleSet from parcels._core.statuscodes import ( AllParcelsErrorCodes, + FieldInterpolationError, FieldOutOfBoundError, FieldSamplingError, KernelError, StatusCode, - FieldInterpolationError, TimeExtrapolationError, ) -from parcels.utils import * - -from parcels._core.converters import ( - Geographic, - GeographicPolar, - GeographicPolarSquare, - GeographicSquare, - UnitConverter, +from parcels._core.uxgrid import UxGrid +from parcels._core.warnings import ( + FieldSetWarning, + FileWarning, + KernelWarning, + ParticleSetWarning, ) from parcels._core.xgrid import XGrid -from parcels._core.uxgrid import UxGrid -from parcels._core.basegrid import BaseGrid +from parcels._logger import logger +from parcels._tutorial import download_example_dataset, list_example_datasets +from parcels.utils import * _stdlib_warnings.warn( "This is an alpha version of Parcels v4. The API is not stable and may change without deprecation warnings.", diff --git a/parcels/_core/basegrid.py b/parcels/_core/basegrid.py index d6933bf4a5..a05ea6dfc3 100644 --- a/parcels/_core/basegrid.py +++ b/parcels/_core/basegrid.py @@ -1,4 +1,3 @@ - from __future__ import annotations from abc import ABC, abstractmethod diff --git a/parcels/_core/field.py b/parcels/_core/field.py index 6d423ad338..01190c2168 100644 --- a/parcels/_core/field.py +++ b/parcels/_core/field.py @@ -8,7 +8,20 @@ import uxarray as ux import xarray as xr +from parcels._core.constants import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS +from parcels._core.converters import ( + UnitConverter, + _unitconverters_map, +) +from parcels._core.index_search import GRID_SEARCH_ERROR, _search_time_index +from parcels._core.particle import KernelParticle +from parcels._core.statuscodes import ( + AllParcelsErrorCodes, + StatusCode, +) from parcels._core.utils.time import TimeInterval +from parcels._core.uxgrid import UxGrid +from parcels._core.xgrid import XGrid, _transpose_xfield_data_to_tzyx from parcels._reprs import default_repr from parcels._typing import VectorType from parcels.interpolators import ( @@ -17,21 +30,7 @@ ZeroInterpolator, ZeroInterpolator_Vector, ) -from parcels._core.particle import KernelParticle -from parcels._core.statuscodes import ( - AllParcelsErrorCodes, - StatusCode, -) from parcels.utils._helpers import _assert_same_function_signature -from parcels._core.converters import ( - UnitConverter, - _unitconverters_map, -) -from parcels._core.uxgrid import UxGrid -from parcels._core.xgrid import XGrid, _transpose_xfield_data_to_tzyx -from parcels._core.constants import RIGHT_OUT_OF_BOUNDS, LEFT_OUT_OF_BOUNDS - -from parcels._core.index_search import GRID_SEARCH_ERROR, _search_time_index __all__ = ["Field", "VectorField"] diff --git a/parcels/_core/fieldset.py b/parcels/_core/fieldset.py index 50c4598e64..bbc064a19e 100644 --- a/parcels/_core/fieldset.py +++ b/parcels/_core/fieldset.py @@ -9,17 +9,17 @@ import xarray as xr import xgcm +from parcels._core.converters import Geographic, GeographicPolar +from parcels._core.field import Field, VectorField from parcels._core.utils.time import get_datetime_type_calendar from parcels._core.utils.time import is_compatible as datetime_is_compatible +from parcels._core.xgrid import _DEFAULT_XGCM_KWARGS, XGrid from parcels._logger import logger from parcels._typing import Mesh -from parcels._core.field import Field, VectorField -from parcels._core.converters import Geographic, GeographicPolar -from parcels._core.xgrid import _DEFAULT_XGCM_KWARGS, XGrid if TYPE_CHECKING: - from parcels._typing import TimeLike from parcels._core.basegrid import BaseGrid + from parcels._typing import TimeLike __all__ = ["FieldSet"] diff --git a/parcels/_core/index_search.py b/parcels/_core/index_search.py index 123774a0dc..5c210985d7 100644 --- a/parcels/_core/index_search.py +++ b/parcels/_core/index_search.py @@ -8,9 +8,8 @@ from parcels._core.statuscodes import _raise_time_extrapolation_error if TYPE_CHECKING: - from parcels.xgrid import XGrid - from parcels._core.field import Field + from parcels.xgrid import XGrid GRID_SEARCH_ERROR = -3 diff --git a/parcels/_core/kernel.py b/parcels/_core/kernel.py index c4b0585237..cbcc5d2cd0 100644 --- a/parcels/_core/kernel.py +++ b/parcels/_core/kernel.py @@ -8,13 +8,7 @@ import numpy as np -from parcels._core.warnings import KernelWarning from parcels._core.basegrid import GridType -from parcels.kernels import ( - AdvectionAnalytical, - AdvectionRK4, - AdvectionRK45, -) from parcels._core.statuscodes import ( StatusCode, _raise_field_interpolation_error, @@ -24,6 +18,12 @@ _raise_grid_searching_error, _raise_time_extrapolation_error, ) +from parcels._core.warnings import KernelWarning +from parcels.kernels import ( + AdvectionAnalytical, + AdvectionRK4, + AdvectionRK45, +) from parcels.utils._helpers import _assert_same_function_signature if TYPE_CHECKING: diff --git a/parcels/_core/particle.py b/parcels/_core/particle.py index 93c6be0dee..4d3ff09459 100644 --- a/parcels/_core/particle.py +++ b/parcels/_core/particle.py @@ -8,9 +8,9 @@ import numpy as np from parcels._compat import _attrgetter_helper +from parcels._core.statuscodes import StatusCode from parcels._core.utils.time import TimeInterval from parcels._reprs import _format_list_items_multiline -from parcels._core.statuscodes import StatusCode __all__ = ["KernelParticle", "Particle", "ParticleClass", "Variable"] _TO_WRITE_OPTIONS = [True, False, "once"] diff --git a/parcels/_core/particlefile.py b/parcels/_core/particlefile.py index 10c3af1d00..f3ae6c041e 100644 --- a/parcels/_core/particlefile.py +++ b/parcels/_core/particlefile.py @@ -18,9 +18,9 @@ from parcels.utils._helpers import timedelta_to_float if TYPE_CHECKING: - from parcels._core.utils.time import TimeInterval from parcels._core.particle import Variable from parcels._core.particleset import ParticleSet + from parcels._core.utils.time import TimeInterval __all__ = ["ParticleFile"] diff --git a/parcels/_core/particleset.py b/parcels/_core/particleset.py index 5e78d8a10a..bdeef9ae78 100644 --- a/parcels/_core/particleset.py +++ b/parcels/_core/particleset.py @@ -9,15 +9,15 @@ from tqdm import tqdm from zarr.storage import DirectoryStore +from parcels._core.converters import _convert_to_flat_array +from parcels._core.kernel import Kernel +from parcels._core.particle import KernelParticle, Particle, create_particle_data +from parcels._core.statuscodes import StatusCode from parcels._core.utils.time import TimeInterval, maybe_convert_python_timedelta_to_numpy +from parcels._core.warnings import ParticleSetWarning from parcels._logger import logger from parcels._reprs import particleset_repr -from parcels._core.warnings import ParticleSetWarning -from parcels._core.kernel import Kernel from parcels.kernels import AdvectionRK4 -from parcels._core.particle import KernelParticle, Particle, create_particle_data -from parcels._core.statuscodes import StatusCode -from parcels._core.converters import _convert_to_flat_array __all__ = ["ParticleSet"] diff --git a/parcels/_core/spatialhash.py b/parcels/_core/spatialhash.py index 879ef254d3..bb13851672 100644 --- a/parcels/_core/spatialhash.py +++ b/parcels/_core/spatialhash.py @@ -1,7 +1,11 @@ import numpy as np -import parcels -from parcels._core.index_search import GRID_SEARCH_ERROR, _latlon_rad_to_xyz, curvilinear_point_in_cell, uxgrid_point_in_cell +from parcels._core.index_search import ( + GRID_SEARCH_ERROR, + _latlon_rad_to_xyz, + curvilinear_point_in_cell, + uxgrid_point_in_cell, +) from parcels._python import isinstance_noimport diff --git a/parcels/_core/utils/array.py b/parcels/_core/utils/array.py index 4c0eaaa833..59a2f24aad 100644 --- a/parcels/_core/utils/array.py +++ b/parcels/_core/utils/array.py @@ -1,4 +1,5 @@ import numpy as np + from parcels._core.constants import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS diff --git a/parcels/_core/uxgrid.py b/parcels/_core/uxgrid.py index 769a173ba4..3c56573e1f 100644 --- a/parcels/_core/uxgrid.py +++ b/parcels/_core/uxgrid.py @@ -5,11 +5,10 @@ import numpy as np import uxarray as ux +from parcels._core.basegrid import BaseGrid from parcels._core.index_search import GRID_SEARCH_ERROR, uxgrid_point_in_cell -from parcels._typing import assert_valid_mesh from parcels._core.utils.array import _search_1d_array - -from parcels._core.basegrid import BaseGrid +from parcels._typing import assert_valid_mesh _UXGRID_AXES = Literal["Z", "FACE"] diff --git a/parcels/_core/xgrid.py b/parcels/_core/xgrid.py index 34e8450339..583e73b850 100644 --- a/parcels/_core/xgrid.py +++ b/parcels/_core/xgrid.py @@ -7,10 +7,10 @@ import xarray as xr import xgcm -from parcels._core.index_search import _search_indices_curvilinear_2d -from parcels._typing import assert_valid_mesh from parcels._core.basegrid import BaseGrid +from parcels._core.index_search import _search_indices_curvilinear_2d from parcels._core.utils.array import _search_1d_array +from parcels._typing import assert_valid_mesh _XGRID_AXES = Literal["X", "Y", "Z"] _XGRID_AXES_ORDERING: Sequence[_XGRID_AXES] = "ZYX" diff --git a/parcels/interaction/interactionkernel.py b/parcels/interaction/interactionkernel.py index d21b7773b4..b423e1f23d 100644 --- a/parcels/interaction/interactionkernel.py +++ b/parcels/interaction/interactionkernel.py @@ -6,8 +6,8 @@ from parcels._compat import MPI from parcels._core.field import VectorField -from parcels.kernel import BaseKernel from parcels._core.statuscodes import StatusCode +from parcels.kernel import BaseKernel __all__ = ["InteractionKernel"] diff --git a/tests-v3/test_interaction.py b/tests-v3/test_interaction.py index 7c1493677f..34b1a6af34 100644 --- a/tests-v3/test_interaction.py +++ b/tests-v3/test_interaction.py @@ -2,6 +2,7 @@ import pytest from parcels import Field, FieldSet, ParticleSet +from parcels._core.particle import InteractionParticle, Variable from parcels.interaction.neighborsearch import ( BruteFlatNeighborSearch, BruteSphericalNeighborSearch, @@ -16,7 +17,6 @@ MergeWithNearestNeighbor, NearestNeighborWithinRange, ) -from parcels._core.particle import InteractionParticle, Variable from tests.common_kernels import DoNothing from tests.utils import create_fieldset_unit_mesh, create_flat_positions, create_spherical_positions diff --git a/tests-v3/tools/test_warnings.py b/tests-v3/tools/test_warnings.py index 42563a074a..8ed1a207ee 100644 --- a/tests-v3/tools/test_warnings.py +++ b/tests-v3/tools/test_warnings.py @@ -8,10 +8,10 @@ FieldSetWarning, KernelWarning, Particle, + ParticleFile, ParticleSet, ParticleSetWarning, ) -from parcels import ParticleFile from tests.utils import TEST_DATA diff --git a/tests/test_advection.py b/tests/test_advection.py index 06e3718e20..c4e8a82ce9 100644 --- a/tests/test_advection.py +++ b/tests/test_advection.py @@ -4,6 +4,7 @@ import xgcm import parcels +from parcels import Field, FieldSet, Particle, ParticleFile, ParticleSet, StatusCode, Variable, VectorField, XGrid from parcels._datasets.structured.generated import ( decaying_moving_eddy_dataset, moving_eddy_dataset, @@ -12,8 +13,6 @@ simple_UV_dataset, stommel_gyre_dataset, ) -from parcels import Field, VectorField -from parcels import FieldSet from parcels.interpolators import CGrid_Velocity, XLinear from parcels.kernels import ( AdvectionDiffusionEM, @@ -23,11 +22,6 @@ AdvectionRK4_3D, AdvectionRK45, ) -from parcels import Particle, Variable -from parcels import ParticleFile -from parcels import ParticleSet -from parcels import StatusCode -from parcels import XGrid from tests.utils import round_and_hash_float_array kernel = { diff --git a/tests/test_datasets.py b/tests/test_datasets.py index 4825e0b98a..2750583f58 100644 --- a/tests/test_datasets.py +++ b/tests/test_datasets.py @@ -1,7 +1,7 @@ import xgcm -from parcels._datasets.structured.generic import datasets from parcels._core.xgrid import _DEFAULT_XGCM_KWARGS +from parcels._datasets.structured.generic import datasets def test_left_indexed_dataset(): diff --git a/tests/test_diffusion.py b/tests/test_diffusion.py index 8d993d5302..c7ecaf0057 100644 --- a/tests/test_diffusion.py +++ b/tests/test_diffusion.py @@ -4,14 +4,10 @@ import pytest from scipy import stats +from parcels import Field, FieldSet, Particle, ParticleSet, Variable, VectorField, XGrid from parcels._datasets.structured.generated import simple_UV_dataset -from parcels import Field, VectorField -from parcels import FieldSet from parcels.interpolators import XLinear from parcels.kernels import AdvectionDiffusionEM, AdvectionDiffusionM1, DiffusionUniformKh -from parcels import Particle, Variable -from parcels import ParticleSet -from parcels import XGrid from tests.utils import create_fieldset_zeros_conversion diff --git a/tests/test_field.py b/tests/test_field.py index 18376830e3..fda23f4798 100644 --- a/tests/test_field.py +++ b/tests/test_field.py @@ -5,13 +5,11 @@ import uxarray as ux import xarray as xr -from parcels import Field, VectorField +from parcels import Field, UxGrid, VectorField, XGrid from parcels._datasets.structured.generic import T as T_structured from parcels._datasets.structured.generic import datasets as datasets_structured from parcels._datasets.unstructured.generic import datasets as datasets_unstructured from parcels.interpolators import UXPiecewiseConstantFace, UXPiecewiseLinearNode -from parcels import UxGrid -from parcels import XGrid def test_field_init_param_types(): diff --git a/tests/test_fieldset.py b/tests/test_fieldset.py index 0fa7576c5e..c96682ed0c 100644 --- a/tests/test_fieldset.py +++ b/tests/test_fieldset.py @@ -6,12 +6,11 @@ import pytest import xarray as xr +from parcels import Field, VectorField, XGrid +from parcels._core.fieldset import CalendarError, FieldSet, _datetime_to_msg from parcels._datasets.structured.circulation_models import datasets as datasets_circulation_models from parcels._datasets.structured.generic import T as T_structured from parcels._datasets.structured.generic import datasets as datasets_structured -from parcels import Field, VectorField -from parcels._core.fieldset import CalendarError, FieldSet, _datetime_to_msg -from parcels import XGrid from tests import utils ds = datasets_structured["ds_2d_left"] diff --git a/tests/test_index_search.py b/tests/test_index_search.py index 1c6a74b45d..ef27bcd65f 100644 --- a/tests/test_index_search.py +++ b/tests/test_index_search.py @@ -3,11 +3,10 @@ import xarray as xr import xgcm -from parcels._datasets.structured.generic import datasets +from parcels import Field, XGrid from parcels._core.index_search import _search_indices_curvilinear_2d +from parcels._datasets.structured.generic import datasets from parcels._tutorial import download_example_dataset -from parcels import Field -from parcels import XGrid @pytest.fixture diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index 8728eec9d8..3b9478d3cb 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -2,11 +2,21 @@ import pytest import xarray as xr +from parcels import ( + Field, + FieldSet, + Particle, + ParticleFile, + ParticleSet, + StatusCode, + UxGrid, + Variable, + VectorField, + XGrid, +) +from parcels._core.index_search import _search_time_index from parcels._datasets.structured.generated import simple_UV_dataset from parcels._datasets.unstructured.generic import datasets as datasets_unstructured -from parcels._core.index_search import _search_time_index -from parcels import Field, VectorField -from parcels import FieldSet from parcels.interpolators import ( UXPiecewiseLinearNode, XFreeslip, @@ -16,12 +26,6 @@ ZeroInterpolator, ) from parcels.kernels import AdvectionRK4_3D -from parcels import Particle, Variable -from parcels import ParticleFile -from parcels import ParticleSet -from parcels import StatusCode -from parcels import UxGrid -from parcels import XGrid from tests.utils import TEST_DATA diff --git a/tests/test_kernel.py b/tests/test_kernel.py index 11cab1e038..023a1cada1 100644 --- a/tests/test_kernel.py +++ b/tests/test_kernel.py @@ -4,13 +4,13 @@ from parcels import ( Field, FieldSet, + Kernel, + Particle, ParticleSet, + XGrid, ) from parcels._datasets.structured.generic import datasets as datasets_structured -from parcels import Kernel from parcels.kernels import AdvectionRK4 -from parcels import Particle -from parcels import XGrid from tests.common_kernels import MoveEast, MoveNorth diff --git a/tests/test_particle.py b/tests/test_particle.py index 50fc40d819..fdc05ea147 100644 --- a/tests/test_particle.py +++ b/tests/test_particle.py @@ -1,8 +1,6 @@ import numpy as np import pytest -from parcels._core.utils.time import TimeInterval -from parcels._datasets.structured.generic import TIME from parcels._core.particle import ( _SAME_AS_FIELDSET_TIME_INTERVAL, Particle, @@ -10,6 +8,8 @@ Variable, create_particle_data, ) +from parcels._core.utils.time import TimeInterval +from parcels._datasets.structured.generic import TIME def test_variable_init(): diff --git a/tests/test_particlefile.py b/tests/test_particlefile.py index 57337a6b34..fbe222f95b 100755 --- a/tests/test_particlefile.py +++ b/tests/test_particlefile.py @@ -8,14 +8,11 @@ from zarr.storage import MemoryStore import parcels -from parcels import Field, FieldSet, Particle, ParticleSet, Variable, VectorField +from parcels import Field, FieldSet, Particle, ParticleFile, ParticleSet, StatusCode, Variable, VectorField, XGrid +from parcels._core.particle import Particle, create_particle_data, get_default_particle from parcels._core.utils.time import TimeInterval from parcels._datasets.structured.generic import datasets from parcels.kernels import AdvectionRK4 -from parcels._core.particle import Particle, create_particle_data, get_default_particle -from parcels import ParticleFile -from parcels import StatusCode -from parcels import XGrid from tests.common_kernels import DoNothing diff --git a/tests/test_particleset.py b/tests/test_particleset.py index 2a1dde102a..3f18b02943 100644 --- a/tests/test_particleset.py +++ b/tests/test_particleset.py @@ -13,9 +13,9 @@ ParticleSet, ParticleSetWarning, Variable, + XGrid, ) from parcels._datasets.structured.generic import datasets as datasets_structured -from parcels import XGrid from tests.common_kernels import DoNothing from tests.utils import round_and_hash_float_array diff --git a/tests/test_particleset_execute.py b/tests/test_particleset_execute.py index 7ae97488df..0aacb1a2d5 100644 --- a/tests/test_particleset_execute.py +++ b/tests/test_particleset_execute.py @@ -6,22 +6,24 @@ from parcels import ( Field, + FieldInterpolationError, + FieldOutOfBoundError, FieldSet, Particle, + ParticleFile, ParticleSet, StatusCode, + TimeExtrapolationError, + UxGrid, Variable, VectorField, + XGrid, ) from parcels._datasets.structured.generated import simple_UV_dataset from parcels._datasets.structured.generic import datasets as datasets_structured from parcels._datasets.unstructured.generic import datasets as datasets_unstructured from parcels.interpolators import UXPiecewiseConstantFace from parcels.kernels import AdvectionEE -from parcels import ParticleFile -from parcels import FieldInterpolationError, FieldOutOfBoundError, TimeExtrapolationError -from parcels import UxGrid -from parcels import XGrid from tests import utils from tests.common_kernels import DoNothing diff --git a/tests/test_spatialhash.py b/tests/test_spatialhash.py index 27ec55bfb5..500ce562cd 100644 --- a/tests/test_spatialhash.py +++ b/tests/test_spatialhash.py @@ -1,7 +1,7 @@ import numpy as np -from parcels._datasets.structured.generic import datasets from parcels import XGrid +from parcels._datasets.structured.generic import datasets def test_spatialhash_init(): diff --git a/tests/test_uxarray_fieldset.py b/tests/test_uxarray_fieldset.py index 3732dbb104..d279dac4f2 100644 --- a/tests/test_uxarray_fieldset.py +++ b/tests/test_uxarray_fieldset.py @@ -7,6 +7,7 @@ FieldSet, Particle, ParticleSet, + UxGrid, VectorField, download_example_dataset, ) @@ -15,7 +16,6 @@ UXPiecewiseConstantFace, UXPiecewiseLinearNode, ) -from parcels import UxGrid @pytest.fixture diff --git a/tests/test_uxgrid.py b/tests/test_uxgrid.py index 758d540089..91d33b8f0d 100644 --- a/tests/test_uxgrid.py +++ b/tests/test_uxgrid.py @@ -1,7 +1,7 @@ import pytest -from parcels._datasets.unstructured.generic import datasets as uxdatasets from parcels import UxGrid +from parcels._datasets.unstructured.generic import datasets as uxdatasets @pytest.mark.parametrize("uxds", [pytest.param(uxds, id=key) for key, uxds in uxdatasets.items()]) diff --git a/tests/test_xgrid.py b/tests/test_xgrid.py index 1e3130fbba..caaf45b1a3 100644 --- a/tests/test_xgrid.py +++ b/tests/test_xgrid.py @@ -6,13 +6,13 @@ import xarray as xr from numpy.testing import assert_allclose -from parcels._datasets.structured.generic import X, Y, Z, datasets +from parcels._core.constants import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS +from parcels._core.utils.array import _search_1d_array from parcels._core.xgrid import ( XGrid, _transpose_xfield_data_to_tzyx, ) -from parcels._core.constants import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS -from parcels._core.utils.array import _search_1d_array +from parcels._datasets.structured.generic import X, Y, Z, datasets from tests import utils GridTestCase = namedtuple("GridTestCase", ["ds", "attr", "expected"]) diff --git a/tests/utils.py b/tests/utils.py index 6f30ea3f12..4653c27dc3 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -9,11 +9,10 @@ import xarray as xr import parcels +from parcels import Field, FieldSet, VectorField +from parcels._core.xgrid import _FIELD_DATA_ORDERING, XGrid, get_axis_from_dim_name from parcels._datasets.structured.generated import simple_UV_dataset -from parcels import Field, VectorField -from parcels import FieldSet from parcels.interpolators import XLinear -from parcels._core.xgrid import _FIELD_DATA_ORDERING, XGrid, get_axis_from_dim_name PROJECT_ROOT = Path(__file__).resolve().parents[1] TEST_ROOT = PROJECT_ROOT / "tests" From 97d6f6809c6861350e34e618f6cf2e3078f59847 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 14:33:14 +0200 Subject: [PATCH 41/45] Move decorators to parcels and remove wildcard import --- parcels/{utils => }/_decorators.py | 0 parcels/utils/__init__.py | 1 - tests-v3/tools/test_helpers.py | 2 +- 3 files changed, 1 insertion(+), 2 deletions(-) rename parcels/{utils => }/_decorators.py (100%) diff --git a/parcels/utils/_decorators.py b/parcels/_decorators.py similarity index 100% rename from parcels/utils/_decorators.py rename to parcels/_decorators.py diff --git a/parcels/utils/__init__.py b/parcels/utils/__init__.py index 592d28b9bc..e69de29bb2 100644 --- a/parcels/utils/__init__.py +++ b/parcels/utils/__init__.py @@ -1 +0,0 @@ -from .interpolation_utils import * diff --git a/tests-v3/tools/test_helpers.py b/tests-v3/tools/test_helpers.py index cce52ee3f5..580ee4b8c2 100644 --- a/tests-v3/tools/test_helpers.py +++ b/tests-v3/tools/test_helpers.py @@ -4,7 +4,7 @@ import pytest import parcels.utils._helpers as helpers -from parcels.utils._decorators import deprecated, deprecated_made_private +from parcels._decorators import deprecated, deprecated_made_private from parcels.utils._helpers import timedelta_to_float From 1404480f66ef45453b73b7be5614eadc26c235d3 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 14:37:18 +0200 Subject: [PATCH 42/45] Remove wildcard import --- parcels/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/parcels/__init__.py b/parcels/__init__.py index dcb2fab8a9..fa2e6db651 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -42,7 +42,6 @@ from parcels._core.xgrid import XGrid from parcels._logger import logger from parcels._tutorial import download_example_dataset, list_example_datasets -from parcels.utils import * _stdlib_warnings.warn( "This is an alpha version of Parcels v4. The API is not stable and may change without deprecation warnings.", From 5555237196f097a1a319a7616a0020704e306ecc Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 14:41:36 +0200 Subject: [PATCH 43/45] Currate package level __all__ --- parcels/__init__.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/parcels/__init__.py b/parcels/__init__.py index fa2e6db651..3eb58c2fb1 100644 --- a/parcels/__init__.py +++ b/parcels/__init__.py @@ -43,6 +43,47 @@ from parcels._logger import logger from parcels._tutorial import download_example_dataset, list_example_datasets +__all__ = [ # noqa: RUF022 + # Core classes + "BaseGrid", + "Field", + "VectorField", + "FieldSet", + "Kernel", + "Particle", + "ParticleClass", + "ParticleFile", + "ParticleSet", + "Variable", + "XGrid", + "UxGrid", + # Converters + "Geographic", + "GeographicPolar", + "GeographicPolarSquare", + "GeographicSquare", + "UnitConverter", + # Status codes and errors + "AllParcelsErrorCodes", + "FieldInterpolationError", + "FieldOutOfBoundError", + "FieldSamplingError", + "KernelError", + "StatusCode", + "TimeExtrapolationError", + # Warnings + "FieldSetWarning", + "FileWarning", + "KernelWarning", + "ParticleSetWarning", + # Utilities + "logger", + "download_example_dataset", + "list_example_datasets", + # (marked for potential removal) + "KernelParticle", +] + _stdlib_warnings.warn( "This is an alpha version of Parcels v4. The API is not stable and may change without deprecation warnings.", UserWarning, From 0d19fe26dfda884b3c9e8a1c0f12b0bd0d8ea0d8 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Sun, 28 Sep 2025 14:50:16 +0200 Subject: [PATCH 44/45] Revert accidental changes to parcels/interaction and tests-v3 Using `git checkout 7e7ff6af -- tests-v3/ parcels/interaction/` --- parcels/interaction/interactionkernel.py | 4 ++-- tests-v3/test_fieldset.py | 2 +- tests-v3/test_interaction.py | 14 +++++++------- tests-v3/test_kernel_language.py | 4 ++-- tests-v3/tools/test_exampledata_utils.py | 2 +- tests-v3/tools/test_helpers.py | 5 ++--- tests-v3/tools/test_warnings.py | 2 +- 7 files changed, 16 insertions(+), 17 deletions(-) diff --git a/parcels/interaction/interactionkernel.py b/parcels/interaction/interactionkernel.py index b423e1f23d..039297f5d6 100644 --- a/parcels/interaction/interactionkernel.py +++ b/parcels/interaction/interactionkernel.py @@ -5,9 +5,9 @@ import numpy as np from parcels._compat import MPI -from parcels._core.field import VectorField -from parcels._core.statuscodes import StatusCode +from parcels.field import VectorField from parcels.kernel import BaseKernel +from parcels.tools.statuscodes import StatusCode __all__ = ["InteractionKernel"] diff --git a/tests-v3/test_fieldset.py b/tests-v3/test_fieldset.py index 860f7e897e..fd83a28bef 100644 --- a/tests-v3/test_fieldset.py +++ b/tests-v3/test_fieldset.py @@ -13,7 +13,7 @@ Variable, ) from parcels.field import VectorField -from parcels.utils.converters import GeographicPolar, UnitConverter +from parcels.tools.converters import GeographicPolar, UnitConverter from tests.utils import TEST_DATA diff --git a/tests-v3/test_interaction.py b/tests-v3/test_interaction.py index 34b1a6af34..c20fdda881 100644 --- a/tests-v3/test_interaction.py +++ b/tests-v3/test_interaction.py @@ -2,7 +2,12 @@ import pytest from parcels import Field, FieldSet, ParticleSet -from parcels._core.particle import InteractionParticle, Variable +from parcels.application_kernels.advection import AdvectionRK4 +from parcels.application_kernels.interaction import ( + AsymmetricAttraction, + MergeWithNearestNeighbor, + NearestNeighborWithinRange, +) from parcels.interaction.neighborsearch import ( BruteFlatNeighborSearch, BruteSphericalNeighborSearch, @@ -11,12 +16,7 @@ KDTreeFlatNeighborSearch, ) from parcels.interaction.neighborsearch.basehash import BaseHashNeighborSearch -from parcels.kernels import AdvectionRK4 -from parcels.kernels.interaction import ( - AsymmetricAttraction, - MergeWithNearestNeighbor, - NearestNeighborWithinRange, -) +from parcels.particle import InteractionParticle, Variable from tests.common_kernels import DoNothing from tests.utils import create_fieldset_unit_mesh, create_flat_positions, create_spherical_positions diff --git a/tests-v3/test_kernel_language.py b/tests-v3/test_kernel_language.py index cbca1c2b74..76b3ad1ba0 100644 --- a/tests-v3/test_kernel_language.py +++ b/tests-v3/test_kernel_language.py @@ -12,13 +12,13 @@ ParticleSet, Variable, ) -from parcels.kernels import ( - PolyTEOS10_bsq, +from parcels.application_kernels.EOSseawaterproperties import ( PressureFromLatDepth, PtempFromTemp, TempFromPtemp, UNESCODensity, ) +from parcels.application_kernels.TEOSseawaterdensity import PolyTEOS10_bsq from tests.common_kernels import DoNothing from tests.utils import create_fieldset_unit_mesh diff --git a/tests-v3/tools/test_exampledata_utils.py b/tests-v3/tools/test_exampledata_utils.py index 3169a07c2e..94ed9cf833 100644 --- a/tests-v3/tools/test_exampledata_utils.py +++ b/tests-v3/tools/test_exampledata_utils.py @@ -1,7 +1,7 @@ import pytest import requests -from parcels._tutorial import ( +from parcels.tools.exampledata_utils import ( _get_pooch, download_example_dataset, list_example_datasets, diff --git a/tests-v3/tools/test_helpers.py b/tests-v3/tools/test_helpers.py index 580ee4b8c2..1403b679f0 100644 --- a/tests-v3/tools/test_helpers.py +++ b/tests-v3/tools/test_helpers.py @@ -3,9 +3,8 @@ import numpy as np import pytest -import parcels.utils._helpers as helpers -from parcels._decorators import deprecated, deprecated_made_private -from parcels.utils._helpers import timedelta_to_float +import parcels.tools._helpers as helpers +from parcels.tools._helpers import deprecated, deprecated_made_private, timedelta_to_float def test_format_list_items_multiline(): diff --git a/tests-v3/tools/test_warnings.py b/tests-v3/tools/test_warnings.py index 8ed1a207ee..1570d44bfa 100644 --- a/tests-v3/tools/test_warnings.py +++ b/tests-v3/tools/test_warnings.py @@ -8,10 +8,10 @@ FieldSetWarning, KernelWarning, Particle, - ParticleFile, ParticleSet, ParticleSetWarning, ) +from parcels.particlefile import ParticleFile from tests.utils import TEST_DATA From 825356abc6594faa1df2b6a4cbfa403f773f2808 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Mon, 29 Sep 2025 09:47:05 +0200 Subject: [PATCH 45/45] review feedback --- parcels/_core/constants.py | 3 --- parcels/_core/field.py | 3 +-- parcels/_core/index_search.py | 47 ++++++++++++++++++++++++++++++++++ parcels/_core/utils/array.py | 48 ----------------------------------- parcels/_core/uxgrid.py | 3 +-- parcels/_core/xgrid.py | 3 +-- tests/test_xgrid.py | 3 +-- 7 files changed, 51 insertions(+), 59 deletions(-) delete mode 100644 parcels/_core/utils/array.py diff --git a/parcels/_core/constants.py b/parcels/_core/constants.py index 411373170c..e69de29bb2 100644 --- a/parcels/_core/constants.py +++ b/parcels/_core/constants.py @@ -1,3 +0,0 @@ -# Used in the searching of 1D arrays for time and space -LEFT_OUT_OF_BOUNDS = -2 -RIGHT_OUT_OF_BOUNDS = -1 diff --git a/parcels/_core/field.py b/parcels/_core/field.py index 01190c2168..d582e5b3c6 100644 --- a/parcels/_core/field.py +++ b/parcels/_core/field.py @@ -8,12 +8,11 @@ import uxarray as ux import xarray as xr -from parcels._core.constants import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS from parcels._core.converters import ( UnitConverter, _unitconverters_map, ) -from parcels._core.index_search import GRID_SEARCH_ERROR, _search_time_index +from parcels._core.index_search import GRID_SEARCH_ERROR, LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS, _search_time_index from parcels._core.particle import KernelParticle from parcels._core.statuscodes import ( AllParcelsErrorCodes, diff --git a/parcels/_core/index_search.py b/parcels/_core/index_search.py index 5c210985d7..64689f49de 100644 --- a/parcels/_core/index_search.py +++ b/parcels/_core/index_search.py @@ -13,6 +13,53 @@ GRID_SEARCH_ERROR = -3 +LEFT_OUT_OF_BOUNDS = -2 +RIGHT_OUT_OF_BOUNDS = -1 + + +def _search_1d_array( + arr: np.array, + x: float, +) -> tuple[int, int]: + """ + Searches for particle locations in a 1D array and returns barycentric coordinate along dimension. + + Assumptions: + - array is strictly monotonically increasing. + + Parameters + ---------- + arr : np.array + 1D array to search in. + x : float + Position in the 1D array to search for. + + Returns + ------- + array of int + Index of the element just before the position x in the array. Note that this index is -2 if the index is left out of bounds and -1 if the index is right out of bounds. + array of float + Barycentric coordinate. + """ + # TODO v4: We probably rework this to deal with 0D arrays before this point (as we already know field dimensionality) + if len(arr) < 2: + return np.zeros(shape=x.shape, dtype=np.int32), np.zeros_like(x) + index = np.searchsorted(arr, x, side="right") - 1 + # Use broadcasting to avoid repeated array access + arr_index = arr[index] + arr_next = arr[np.clip(index + 1, 1, len(arr) - 1)] # Ensure we don't go out of bounds + bcoord = (x - arr_index) / (arr_next - arr_index) + + # TODO check how we can avoid searchsorted when grid spacing is uniform + # dx = arr[1] - arr[0] + # index = ((x - arr[0]) / dx).astype(int) + # index = np.clip(index, 0, len(arr) - 2) + # bcoord = (x - arr[index]) / dx + + index = np.where(x < arr[0], LEFT_OUT_OF_BOUNDS, index) + index = np.where(x >= arr[-1], RIGHT_OUT_OF_BOUNDS, index) + + return np.atleast_1d(index), np.atleast_1d(bcoord) def _search_time_index(field: Field, time: datetime): diff --git a/parcels/_core/utils/array.py b/parcels/_core/utils/array.py deleted file mode 100644 index 59a2f24aad..0000000000 --- a/parcels/_core/utils/array.py +++ /dev/null @@ -1,48 +0,0 @@ -import numpy as np - -from parcels._core.constants import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS - - -def _search_1d_array( - arr: np.array, - x: float, -) -> tuple[int, int]: - """ - Searches for particle locations in a 1D array and returns barycentric coordinate along dimension. - - Assumptions: - - array is strictly monotonically increasing. - - Parameters - ---------- - arr : np.array - 1D array to search in. - x : float - Position in the 1D array to search for. - - Returns - ------- - array of int - Index of the element just before the position x in the array. Note that this index is -2 if the index is left out of bounds and -1 if the index is right out of bounds. - array of float - Barycentric coordinate. - """ - # TODO v4: We probably rework this to deal with 0D arrays before this point (as we already know field dimensionality) - if len(arr) < 2: - return np.zeros(shape=x.shape, dtype=np.int32), np.zeros_like(x) - index = np.searchsorted(arr, x, side="right") - 1 - # Use broadcasting to avoid repeated array access - arr_index = arr[index] - arr_next = arr[np.clip(index + 1, 1, len(arr) - 1)] # Ensure we don't go out of bounds - bcoord = (x - arr_index) / (arr_next - arr_index) - - # TODO check how we can avoid searchsorted when grid spacing is uniform - # dx = arr[1] - arr[0] - # index = ((x - arr[0]) / dx).astype(int) - # index = np.clip(index, 0, len(arr) - 2) - # bcoord = (x - arr[index]) / dx - - index = np.where(x < arr[0], LEFT_OUT_OF_BOUNDS, index) - index = np.where(x >= arr[-1], RIGHT_OUT_OF_BOUNDS, index) - - return np.atleast_1d(index), np.atleast_1d(bcoord) diff --git a/parcels/_core/uxgrid.py b/parcels/_core/uxgrid.py index 3c56573e1f..11da6daffa 100644 --- a/parcels/_core/uxgrid.py +++ b/parcels/_core/uxgrid.py @@ -6,8 +6,7 @@ import uxarray as ux from parcels._core.basegrid import BaseGrid -from parcels._core.index_search import GRID_SEARCH_ERROR, uxgrid_point_in_cell -from parcels._core.utils.array import _search_1d_array +from parcels._core.index_search import GRID_SEARCH_ERROR, _search_1d_array, uxgrid_point_in_cell from parcels._typing import assert_valid_mesh _UXGRID_AXES = Literal["Z", "FACE"] diff --git a/parcels/_core/xgrid.py b/parcels/_core/xgrid.py index 583e73b850..d20d53f8b3 100644 --- a/parcels/_core/xgrid.py +++ b/parcels/_core/xgrid.py @@ -8,8 +8,7 @@ import xgcm from parcels._core.basegrid import BaseGrid -from parcels._core.index_search import _search_indices_curvilinear_2d -from parcels._core.utils.array import _search_1d_array +from parcels._core.index_search import _search_1d_array, _search_indices_curvilinear_2d from parcels._typing import assert_valid_mesh _XGRID_AXES = Literal["X", "Y", "Z"] diff --git a/tests/test_xgrid.py b/tests/test_xgrid.py index caaf45b1a3..d93e4689ad 100644 --- a/tests/test_xgrid.py +++ b/tests/test_xgrid.py @@ -6,8 +6,7 @@ import xarray as xr from numpy.testing import assert_allclose -from parcels._core.constants import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS -from parcels._core.utils.array import _search_1d_array +from parcels._core.index_search import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS, _search_1d_array from parcels._core.xgrid import ( XGrid, _transpose_xfield_data_to_tzyx,