diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d1a621e4..f8c6dcc9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: black --check . - name: Lint with ruff run: | - ruff . + ruff check . build_0: name: xradar unit tests - linux @@ -42,6 +42,7 @@ jobs: fail-fast: false matrix: python-version: ["3.10", "3.11", "3.12"] + numpy-version: ["1", "2"] steps: - uses: actions/checkout@v4 with: @@ -55,6 +56,7 @@ jobs: cache-environment-key: "${{runner.os}}-${{runner.arch}}-py${{env.PYTHON_VERSION}}-${{env.TODAY}}-${{hashFiles(env.CONDA_ENV_FILE)}}" create-args: >- python=${{matrix.python-version}} + numpy=${{matrix.numpy-version}} conda - name: Install xradar run: | @@ -88,6 +90,7 @@ jobs: fail-fast: false matrix: python-version: ["3.10", "3.11", "3.12"] + numpy-version: ["1", "2"] steps: - uses: actions/checkout@v4 with: @@ -101,6 +104,7 @@ jobs: cache-environment-key: "${{runner.os}}-${{runner.arch}}-py${{env.PYTHON_VERSION}}-${{env.TODAY}}-${{hashFiles(env.CONDA_ENV_FILE)}}" create-args: >- python=${{matrix.python-version}} + numpy=${{matrix.numpy-version}} conda - name: Install xradar run: | diff --git a/docs/history.md b/docs/history.md index 5c554d4f..065b96d0 100644 --- a/docs/history.md +++ b/docs/history.md @@ -1,9 +1,9 @@ # History ## Development Version (unreleased) - -* ADD: Add Alfonso to citation doc ({pull}`169`) by [@mgrover1](https://github.com/mgrover1) -* ENH: Adding global variables and attributes to iris datatree ({pull}`166`) by [@aladinor](https://github.com/aladinor) +* FIX: Fix use of ruff, CI and numpy2 ({pull}`177`) by [@mgrover1](https://github.com/mgrover1) and [@kmuehlbauer](https://github.com/kmuehlbauer). +* ADD: Add Alfonso to citation doc ({pull}`169`) by [@mgrover1](https://github.com/mgrover1). +* ENH: Adding global variables and attributes to iris datatree ({pull}`166`) by [@aladinor](https://github.com/aladinor). * FIX: Set fillvalue before applying scale/offset when exporting to odim ({issue}`122`) by [@pavlikp](https://github.com/pavlikp), ({pull}`173`) by [@kmuehlbauer](https://github.com/kmuehlbauer). ## 0.5.0 (2024-03-28) diff --git a/examples/notebooks/NexradLevel2.ipynb b/examples/notebooks/NexradLevel2.ipynb index a4cd1cb6..d17b3539 100644 --- a/examples/notebooks/NexradLevel2.ipynb +++ b/examples/notebooks/NexradLevel2.ipynb @@ -38,13 +38,23 @@ "metadata": {}, "outputs": [], "source": [ - "filename = DATASETS.fetch(\"KLBB20160601_150025_V06\")" + "filename = \"../../../../Downloads/KDMX20200810_154746_V06\"" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "id": "4", "metadata": {}, + "outputs": [], + "source": [ + "filename = DATASETS.fetch(\"KATX20130717_195021_V06\")" + ] + }, + { + "cell_type": "markdown", + "id": "5", + "metadata": {}, "source": [ "## xr.open_dataset\n", "\n", @@ -54,7 +64,7 @@ { "cell_type": "code", "execution_count": null, - "id": "5", + "id": "6", "metadata": {}, "outputs": [], "source": [ @@ -62,9 +72,31 @@ "display(ds)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "7", + "metadata": {}, + "outputs": [], + "source": [ + "ds" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "np.testing.assert_almost_equal(ds.sweep_fixed_angle.values, 0.4833984)" + ] + }, { "cell_type": "markdown", - "id": "6", + "id": "9", "metadata": {}, "source": [ "### Plot Time vs. Azimuth" @@ -73,7 +105,7 @@ { "cell_type": "code", "execution_count": null, - "id": "7", + "id": "10", "metadata": {}, "outputs": [], "source": [ @@ -82,7 +114,7 @@ }, { "cell_type": "markdown", - "id": "8", + "id": "11", "metadata": {}, "source": [ "### Plot Range vs. Time\n", @@ -93,7 +125,7 @@ { "cell_type": "code", "execution_count": null, - "id": "9", + "id": "12", "metadata": {}, "outputs": [], "source": [ @@ -102,7 +134,7 @@ }, { "cell_type": "markdown", - "id": "10", + "id": "13", "metadata": {}, "source": [ "### Plot Range vs. Azimuth\n" @@ -111,7 +143,7 @@ { "cell_type": "code", "execution_count": null, - "id": "11", + "id": "14", "metadata": {}, "outputs": [], "source": [ @@ -120,7 +152,7 @@ }, { "cell_type": "markdown", - "id": "12", + "id": "15", "metadata": {}, "source": [ "## backend_kwargs\n", @@ -131,7 +163,7 @@ { "cell_type": "code", "execution_count": null, - "id": "13", + "id": "16", "metadata": {}, "outputs": [], "source": [ @@ -141,7 +173,7 @@ { "cell_type": "code", "execution_count": null, - "id": "14", + "id": "17", "metadata": {}, "outputs": [], "source": [ @@ -151,7 +183,7 @@ }, { "cell_type": "markdown", - "id": "15", + "id": "18", "metadata": {}, "source": [ "## open_nexradlevel2_datatree\n", @@ -162,7 +194,7 @@ { "cell_type": "code", "execution_count": null, - "id": "16", + "id": "19", "metadata": {}, "outputs": [], "source": [ @@ -172,7 +204,7 @@ { "cell_type": "code", "execution_count": null, - "id": "17", + "id": "20", "metadata": {}, "outputs": [], "source": [ @@ -182,7 +214,7 @@ }, { "cell_type": "markdown", - "id": "18", + "id": "21", "metadata": {}, "source": [ "### Plot Sweep Range vs. Time" @@ -191,7 +223,7 @@ { "cell_type": "code", "execution_count": null, - "id": "19", + "id": "22", "metadata": {}, "outputs": [], "source": [ @@ -200,7 +232,7 @@ }, { "cell_type": "markdown", - "id": "20", + "id": "23", "metadata": {}, "source": [ "### Plot Sweep Range vs. Azimuth" @@ -209,7 +241,7 @@ { "cell_type": "code", "execution_count": null, - "id": "21", + "id": "24", "metadata": {}, "outputs": [], "source": [ @@ -219,7 +251,7 @@ { "cell_type": "code", "execution_count": null, - "id": "22", + "id": "25", "metadata": {}, "outputs": [], "source": [ @@ -230,7 +262,7 @@ { "cell_type": "code", "execution_count": null, - "id": "23", + "id": "26", "metadata": {}, "outputs": [], "source": [ @@ -241,15 +273,53 @@ { "cell_type": "code", "execution_count": null, - "id": "24", + "id": "27", + "metadata": {}, + "outputs": [], + "source": [ + "dtree[\"sweep_0\"][\"sweep_fixed_angle\"].values" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28", + "metadata": {}, + "outputs": [], + "source": [ + "dtree[\"sweep_1\"][\"sweep_fixed_angle\"].values" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29", "metadata": {}, "outputs": [], "source": [ "dtree = xd.io.open_nexradlevel2_datatree(\n", - " filename, sweep=[\"sweep_1\", \"sweep_2\", \"sweep_8\"]\n", + " filename,\n", ")\n", "display(dtree)" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30", + "metadata": {}, + "outputs": [], + "source": [ + "dtree[\"sweep_1\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -263,7 +333,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.5" + "version": "3.11.4" } }, "nbformat": 4, diff --git a/examples/notebooks/ODIM_H5.ipynb b/examples/notebooks/ODIM_H5.ipynb index 64e36a97..3a7a7505 100644 --- a/examples/notebooks/ODIM_H5.ipynb +++ b/examples/notebooks/ODIM_H5.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "59447ad6-ac47-494e-b696-4335b36b205b", + "id": "0", "metadata": {}, "source": [ "# ODIM_H5" @@ -11,7 +11,7 @@ { "cell_type": "code", "execution_count": null, - "id": "6f96b5d8-2b96-4fd7-b8ba-166c34a8dcd2", + "id": "1", "metadata": {}, "outputs": [], "source": [ @@ -22,7 +22,7 @@ }, { "cell_type": "markdown", - "id": "33d50be4-dfe5-4d99-a936-67a9a76bac94", + "id": "2", "metadata": {}, "source": [ "## Download\n", @@ -33,7 +33,7 @@ { "cell_type": "code", "execution_count": null, - "id": "d3c6d408-5ab2-43c3-afd1-b3a703ef3b24", + "id": "3", "metadata": {}, "outputs": [], "source": [ @@ -42,7 +42,7 @@ }, { "cell_type": "markdown", - "id": "b987dcfd-5105-4483-932e-71b8002e5f09", + "id": "4", "metadata": {}, "source": [ "## xr.open_dataset\n", @@ -53,7 +53,7 @@ { "cell_type": "code", "execution_count": null, - "id": "7675b518-18e4-4ea6-b101-f1bccf603902", + "id": "5", "metadata": {}, "outputs": [], "source": [ @@ -61,9 +61,19 @@ "display(ds)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "6", + "metadata": {}, + "outputs": [], + "source": [ + "ds.sweep_fixed_angle.values" + ] + }, { "cell_type": "markdown", - "id": "01ec8c90-2da8-46ae-a0b5-0e1792a79bbe", + "id": "7", "metadata": {}, "source": [ "### Plot Time vs. Azimuth" @@ -72,7 +82,7 @@ { "cell_type": "code", "execution_count": null, - "id": "24dfb5f8-de27-46f0-9246-722e5955a345", + "id": "8", "metadata": {}, "outputs": [], "source": [ @@ -81,7 +91,7 @@ }, { "cell_type": "markdown", - "id": "222ca704-d6e1-49e6-84a0-de55df9fdf61", + "id": "9", "metadata": {}, "source": [ "### Plot Range vs. Time" @@ -90,7 +100,7 @@ { "cell_type": "code", "execution_count": null, - "id": "34429720-e689-4786-99e3-5af9742d19ad", + "id": "10", "metadata": {}, "outputs": [], "source": [ @@ -99,7 +109,7 @@ }, { "cell_type": "markdown", - "id": "d904cd09-8590-42e2-8dce-41d3949d313c", + "id": "11", "metadata": {}, "source": [ "### Plot Range vs. Azimuth\n", @@ -110,7 +120,7 @@ { "cell_type": "code", "execution_count": null, - "id": "6479a374-25ab-42be-b53e-82849b6faffc", + "id": "12", "metadata": {}, "outputs": [], "source": [ @@ -119,7 +129,7 @@ }, { "cell_type": "markdown", - "id": "5deafdf1-9224-459c-8b10-7c501ae13234", + "id": "13", "metadata": {}, "source": [ "## backend_kwargs\n", @@ -130,7 +140,7 @@ { "cell_type": "code", "execution_count": null, - "id": "08f12b48-a3b5-43b7-b9a1-87afa9002fb9", + "id": "14", "metadata": {}, "outputs": [], "source": [ @@ -140,7 +150,7 @@ { "cell_type": "code", "execution_count": null, - "id": "dd052e96-9666-40ff-8b9b-3723daf68c32", + "id": "15", "metadata": {}, "outputs": [], "source": [ @@ -150,7 +160,7 @@ }, { "cell_type": "markdown", - "id": "9a09378a-11d9-414f-bc23-0b6f01017d12", + "id": "16", "metadata": {}, "source": [ "## open_odim_datatree\n", @@ -161,7 +171,7 @@ { "cell_type": "code", "execution_count": null, - "id": "e8485006-ca89-4409-82ab-29ae8f93004a", + "id": "17", "metadata": {}, "outputs": [], "source": [ @@ -171,7 +181,7 @@ { "cell_type": "code", "execution_count": null, - "id": "a65f0b48-7197-4f79-bc26-2045cfc59a4a", + "id": "18", "metadata": {}, "outputs": [], "source": [ @@ -181,7 +191,7 @@ }, { "cell_type": "markdown", - "id": "638bc6c0-3293-4661-a5d5-e9aaad14ffe9", + "id": "19", "metadata": {}, "source": [ "### Plot Sweep Range vs. Time" @@ -190,7 +200,7 @@ { "cell_type": "code", "execution_count": null, - "id": "f9db8500-7072-451b-84a1-f36767110e16", + "id": "20", "metadata": {}, "outputs": [], "source": [ @@ -199,7 +209,7 @@ }, { "cell_type": "markdown", - "id": "1e44c0fd-02bc-4d2d-ac91-772bdcebe04b", + "id": "21", "metadata": {}, "source": [ "### Plot Sweep Range vs. Azimuth" @@ -208,7 +218,7 @@ { "cell_type": "code", "execution_count": null, - "id": "c7aab6b3-aeb0-4ed1-8397-8b505e63464a", + "id": "22", "metadata": {}, "outputs": [], "source": [ @@ -218,7 +228,7 @@ { "cell_type": "code", "execution_count": null, - "id": "9dc09b53-7e2a-4fb6-9b28-a3ae3fd95bd0", + "id": "23", "metadata": {}, "outputs": [], "source": [ @@ -229,7 +239,7 @@ { "cell_type": "code", "execution_count": null, - "id": "41976524-fca8-4569-8b37-867d2214709c", + "id": "24", "metadata": {}, "outputs": [], "source": [ @@ -240,7 +250,7 @@ { "cell_type": "code", "execution_count": null, - "id": "c4239ebf-f16d-42ee-8f03-a38ecbc04cee", + "id": "25", "metadata": {}, "outputs": [], "source": [ @@ -260,7 +270,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.6" + "version": "3.11.4" } }, "nbformat": 4, diff --git a/examples/notebooks/conftest.py b/examples/notebooks/conftest.py index c21755ab..0e4369ce 100644 --- a/examples/notebooks/conftest.py +++ b/examples/notebooks/conftest.py @@ -75,7 +75,7 @@ def repr_failure(self, excinfo): return super().repr_failure(excinfo) def reportinfo(self): - return self.path, 0, "TestCase: %s" % self.name + return self.path, 0, f"TestCase: {self.name}" class NotebookException(Exception): diff --git a/tests/io/test_io.py b/tests/io/test_io.py index 7c151b95..6db703a6 100644 --- a/tests/io/test_io.py +++ b/tests/io/test_io.py @@ -742,7 +742,7 @@ def test_odim_optional_how(odim_file2): ds = h5py.File(outfile) for i in range(1, 6): - ds_how = ds["dataset%s" % (i)]["how"].attrs + ds_how = ds[f"dataset{i}"]["how"].attrs assert "scan_index" in ds_how assert "scan_count" in ds_how assert "startazA" in ds_how @@ -762,7 +762,7 @@ def test_odim_optional_how(odim_file2): ds = h5py.File(outfile) for i in range(1, 6): - ds_how = ds["dataset%s" % (i)]["how"].attrs + ds_how = ds[f"dataset{i}"]["how"].attrs assert "scan_index" not in ds_how assert "scan_count" not in ds_how assert "startazA" not in ds_how diff --git a/xradar/io/backends/iris.py b/xradar/io/backends/iris.py index f5e78ad8..4e82462a 100644 --- a/xradar/io/backends/iris.py +++ b/xradar/io/backends/iris.py @@ -179,6 +179,9 @@ def decode_array(data, scale=1.0, offset=0, offset2=0, tofloat=False, mask=None) data = to_float(data) if mask is not None: data = np.ma.masked_equal(data, mask) + # numpy 2 changed casting rules + # so we need to cast to float beforehand + data = data.astype(np.float64) return (data + offset) / scale + offset2 @@ -3338,7 +3341,8 @@ def get_compression_code(self): cmp_val = self.read_from_record(1, "int16")[0] cmp_msb = np.sign(cmp_val) == -1 if cmp_msb: - cmp_val = cmp_val + 32768 + # prevent OverflowError in numpy 2 + cmp_val = cmp_val + 32767 + 1 if self._debug: print( "--- Sub CMP Code:", @@ -3959,9 +3963,7 @@ def _get_iris_group_names(filename): def _get_required_root_dataset(ls_ds, optional=True): """Extract Root Dataset.""" # keep only defined mandatory and defined optional variables per default - data_var = set( - [x for xs in [sweep.variables.keys() for sweep in ls_ds] for x in xs] - ) + data_var = {x for xs in [sweep.variables.keys() for sweep in ls_ds] for x in xs} remove_root = set(data_var) ^ set(required_root_vars) if optional: remove_root ^= set(optional_root_vars) @@ -3972,9 +3974,7 @@ def _get_required_root_dataset(ls_ds, optional=True): } remove_root &= data_var root = [sweep.drop_vars(remove_root) for sweep in ls_ds] - root_vars = set( - [x for xs in [sweep.variables.keys() for sweep in root] for x in xs] - ) + root_vars = {x for xs in [sweep.variables.keys() for sweep in root] for x in xs} # rename variables # todo: find a more easy method not iterating over all variables for k in root_vars: @@ -3982,9 +3982,7 @@ def _get_required_root_dataset(ls_ds, optional=True): if rename: root = [sweep.rename_vars({k: rename}) for sweep in root] - root_vars = set( - [x for xs in [sweep.variables.keys() for sweep in root] for x in xs] - ) + root_vars = {x for xs in [sweep.variables.keys() for sweep in root] for x in xs} ds_vars = [sweep[root_vars] for sweep in ls_ds] root = xr.concat(ds_vars, dim="sweep").reset_coords() @@ -4010,7 +4008,7 @@ def _get_subgroup(ls_ds: list[xr.Dataset], subdict): Variables are fetched from the provided Dataset according to the subdict dictionary. """ meta_vars = subdict - data_vars = set([x for xs in [ds.variables.keys() for ds in ls_ds] for x in xs]) + data_vars = {x for xs in [ds.variables.keys() for ds in ls_ds] for x in xs} extract_vars = set(data_vars) & set(meta_vars) subgroup = xr.concat([ds[extract_vars] for ds in ls_ds], "sweep") for k in subgroup.data_vars: diff --git a/xradar/io/backends/rainbow.py b/xradar/io/backends/rainbow.py index 7e3cb993..2630e254 100644 --- a/xradar/io/backends/rainbow.py +++ b/xradar/io/backends/rainbow.py @@ -519,7 +519,7 @@ def _get_rbdict_value(self, rbdict, name, dtype=None, default=None): if value is None: value = self.pargroup.get(name, default) if dtype is not None: - if dtype == bool: + if dtype is bool: value = int(value) value = dtype(value) return value