{ "cells": [ { "cell_type": "markdown", "id": "9dc63b4a-ebb9-41be-bf43-ff4549f37cbd", "metadata": {}, "source": [ "# Animating NEXRAD Level II Data\n", "---" ] }, { "cell_type": "markdown", "id": "79d482d1-ae86-44bc-ae65-7abbc8afe278", "metadata": {}, "source": [ "## Overview\n", " \n", "Within this notebook, we will cover:\n", "\n", "1. Exploring the \"guts\" of a NEXRAD radar file \n", "1. Animating a sequence of AWS-served NEXRAD Level 2 Radar scans\n", "\n", "## Prerequisites\n", "| Concepts | Importance | Notes |\n", "| --- | --- | --- |\n", "| [Cartopy Intro](https://foundations.projectpythia.org/core/cartopy/cartopy.html) | Required | Projections and Features |\n", "| [Matplotlib Basics](https://foundations.projectpythia.org/core/matplotlib/matplotlib-basics.html) | Required | Basic plotting |\n", "| [Py-ART Basics](../foundations/pyart-basics) | Required | IO/Visualization |\n", "\n", "- **Time to learn**: 20 minutes\n", "---" ] }, { "cell_type": "markdown", "id": "44203db4-00ab-4fad-8b61-ead013282b80", "metadata": { "tags": [] }, "source": [ "## Imports" ] }, { "cell_type": "code", "execution_count": null, "id": "77872ced-4f00-4520-8e4e-651c7aa2961b", "metadata": { "tags": [] }, "outputs": [], "source": [ "import pyart\n", "import fsspec\n", "from metpy.plots import USCOUNTIES, ctables\n", "import matplotlib.pyplot as plt\n", "import cartopy.crs as ccrs\n", "import cartopy.feature as cfeature\n", "import warnings\n", "from datetime import datetime as dt\n", "from datetime import timedelta\n", "\n", "import matplotlib\n", "matplotlib.rcParams['animation.html'] = 'html5'\n", "from matplotlib.animation import ArtistAnimation\n", "\n", "warnings.filterwarnings(\"ignore\")" ] }, { "cell_type": "markdown", "id": "87af5f44-55e6-4d23-9523-6e49e2563f88", "metadata": {}, "source": [ "## Select the time and NEXRAD site" ] }, { "cell_type": "code", "execution_count": null, "id": "0e400af6-472d-435e-9a07-2b16978f63f4", "metadata": { "tags": [] }, "outputs": [], "source": [ "datTime = dt(2014,5,26,22)\n", "year = dt.strftime(datTime,format=\"%Y\")\n", "month = dt.strftime(datTime,format=\"%m\")\n", "day = dt.strftime(datTime,format=\"%d\")\n", "hour = dt.strftime(datTime,format=\"%H\")\n", "timeStr = f'{year}{month}{day}{hour}'\n", "\n", "site = 'KSJT'" ] }, { "cell_type": "markdown", "id": "e53147e6-a08a-444b-a7df-9b2a958c4c3b", "metadata": {}, "source": [ "Point to the [NOAA NEXRAD Level 2 S3 Bucket on AWS](https://noaa-nexrad-level2.s3.amazonaws.com/index.html)" ] }, { "cell_type": "code", "execution_count": null, "id": "79521c33-842a-4eb5-b9f7-e57cf420ea96", "metadata": { "tags": [] }, "outputs": [], "source": [ "fs = fsspec.filesystem(\"s3\", anon=True)" ] }, { "cell_type": "markdown", "id": "70c7dd2e-893d-475f-8ee1-35571e4125bb", "metadata": {}, "source": [ "Depending on the year, the radar files will have different naming conventions. " ] }, { "cell_type": "code", "execution_count": null, "id": "39b43c6d-6177-439d-ba97-82e2dc619d34", "metadata": { "tags": [] }, "outputs": [], "source": [ "pattern1 = f's3://noaa-nexrad-level2/{year}/{month}/{day}/{site}/{site}{year}{month}{day}_{hour}*V06'\n", "pattern2 = f's3://noaa-nexrad-level2/{year}/{month}/{day}/{site}/{site}{year}{month}{day}_{hour}*V*.gz'\n", "pattern3 = f's3://noaa-nexrad-level2/{year}/{month}/{day}/{site}/{site}{year}{month}{day}_{hour}*.gz'" ] }, { "cell_type": "markdown", "id": "9fa4912e-9a5b-4972-ad14-6bd0025ca494", "metadata": {}, "source": [ "Construct the URL pointing to the radar file directory and get a list of matching files." ] }, { "cell_type": "markdown", "id": "fea66cf6-1d9e-4a72-8b89-ecbba7ae5277", "metadata": { "tags": [] }, "source": [ "Try each file pattern. Once the list of files is non-empty, we are all set." ] }, { "cell_type": "code", "execution_count": null, "id": "4ba12bed-2963-453f-a98b-8b8e1d79f502", "metadata": { "tags": [] }, "outputs": [], "source": [ "files = sorted(fs.glob(pattern1))\n", "\n", "if (len(files) == 0):\n", " files = sorted(fs.glob(pattern2)) \n", "\n", "if (len(files) == 0):\n", " files = sorted(fs.glob(pattern3)) " ] }, { "cell_type": "markdown", "id": "29103e21-33df-443f-b9d2-a07f9d479634", "metadata": { "tags": [] }, "source": [ "If we still have an empty list, either there are no files available for that site/date, or the file name does not match any of the patterns above. " ] }, { "cell_type": "code", "execution_count": null, "id": "ca2573bb-f9be-4720-96c4-7f9c9c081c01", "metadata": { "tags": [] }, "outputs": [], "source": [ "if (len(files) == 0):\n", " print (\"There are no files found for this date and location. Either try a different date/site, \\\n", "or browse the NEXRAD2 archive to see if the file name uses a different pattern.\")\n", "else:\n", " print (files)" ] }, { "cell_type": "markdown", "id": "2df4be79-bba7-4d94-a4de-a13e4e2a247a", "metadata": {}, "source": [ "## Read the Data into PyART\n", "\n", "Read in the first radar file in the group and list the available fields." ] }, { "cell_type": "code", "execution_count": null, "id": "01b86b2b-78e5-444b-b23b-a7322e6236c6", "metadata": { "tags": [] }, "outputs": [], "source": [ "radar = pyart.io.read_nexrad_archive(f's3://{files[0]}')\n", "list(radar.fields)" ] }, { "cell_type": "markdown", "id": "e5452855-71e1-47af-9aea-c38390191635", "metadata": {}, "source": [ "The `radar` object has a lot of useful data ... and *metadata*! One way to look at the attributes of any Python object is to use the `vars` function. It returns a Python `dictionary`; each dictionary `key` has an associated value ... which might be a single value ... a list of values ... another dictionary ... and so on." ] }, { "cell_type": "code", "execution_count": null, "id": "5cf0b6bf-0a52-4a7d-97e5-b54c8a31b1f3", "metadata": { "tags": [] }, "outputs": [], "source": [ "radarDict = vars(radar)" ] }, { "cell_type": "code", "execution_count": null, "id": "7dd8a694-ca11-4fdf-bf39-eb89fd242084", "metadata": { "tags": [] }, "outputs": [], "source": [ "radarDict" ] }, { "cell_type": "markdown", "id": "ad662746-3852-4ac7-b13c-8f0163df0988", "metadata": {}, "source": [ "We can get a list of all the individual keys in the dictionary:" ] }, { "cell_type": "code", "execution_count": null, "id": "ba40b88a-1b89-43fd-b292-a8911c325a7e", "metadata": { "tags": [] }, "outputs": [], "source": [ "radarDict.keys()" ] }, { "cell_type": "markdown", "id": "17b21ae3-9aa0-4949-b792-532ef516dd55", "metadata": {}, "source": [ "The first key is `time`. Let's look at it:" ] }, { "cell_type": "code", "execution_count": null, "id": "5dfe99e1-a72e-40c3-b1f0-5ebcbffb5522", "metadata": { "tags": [] }, "outputs": [], "source": [ "radarDict['time']" ] }, { "cell_type": "markdown", "id": "f42b1d9e-4db8-43f6-b75b-10a3a18c952b", "metadata": {}, "source": [ "It's also a Python dictionary! It's shorter than its parent's ... so we can see that there are six keys. Let's look at the first one, `units`." ] }, { "cell_type": "code", "execution_count": null, "id": "a479ab5a-23ca-414f-acb9-888a1418e5ef", "metadata": { "tags": [] }, "outputs": [], "source": [ "radarDict['time']['units']" ] }, { "cell_type": "markdown", "id": "30df8dd1-cf32-4311-934a-c5312824113c", "metadata": {}, "source": [ "It's a string ... and a useful one ... as it provides a base time that we can use to infer timestamps for the start of each of the individual sweeps that make up the full volume scan of this particular radar file." ] }, { "cell_type": "markdown", "id": "ce1632bd-88c3-4cc9-9550-c5c74c2429fb", "metadata": {}, "source": [ "Let's look at `time`'s `data` key:" ] }, { "cell_type": "code", "execution_count": null, "id": "9151c63a-7e98-4b52-be48-7fd2a16a2eb8", "metadata": { "tags": [] }, "outputs": [], "source": [ "radar.time['data'] # equivalent to: radarDict['time']['data']" ] }, { "cell_type": "markdown", "id": "1a0b2b99-85d6-4f81-86f6-92d358747415", "metadata": {}, "source": [ "
radar
dictionary can be accessed as an attribute in the radar
object itself.