diff --git a/.github/workflows/pypi-release.yml b/.github/workflows/pypi-release.yml index ef7440bc63..1b4bd922cf 100644 --- a/.github/workflows/pypi-release.yml +++ b/.github/workflows/pypi-release.yml @@ -90,10 +90,6 @@ jobs: path: dist - name: Publish package to PyPI uses: pypa/gh-action-pypi-publish@v1.12.4 - with: - user: __token__ - password: ${{ secrets.PARCELS_PYPI_PROD_TOKEN }} - verbose: true test-pypi-release: needs: upload-to-pypi diff --git a/README.md b/README.md index 5b9239134d..12f96e6f42 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ [![Anaconda-release](https://anaconda.org/conda-forge/parcels/badges/version.svg)](https://anaconda.org/conda-forge/parcels/) [![Anaconda-date](https://anaconda.org/conda-forge/parcels/badges/latest_release_date.svg)](https://anaconda.org/conda-forge/parcels/) [![Zenodo](https://zenodo.org/badge/DOI/10.5281/zenodo.823561.svg)](https://doi.org/10.5281/zenodo.823561) -[![Code style: Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/format.json)](https://github.com/astral-sh/ruff) +[![Xarray](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/pydata/xarray/refs/heads/main/doc/badge.json)](https://xarray.dev) +[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![unit-tests](https://github.com/OceanParcels/parcels/actions/workflows/ci.yml/badge.svg)](https://github.com/OceanParcels/parcels/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/OceanParcels/parcels/branch/main/graph/badge.svg)](https://codecov.io/gh/OceanParcels/parcels) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/5353/badge)](https://bestpractices.coreinfrastructure.org/projects/5353) diff --git a/tests/test_data/create_testfields.py b/tests/test_data/create_testfields.py deleted file mode 100644 index d59304939b..0000000000 --- a/tests/test_data/create_testfields.py +++ /dev/null @@ -1,132 +0,0 @@ -import math - -import numpy as np - -from parcels import FieldSet, GridType - -try: - from pympler import asizeof -except: - asizeof = None - -import os - -import xarray as xr - -try: - from parcels.tools import perlin2d as PERLIN -except: - PERLIN = None -noctaves = 4 -perlinres = (32, 8) -shapescale = (1, 1) -perlin_persistence = 0.3 -scalefac = 2.0 - - -def generate_testfieldset(xdim, ydim, zdim, tdim): - lon = np.linspace(0.0, 2.0, xdim, dtype=np.float32) - lat = np.linspace(0.0, 1.0, ydim, dtype=np.float32) - depth = np.linspace(0.0, 0.5, zdim, dtype=np.float32) - time = np.linspace(0.0, tdim, tdim, dtype=np.float64) - U = np.ones((tdim, zdim, ydim, xdim), dtype=np.float32) - V = np.zeros((tdim, zdim, ydim, xdim), dtype=np.float32) - P = 2.0 * np.ones((tdim, zdim, ydim, xdim), dtype=np.float32) - data = {"U": U, "V": V, "P": P} - dimensions = {"lon": lon, "lat": lat, "depth": depth, "time": time} - fieldset = FieldSet.from_data(data, dimensions, mesh="flat") - fieldset.write("testfields") - - -def generate_perlin_testfield(): - img_shape = ( - int(math.pow(2, noctaves)) * perlinres[0] * shapescale[0], - int(math.pow(2, noctaves)) * perlinres[1] * shapescale[1], - ) - - # Coordinates of the test fieldset (on A-grid in deg) - lon = np.linspace(-180.0, 180.0, img_shape[0], dtype=np.float32) - lat = np.linspace(-90.0, 90.0, img_shape[1], dtype=np.float32) - time = np.zeros(1, dtype=np.float64) - - # Define arrays U (zonal), V (meridional), W (vertical) and P (sea - # surface height) all on A-grid - if PERLIN is not None: - U = PERLIN.generate_fractal_noise_2d(img_shape, perlinres, noctaves, perlin_persistence) * scalefac - V = PERLIN.generate_fractal_noise_2d(img_shape, perlinres, noctaves, perlin_persistence) * scalefac - else: - U = np.ones(img_shape, dtype=np.float32) * scalefac - V = np.ones(img_shape, dtype=np.float32) * scalefac - U = np.transpose(U, (1, 0)) - U = np.expand_dims(U, 0) - V = np.transpose(V, (1, 0)) - V = np.expand_dims(V, 0) - data = {"U": U, "V": V} - dimensions = {"time": time, "lon": lon, "lat": lat} - if asizeof is not None: - print(f"Perlin U-field requires {U.size * U.itemsize} bytes of memory.") - print(f"Perlin V-field requires {V.size * V.itemsize} bytes of memory.") - fieldset = FieldSet.from_data(data, dimensions, mesh="spherical") - # fieldset.write("perlinfields") # can also be used, but then has a ghost depth dimension - write_simple_2Dt(fieldset.U, os.path.join(os.path.dirname(__file__), "perlinfields"), varname="vozocrtx") - write_simple_2Dt(fieldset.V, os.path.join(os.path.dirname(__file__), "perlinfields"), varname="vomecrty") - - -def write_simple_2Dt(field, filename, varname=None): - """Write a :class:`Field` to a netcdf file - - Parameters - ---------- - field : parcels.field.Field - Field to write to file - filename : str - Base name of the file to write to - varname : str, optional - Name of the variable to write to file. If None, defaults to field.name - """ - filepath = str(f"{filename}{field.name}.nc") - if varname is None: - varname = field.name - - # Create DataArray objects for file I/O - if field.grid._gtype == GridType.RectilinearZGrid: - nav_lon = xr.DataArray( - field.grid.lon + np.zeros((field.grid.ydim, field.grid.xdim), dtype=np.float32), - coords=[("y", field.grid.lat), ("x", field.grid.lon)], - ) - nav_lat = xr.DataArray( - field.grid.lat.reshape(field.grid.ydim, 1) + np.zeros(field.grid.xdim, dtype=np.float32), - coords=[("y", field.grid.lat), ("x", field.grid.lon)], - ) - elif field.grid._gtype == GridType.CurvilinearZGrid: - nav_lon = xr.DataArray(field.grid.lon, coords=[("y", range(field.grid.ydim)), ("x", range(field.grid.xdim))]) - nav_lat = xr.DataArray(field.grid.lat, coords=[("y", range(field.grid.ydim)), ("x", range(field.grid.xdim))]) - else: - raise NotImplementedError("Field.write only implemented for RectilinearZGrid and CurvilinearZGrid") - - attrs = {"units": "seconds since " + str(field.grid.time_origin)} if field.grid.time_origin.calendar else {} - time_counter = xr.DataArray(field.grid.time, dims=["time_counter"], attrs=attrs) - vardata = xr.DataArray( - field.data.reshape((field.grid.tdim, field.grid.ydim, field.grid.xdim)), dims=["time_counter", "y", "x"] - ) - # Create xarray Dataset and output to netCDF format - attrs = {"parcels_mesh": field.grid.mesh} - dset = xr.Dataset( - {varname: vardata}, coords={"nav_lon": nav_lon, "nav_lat": nav_lat, "time_counter": time_counter}, attrs=attrs - ) - dset.to_netcdf(filepath) - if asizeof is not None: - mem = 0 - mem += asizeof.asizeof(field) - mem += asizeof.asizeof(field.data[:]) - mem += asizeof.asizeof(field.grid) - mem += asizeof.asizeof(vardata) - mem += asizeof.asizeof(nav_lat) - mem += asizeof.asizeof(nav_lon) - mem += asizeof.asizeof(time_counter) - print(f"Field '{field.name}' requires {mem} bytes of memory.") - - -if __name__ == "__main__": - generate_testfieldset(xdim=5, ydim=3, zdim=2, tdim=15) - generate_perlin_testfield()