Skip to content

Commit 5ccc0bc

Browse files
Package restructure (#2247)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 685a582 commit 5ccc0bc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+2047
-1914
lines changed

parcels/__init__.py

Lines changed: 81 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,89 @@
22

33
__version__ = version
44

5-
import warnings as _warnings
5+
import warnings as _stdlib_warnings
66

7-
from parcels.application_kernels import *
8-
from parcels.field import *
9-
from parcels.fieldset import *
10-
from parcels.interaction import *
11-
from parcels.kernel import *
12-
from parcels.particle import *
13-
from parcels.particlefile import *
14-
from parcels.particleset import *
15-
from parcels.tools import *
7+
from parcels._core.basegrid import BaseGrid
8+
from parcels._core.converters import (
9+
Geographic,
10+
GeographicPolar,
11+
GeographicPolarSquare,
12+
GeographicSquare,
13+
UnitConverter,
14+
)
15+
from parcels._core.field import Field, VectorField
16+
from parcels._core.fieldset import FieldSet
17+
from parcels._core.kernel import Kernel
18+
from parcels._core.particle import (
19+
KernelParticle, # ? remove?
20+
Particle,
21+
ParticleClass,
22+
Variable,
23+
)
24+
from parcels._core.particlefile import ParticleFile
25+
from parcels._core.particleset import ParticleSet
26+
from parcels._core.statuscodes import (
27+
AllParcelsErrorCodes,
28+
FieldInterpolationError,
29+
FieldOutOfBoundError,
30+
FieldSamplingError,
31+
KernelError,
32+
StatusCode,
33+
TimeExtrapolationError,
34+
)
35+
from parcels._core.uxgrid import UxGrid
36+
from parcels._core.warnings import (
37+
FieldSetWarning,
38+
FileWarning,
39+
KernelWarning,
40+
ParticleSetWarning,
41+
)
42+
from parcels._core.xgrid import XGrid
43+
from parcels._logger import logger
44+
from parcels._tutorial import download_example_dataset, list_example_datasets
45+
46+
__all__ = [ # noqa: RUF022
47+
# Core classes
48+
"BaseGrid",
49+
"Field",
50+
"VectorField",
51+
"FieldSet",
52+
"Kernel",
53+
"Particle",
54+
"ParticleClass",
55+
"ParticleFile",
56+
"ParticleSet",
57+
"Variable",
58+
"XGrid",
59+
"UxGrid",
60+
# Converters
61+
"Geographic",
62+
"GeographicPolar",
63+
"GeographicPolarSquare",
64+
"GeographicSquare",
65+
"UnitConverter",
66+
# Status codes and errors
67+
"AllParcelsErrorCodes",
68+
"FieldInterpolationError",
69+
"FieldOutOfBoundError",
70+
"FieldSamplingError",
71+
"KernelError",
72+
"StatusCode",
73+
"TimeExtrapolationError",
74+
# Warnings
75+
"FieldSetWarning",
76+
"FileWarning",
77+
"KernelWarning",
78+
"ParticleSetWarning",
79+
# Utilities
80+
"logger",
81+
"download_example_dataset",
82+
"list_example_datasets",
83+
# (marked for potential removal)
84+
"KernelParticle",
85+
]
1686

17-
_warnings.warn(
87+
_stdlib_warnings.warn(
1888
"This is an alpha version of Parcels v4. The API is not stable and may change without deprecation warnings.",
1989
UserWarning,
2090
stacklevel=2,
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import numpy as np
88

9-
from parcels.spatialhash import SpatialHash
9+
from parcels._core.spatialhash import SpatialHash
1010

1111
if TYPE_CHECKING:
1212
import numpy as np
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
"GeographicPolarSquare",
1212
"GeographicSquare",
1313
"UnitConverter",
14-
"convert_to_flat_array",
15-
"unitconverters_map",
14+
"_convert_to_flat_array",
15+
"_unitconverters_map",
1616
]
1717

1818

19-
def convert_to_flat_array(var: npt.ArrayLike) -> npt.NDArray:
19+
def _convert_to_flat_array(var: npt.ArrayLike) -> npt.NDArray:
2020
"""Convert lists and single integers/floats to one-dimensional numpy arrays
2121
2222
Parameters
@@ -96,7 +96,7 @@ def to_source(self, value, z, y, x):
9696
return value * pow(1000.0 * 1.852 * 60.0 * np.cos(y * pi / 180), 2)
9797

9898

99-
unitconverters_map = {
99+
_unitconverters_map = {
100100
"U": GeographicPolar(),
101101
"V": Geographic(),
102102
"Kh_zonal": GeographicPolarSquare(),
Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,28 @@
88
import uxarray as ux
99
import xarray as xr
1010

11+
from parcels._core.converters import (
12+
UnitConverter,
13+
_unitconverters_map,
14+
)
15+
from parcels._core.index_search import GRID_SEARCH_ERROR, LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS, _search_time_index
16+
from parcels._core.particle import KernelParticle
17+
from parcels._core.statuscodes import (
18+
AllParcelsErrorCodes,
19+
StatusCode,
20+
)
1121
from parcels._core.utils.time import TimeInterval
22+
from parcels._core.uxgrid import UxGrid
23+
from parcels._core.xgrid import XGrid, _transpose_xfield_data_to_tzyx
1224
from parcels._reprs import default_repr
1325
from parcels._typing import VectorType
14-
from parcels.application_kernels.interpolation import (
26+
from parcels.interpolators import (
1527
UXPiecewiseLinearNode,
1628
XLinear,
1729
ZeroInterpolator,
1830
ZeroInterpolator_Vector,
1931
)
20-
from parcels.particle import KernelParticle
21-
from parcels.tools._helpers import _assert_same_function_signature
22-
from parcels.tools.converters import (
23-
UnitConverter,
24-
unitconverters_map,
25-
)
26-
from parcels.tools.statuscodes import (
27-
AllParcelsErrorCodes,
28-
StatusCode,
29-
)
30-
from parcels.uxgrid import UxGrid
31-
from parcels.xgrid import LEFT_OUT_OF_BOUNDS, RIGHT_OUT_OF_BOUNDS, XGrid, _transpose_xfield_data_to_tzyx
32-
33-
from ._index_search import GRID_SEARCH_ERROR, _search_time_index
32+
from parcels.utils._helpers import _assert_same_function_signature
3433

3534
__all__ = ["Field", "VectorField"]
3635

@@ -143,10 +142,10 @@ def __init__(
143142

144143
self.igrid = -1 # Default the grid index to -1
145144

146-
if self.grid._mesh == "flat" or (self.name not in unitconverters_map.keys()):
145+
if self.grid._mesh == "flat" or (self.name not in _unitconverters_map.keys()):
147146
self.units = UnitConverter()
148147
elif self.grid._mesh == "spherical":
149-
self.units = unitconverters_map[self.name]
148+
self.units = _unitconverters_map[self.name]
150149

151150
if self.data.shape[0] > 1:
152151
if "time" not in self.data.coords:
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@
99
import xarray as xr
1010
import xgcm
1111

12+
from parcels._core.converters import Geographic, GeographicPolar
13+
from parcels._core.field import Field, VectorField
1214
from parcels._core.utils.time import get_datetime_type_calendar
1315
from parcels._core.utils.time import is_compatible as datetime_is_compatible
16+
from parcels._core.xgrid import _DEFAULT_XGCM_KWARGS, XGrid
17+
from parcels._logger import logger
1418
from parcels._typing import Mesh
15-
from parcels.field import Field, VectorField
16-
from parcels.tools.converters import Geographic, GeographicPolar
17-
from parcels.tools.loggers import logger
18-
from parcels.xgrid import _DEFAULT_XGCM_KWARGS, XGrid
1919

2020
if TYPE_CHECKING:
21+
from parcels._core.basegrid import BaseGrid
2122
from parcels._typing import TimeLike
22-
from parcels.basegrid import BaseGrid
2323
__all__ = ["FieldSet"]
2424

2525

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,61 @@
55

66
import numpy as np
77

8-
from parcels.tools.statuscodes import _raise_time_extrapolation_error
8+
from parcels._core.statuscodes import _raise_time_extrapolation_error
99

1010
if TYPE_CHECKING:
11+
from parcels._core.field import Field
1112
from parcels.xgrid import XGrid
1213

13-
from .field import Field
14-
1514

1615
GRID_SEARCH_ERROR = -3
16+
LEFT_OUT_OF_BOUNDS = -2
17+
RIGHT_OUT_OF_BOUNDS = -1
18+
19+
20+
def _search_1d_array(
21+
arr: np.array,
22+
x: float,
23+
) -> tuple[int, int]:
24+
"""
25+
Searches for particle locations in a 1D array and returns barycentric coordinate along dimension.
26+
27+
Assumptions:
28+
- array is strictly monotonically increasing.
29+
30+
Parameters
31+
----------
32+
arr : np.array
33+
1D array to search in.
34+
x : float
35+
Position in the 1D array to search for.
36+
37+
Returns
38+
-------
39+
array of int
40+
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.
41+
array of float
42+
Barycentric coordinate.
43+
"""
44+
# TODO v4: We probably rework this to deal with 0D arrays before this point (as we already know field dimensionality)
45+
if len(arr) < 2:
46+
return np.zeros(shape=x.shape, dtype=np.int32), np.zeros_like(x)
47+
index = np.searchsorted(arr, x, side="right") - 1
48+
# Use broadcasting to avoid repeated array access
49+
arr_index = arr[index]
50+
arr_next = arr[np.clip(index + 1, 1, len(arr) - 1)] # Ensure we don't go out of bounds
51+
bcoord = (x - arr_index) / (arr_next - arr_index)
52+
53+
# TODO check how we can avoid searchsorted when grid spacing is uniform
54+
# dx = arr[1] - arr[0]
55+
# index = ((x - arr[0]) / dx).astype(int)
56+
# index = np.clip(index, 0, len(arr) - 2)
57+
# bcoord = (x - arr[index]) / dx
58+
59+
index = np.where(x < arr[0], LEFT_OUT_OF_BOUNDS, index)
60+
index = np.where(x >= arr[-1], RIGHT_OUT_OF_BOUNDS, index)
61+
62+
return np.atleast_1d(index), np.atleast_1d(bcoord)
1763

1864

1965
def _search_time_index(field: Field, time: datetime):
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,8 @@
88

99
import numpy as np
1010

11-
from parcels.application_kernels.advection import (
12-
AdvectionAnalytical,
13-
AdvectionRK4,
14-
AdvectionRK45,
15-
)
16-
from parcels.basegrid import GridType
17-
from parcels.tools._helpers import _assert_same_function_signature
18-
from parcels.tools.statuscodes import (
11+
from parcels._core.basegrid import GridType
12+
from parcels._core.statuscodes import (
1913
StatusCode,
2014
_raise_field_interpolation_error,
2115
_raise_field_out_of_bound_error,
@@ -24,7 +18,13 @@
2418
_raise_grid_searching_error,
2519
_raise_time_extrapolation_error,
2620
)
27-
from parcels.tools.warnings import KernelWarning
21+
from parcels._core.warnings import KernelWarning
22+
from parcels.kernels import (
23+
AdvectionAnalytical,
24+
AdvectionRK4,
25+
AdvectionRK45,
26+
)
27+
from parcels.utils._helpers import _assert_same_function_signature
2828

2929
if TYPE_CHECKING:
3030
from collections.abc import Callable
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
import numpy as np
99

1010
from parcels._compat import _attrgetter_helper
11+
from parcels._core.statuscodes import StatusCode
1112
from parcels._core.utils.time import TimeInterval
1213
from parcels._reprs import _format_list_items_multiline
13-
from parcels.tools.statuscodes import StatusCode
1414

1515
__all__ = ["KernelParticle", "Particle", "ParticleClass", "Variable"]
1616
_TO_WRITE_OPTIONS = [True, False, "once"]
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@
1414
from zarr.storage import DirectoryStore
1515

1616
import parcels
17-
from parcels.particle import _SAME_AS_FIELDSET_TIME_INTERVAL, ParticleClass
18-
from parcels.tools._helpers import timedelta_to_float
17+
from parcels._core.particle import _SAME_AS_FIELDSET_TIME_INTERVAL, ParticleClass
18+
from parcels.utils._helpers import timedelta_to_float
1919

2020
if TYPE_CHECKING:
21+
from parcels._core.particle import Variable
22+
from parcels._core.particleset import ParticleSet
2123
from parcels._core.utils.time import TimeInterval
22-
from parcels.particle import Variable
23-
from parcels.particleset import ParticleSet
2424

2525
__all__ = ["ParticleFile"]
2626

0 commit comments

Comments
 (0)