Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NEXRAD Level2 structured reader #158

Merged
merged 14 commits into from
Mar 13, 2024
3 changes: 1 addition & 2 deletions ci/notebooktests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dependencies:
- netCDF4
- notebook
- numpy
- open-radar-data>=0.1.0
- pip
- pyproj
- pytest
Expand All @@ -32,5 +33,3 @@ dependencies:
- arm_pyart
- ffmpeg
- zarr
- pip:
- git+https://github.com/openradar/open-radar-data.git
3 changes: 1 addition & 2 deletions ci/unittests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dependencies:
- lat_lon_parser
- netCDF4
- numpy
- open-radar-data>=0.1.0
- pip
- pyproj
- pytest
Expand All @@ -25,5 +26,3 @@ dependencies:
- xarray
- xarray-datatree>=0.0.10
- xmltodict
- pip:
- git+https://github.com/openradar/open-radar-data.git
1 change: 1 addition & 0 deletions docs/history.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* MNT: restructure odim.py/gamic.py, add test_odim.py/test_gamic.py ({pull}`154`) by [@kmuehlbauer](https://github.com/kmuehlbauer).
* MNT: use CODECOV token ({pull}`155`) by [@kmuehlbauer](https://github.com/kmuehlbauer).
* MNT: fix path for notebook coverage ({pull}`157`) by [@kmuehlbauer](https://github.com/kmuehlbauer).
* ADD: NEXRAD Level2 structured reader ({pull}`158`) by [@kmuehlbauer](https://github.com/kmuehlbauer) and [@mgrover1](https://github.com/mgrover1).

## 0.4.3 (2024-02-24)

Expand Down
19 changes: 19 additions & 0 deletions docs/importers.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Currently xradar can import:
- [](#furuno-scn-and-scnx)
- [](#rainbow)
- [](#iris-sigmet)
- [](#nexradlevel2)

## CfRadial1

Expand Down Expand Up @@ -115,3 +116,21 @@ more functions are applied on that {py:class}`xarray:xarray.Dataset`.
With {func}`~xradar.io.backends.iris.open_iris_datatree` all groups (eg. ``1``)
are extracted. From that the ``root`` group is processed. Everything is finally added as
ParentNodes and ChildNodes to a {py:class}`datatree:datatree.DataTree`.


## NexradLevel2

### NexradLevel2BackendEntryPoint

The xarray backend {class}`~xradar.io.backends.nexrad_level2.NexradLevel2BackendEntryPoint`
opens the file with {class}`~xradar.io.backends.nexrad_level2.NexradLevel2Store`. Several
private helper functions are used to conveniently access data and
metadata. Finally, the xarray machinery returns a {py:class}`xarray:xarray.Dataset`
with wanted group (eg. ``0``). Depending on the used backend kwargs several
more functions are applied on that {py:class}`xarray:xarray.Dataset`.

### open_nexradlevel2_datatree

With {func}`~xradar.io.backends.nexrad_level2.open_nexradlevel2_datatree`
all groups (eg. ``1``) are extracted. From that the ``root`` group is processed.
Everything is finally added as ParentNodes and ChildNodes to a {py:class}`datatree:datatree.DataTree`.
1 change: 1 addition & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ notebooks/GAMIC
notebooks/Furuno
notebooks/Rainbow
notebooks/Iris
notebooks/NexradLevel2
notebooks/Read-plot-Sigmet-data-from-AWS
notebooks/plot-ppi
notebooks/angle_reindexing
Expand Down
3 changes: 1 addition & 2 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dependencies:
- h5py
- lat_lon_parser
- netCDF4
- open-radar-data>=0.1.0
- pyproj
- xarray
- xarray-datatree>=0.0.10
Expand All @@ -29,5 +30,3 @@ dependencies:
- arm_pyart
- ffmpeg
- zarr
- pip:
- git+https://github.com/openradar/open-radar-data.git
271 changes: 271 additions & 0 deletions examples/notebooks/NexradLevel2.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "0",
"metadata": {},
"source": [
"# NEXRAD Level 2"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1",
"metadata": {},
"outputs": [],
"source": [
"import xarray as xr\n",
"import xradar as xd\n",
"import cmweather\n",
"from open_radar_data import DATASETS"
]
},
{
"cell_type": "markdown",
"id": "2",
"metadata": {},
"source": [
"## Download\n",
"\n",
"Fetching NEXRAD Level2 radar data file from [open-radar-data](https://github.com/openradar/open-radar-data) repository."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3",
"metadata": {},
"outputs": [],
"source": [
"filename = DATASETS.fetch(\"KLBB20160601_150025_V06\")"
]
},
{
"cell_type": "markdown",
"id": "4",
"metadata": {},
"source": [
"## xr.open_dataset\n",
"\n",
"Making use of the xarray `nexradlevel2` backend. We also need to provide the group. Note, that we are using CfRadial2 group access pattern."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5",
"metadata": {},
"outputs": [],
"source": [
"ds = xr.open_dataset(filename, group=\"sweep_0\", engine=\"nexradlevel2\")\n",
"display(ds)"
]
},
{
"cell_type": "markdown",
"id": "6",
"metadata": {},
"source": [
"### Plot Time vs. Azimuth"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7",
"metadata": {},
"outputs": [],
"source": [
"ds.azimuth.plot()"
]
},
{
"cell_type": "markdown",
"id": "8",
"metadata": {},
"source": [
"### Plot Range vs. Time\n",
"\n",
"We need to sort by time and specify the y-coordinate."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9",
"metadata": {},
"outputs": [],
"source": [
"ds.DBZH.sortby(\"time\").plot(y=\"time\", cmap=\"HomeyerRainbow\")"
]
},
{
"cell_type": "markdown",
"id": "10",
"metadata": {},
"source": [
"### Plot Range vs. Azimuth\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "11",
"metadata": {},
"outputs": [],
"source": [
"ds.DBZH.plot(cmap=\"HomeyerRainbow\")"
]
},
{
"cell_type": "markdown",
"id": "12",
"metadata": {},
"source": [
"## backend_kwargs\n",
"\n",
"Beside `first_dim` there are several additional backend_kwargs for the nexradlevel2 backend, which handle different aspects of angle alignment. This comes into play, when azimuth and/or elevation arrays are not evenly spacend and other issues."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "13",
"metadata": {},
"outputs": [],
"source": [
"help(xd.io.NexradLevel2BackendEntrypoint)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "14",
"metadata": {},
"outputs": [],
"source": [
"ds = xr.open_dataset(filename, group=\"sweep_0\", engine=\"nexradlevel2\", first_dim=\"time\")\n",
"display(ds)"
]
},
{
"cell_type": "markdown",
"id": "15",
"metadata": {},
"source": [
"## open_nexradlevel2_datatree\n",
"\n",
"The same works analoguous with the datatree loader. But additionally we can provide a sweep string, number or list."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "16",
"metadata": {},
"outputs": [],
"source": [
"help(xd.io.open_nexradlevel2_datatree)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "17",
"metadata": {},
"outputs": [],
"source": [
"dtree = xd.io.open_nexradlevel2_datatree(filename, sweep=4)\n",
"display(dtree)"
]
},
{
"cell_type": "markdown",
"id": "18",
"metadata": {},
"source": [
"### Plot Sweep Range vs. Time"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "19",
"metadata": {},
"outputs": [],
"source": [
"dtree[\"sweep_0\"].ds.DBZH.sortby(\"time\").plot(y=\"time\", cmap=\"HomeyerRainbow\")"
]
},
{
"cell_type": "markdown",
"id": "20",
"metadata": {},
"source": [
"### Plot Sweep Range vs. Azimuth"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "21",
"metadata": {},
"outputs": [],
"source": [
"dtree[\"sweep_0\"].ds.DBZH.plot(cmap=\"HomeyerRainbow\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "22",
"metadata": {},
"outputs": [],
"source": [
"dtree = xd.io.open_nexradlevel2_datatree(filename, sweep=\"sweep_8\")\n",
"display(dtree)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "23",
"metadata": {},
"outputs": [],
"source": [
"dtree = xd.io.open_nexradlevel2_datatree(filename, sweep=[0, 1, 8])\n",
"display(dtree)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "24",
"metadata": {},
"outputs": [],
"source": [
"dtree = xd.io.open_nexradlevel2_datatree(\n",
" filename, sweep=[\"sweep_1\", \"sweep_2\", \"sweep_8\"]\n",
")\n",
"display(dtree)"
]
}
],
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ gamic = "xradar.io.backends:GamicBackendEntrypoint"
iris = "xradar.io.backends:IrisBackendEntrypoint"
odim = "xradar.io.backends:OdimBackendEntrypoint"
rainbow = "xradar.io.backends:RainbowBackendEntrypoint"
nexradlevel2 = "xradar.io.backends:NexradLevel2BackendEntrypoint"


[build-system]
requires = [
Expand Down
Loading