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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions docs/examples/tutorial_kernelloop.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@
" \"V\": \"northward_eulerian_current_velocity\",\n",
"}\n",
"dimensions = {\"lat\": \"lat\", \"lon\": \"lon\", \"time\": \"time\"}\n",
"fieldset = parcels.FieldSet.from_netcdf(filenames, variables, dimensions)\n",
"fieldset = parcels.FieldSet.from_netcdf(\n",
" filenames, variables, dimensions, allow_time_extrapolation=True\n",
")\n",
"# uppermost layer in the hydrodynamic data\n",
"fieldset.mindepth = fieldset.U.depth[0]"
]
Expand All @@ -137,11 +139,15 @@
" lon=fieldset.U.lon,\n",
" lat=fieldset.U.lat,\n",
" mesh=\"spherical\",\n",
" fieldtype=\"U\",\n",
")\n",
"VWind = parcels.Field(\n",
" \"VWind\", np.zeros((ydim, xdim), dtype=np.float32), grid=UWind.grid, fieldtype=\"V\"\n",
" \"VWind\",\n",
" np.zeros((ydim, xdim), dtype=np.float32),\n",
" grid=UWind.grid,\n",
")\n",
"UWind.units = parcels.tools.converters.GeographicPolar()\n",
"VWind.units = parcels.tools.converters.Geographic()\n",
"\n",
"fieldset_wind = parcels.FieldSet(UWind, VWind)\n",
"\n",
"fieldset.add_field(fieldset_wind.U, name=\"UWind\")\n",
Expand Down
25 changes: 0 additions & 25 deletions docs/examples/tutorial_unitconverters.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -326,31 +326,6 @@
"print(fieldset.Ustokes[0, 0, 40, -5])\n",
"print(fieldset.Ustokes[0, 0, 40, -5] * 1852 * 60 * np.cos(40 * np.pi / 180))"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Alternatively, the UnitConverter can be set when the `FieldSet` or `Field` is created by using the `fieldtype` argument (use a dictionary in the case of `FieldSet` construction.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fieldset.add_field(\n",
" parcels.Field(\n",
" \"Ustokes2\",\n",
" np.ones((ydim, xdim), dtype=np.float32),\n",
" grid=fieldset.U.grid,\n",
" fieldtype=\"U\",\n",
" )\n",
")\n",
"print(fieldset.Ustokes2[0, 0, 40, -5])"
]
}
],
"metadata": {
Expand Down
26 changes: 16 additions & 10 deletions parcels/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,6 @@
grid : parcels.grid.Grid
:class:`parcels.grid.Grid` object containing all the lon, lat depth, time
mesh and time_origin information. Can be constructed from any of the Grid objects
fieldtype : str
Type of Field to be used for UnitConverter (either 'U', 'V', 'Kh_zonal', 'Kh_meridional' or None)
time_origin : parcels.tools.converters.TimeConverter
Time origin of the time axis (only if grid is None)
interp_method : str
Expand All @@ -148,7 +146,6 @@
time=None,
grid=None,
mesh: Mesh = "flat",
fieldtype=None,
time_origin: TimeConverter | None = None,
interp_method: InterpMethod = "linear",
allow_time_extrapolation: bool | None = None,
Expand All @@ -170,13 +167,12 @@
time_origin = TimeConverter(0)
self._grid = Grid.create_grid(lon, lat, depth, time, time_origin=time_origin, mesh=mesh)
self.igrid = -1
self.fieldtype = self.name if fieldtype is None else fieldtype
if self.grid.mesh == "flat" or (self.fieldtype not in unitconverters_map.keys()):
self.units = UnitConverter()
elif self.grid.mesh == "spherical":
self.units = unitconverters_map[self.fieldtype]
else:
raise ValueError("Unsupported mesh type. Choose either: 'spherical' or 'flat'")
self.units = UnitConverter()
if self.grid.mesh == "spherical":
try:
self.units = unitconverters_map[self.name]
except KeyError:
pass
if isinstance(interp_method, dict):
if self.name in interp_method:
self.interp_method = interp_method[self.name]
Expand Down Expand Up @@ -216,6 +212,16 @@
def __repr__(self) -> str:
return field_repr(self)

@property
def units(self):
return self._units

@units.setter
def units(self, value):
if not isinstance(value, UnitConverter):
raise ValueError(f"Units must be a UnitConverter object, got {type(value)}")

Check warning on line 222 in parcels/field.py

View check run for this annotation

Codecov / codecov/patch

parcels/field.py#L222

Added line #L222 was not covered by tests
self._units = value

@property
def grid(self):
return self._grid
Expand Down
21 changes: 0 additions & 21 deletions parcels/fieldset.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,6 @@ def from_netcdf(
filenames,
variables,
dimensions,
fieldtype=None,
mesh: Mesh = "spherical",
allow_time_extrapolation: bool | None = None,
**kwargs,
Expand All @@ -305,9 +304,6 @@ def from_netcdf(
Note that dimensions can also be a dictionary of dictionaries if
dimension names are different for each variable
(e.g. dimensions['U'], dimensions['V'], etc).
fieldtype :
Optional dictionary mapping fields to fieldtypes to be used for UnitConverter.
(either 'U', 'V', 'Kh_zonal', 'Kh_meridional' or None) (Default value = None)
mesh : str
String indicating the type of mesh coordinates and
units used during velocity interpolation, see also `this tutorial <../examples/tutorial_unitconverters.ipynb>`__:
Expand Down Expand Up @@ -353,7 +349,6 @@ def from_netcdf(
# Use dimensions[var] if it's a dict of dicts
dims = dimensions[var] if var in dimensions else dimensions
cls.checkvaliddimensionsdict(dims)
fieldtype = fieldtype[var] if (fieldtype and var in fieldtype) else fieldtype

grid = None

Expand All @@ -364,7 +359,6 @@ def from_netcdf(
grid=grid,
mesh=mesh,
allow_time_extrapolation=allow_time_extrapolation,
fieldtype=fieldtype,
**kwargs,
)

Expand Down Expand Up @@ -426,9 +420,6 @@ def from_nemo(
(for indexing details: https://www.nemo-ocean.eu/doc/img360.png )
In 3D, the depth is the one corresponding to W nodes
The gridindexingtype is set to 'nemo'. See also the Grid indexing documentation on oceanparcels.org
fieldtype :
Optional dictionary mapping fields to fieldtypes to be used for UnitConverter.
(either 'U', 'V', 'Kh_zonal', 'Kh_meridional' or None)
mesh : str
String indicating the type of mesh coordinates and
units used during velocity interpolation, see also `this tutorial <../examples/tutorial_unitconverters.ipynb>`__:
Expand Down Expand Up @@ -635,9 +626,6 @@ def from_c_grid_dataset(
which are located on the corners of the cells.
(for indexing details: https://www.nemo-ocean.eu/doc/img360.png )
In 3D, the depth is the one corresponding to W nodes.
fieldtype :
Optional dictionary mapping fields to fieldtypes to be used for UnitConverter.
(either 'U', 'V', 'Kh_zonal', 'Kh_meridional' or None)
mesh : str
String indicating the type of mesh coordinates and
units used during velocity interpolation, see also `this tutorial <../examples/tutorial_unitconverters.ipynb>`__:
Expand Down Expand Up @@ -738,9 +726,6 @@ def from_mom5(
Note that W is normally directed upward in MOM5, but Parcels requires W
in the positive z-direction (downward) so W is multiplied by -1.
T node is at the cell centre, and constant per cell.
fieldtype :
Optional dictionary mapping fields to fieldtypes to be used for UnitConverter.
(either 'U', 'V', 'Kh_zonal', 'Kh_meridional' or None)
mesh : str
String indicating the type of mesh coordinates and
units used during velocity interpolation, see also the `Unit converters tutorial <../examples/tutorial_unitconverters.ipynb>`__:
Expand Down Expand Up @@ -841,9 +826,6 @@ def from_b_grid_dataset(
W nodes are at the centre of the horizontal interfaces.
They are interpolated linearly (as a function of z) in the cell.
T node is at the cell centre, and constant per cell.
fieldtype :
Optional dictionary mapping fields to fieldtypes to be used for UnitConverter.
(either 'U', 'V', 'Kh_zonal', 'Kh_meridional' or None)
mesh : str
String indicating the type of mesh coordinates and
units used during velocity interpolation, see also `this tutorial <../examples/tutorial_unitconverters.ipynb>`__:
Expand Down Expand Up @@ -908,9 +890,6 @@ def from_xarray_dataset(cls, ds, variables, dimensions, mesh="spherical", allow_
Note that dimensions can also be a dictionary of dictionaries if
dimension names are different for each variable
(e.g. dimensions['U'], dimensions['V'], etc).
fieldtype :
Optional dictionary mapping fields to fieldtypes to be used for UnitConverter.
(either 'U', 'V', 'Kh_zonal', 'Kh_meridional' or None)
mesh : str
String indicating the type of mesh coordinates and
units used during velocity interpolation, see also `this tutorial <../examples/tutorial_unitconverters.ipynb>`__:
Expand Down
37 changes: 4 additions & 33 deletions tests/test_fieldset.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@
Variable,
)
from parcels.field import Field, VectorField
from parcels.tools.converters import (
GeographicPolar,
UnitConverter,
)
from tests.utils import TEST_DATA


Expand Down Expand Up @@ -161,31 +157,6 @@ def test_fieldset_from_modulefile():
FieldSet.from_modulefile(nemo_error_fname, modulename="none_returning_function")


def test_field_from_netcdf_fieldtypes():
filenames = {
"varU": {
"lon": str(TEST_DATA / "mask_nemo_cross_180lon.nc"),
"lat": str(TEST_DATA / "mask_nemo_cross_180lon.nc"),
"data": str(TEST_DATA / "Uu_eastward_nemo_cross_180lon.nc"),
},
"varV": {
"lon": str(TEST_DATA / "mask_nemo_cross_180lon.nc"),
"lat": str(TEST_DATA / "mask_nemo_cross_180lon.nc"),
"data": str(TEST_DATA / "Vv_eastward_nemo_cross_180lon.nc"),
},
}
variables = {"varU": "U", "varV": "V"}
dimensions = {"lon": "glamf", "lat": "gphif"}

# first try without setting fieldtype
fset = FieldSet.from_nemo(filenames, variables, dimensions)
assert isinstance(fset.varU.units, UnitConverter)

# now try with setting fieldtype
fset = FieldSet.from_nemo(filenames, variables, dimensions, fieldtype={"varU": "U", "varV": "V"})
assert isinstance(fset.varU.units, GeographicPolar)


def test_fieldset_from_agrid_dataset():
filenames = {
"lon": str(TEST_DATA / "mask_nemo_cross_180lon.nc"),
Expand Down Expand Up @@ -250,18 +221,18 @@ def test_add_duplicate_field(dupobject):
fieldset.add_field(field2)


@pytest.mark.parametrize("fieldtype", ["normal", "vector"])
def test_add_field_after_pset(fieldtype):
@pytest.mark.parametrize("field_type", ["normal", "vector"])
def test_add_field_after_pset(field_type):
data, dimensions = generate_fieldset_data(100, 100)
fieldset = FieldSet.from_data(data, dimensions)
pset = ParticleSet(fieldset, Particle, lon=0, lat=0) # noqa ; to trigger fieldset._check_complete
field1 = Field("field1", fieldset.U.data, lon=fieldset.U.lon, lat=fieldset.U.lat)
field2 = Field("field2", fieldset.U.data, lon=fieldset.U.lon, lat=fieldset.U.lat)
vfield = VectorField("vfield", field1, field2)
with pytest.raises(RuntimeError):
if fieldtype == "normal":
if field_type == "normal":
fieldset.add_field(field1)
elif fieldtype == "vector":
elif field_type == "vector":
fieldset.add_vector_field(vfield)


Expand Down
Loading