{ "cells": [ { "cell_type": "markdown", "id": "99aafef2", "metadata": { "id": "99aafef2" }, "source": [ "# Exploring TC PRIMED, Chapter 2: Composite Analysis\n", "- Creators: Naufal Razin, Kathy Haynes, and Chris Slocum\n", "- Affiliations: CIRA and NESDIS/STAR\n", "\n", "---\n", "\n", "## Overview\n", "With an extensive array of tropical cyclone passive microwave observations, retrieved precipitation, track and intensity information, and environmental diagnostics, TC PRIMED provides users with the opportunity to conduct a comprehensive study on tropical cyclone convective and precipitation structure, intensity, and environment. In this notebook, you will learn how to conduct a simple timeseries composite using TC PRIMED data.\n", "\n", "## Prerequisites\n", "To successfully navigate and use this notebook, you should be familiar with:\n", "- the basics of Python programming such as loading modules, assigning variables, and list/array indexing\n", "- NetCDF files and NetCDF groups (Chapter 1a of this Learning Journey)\n", "- plotting data using matplotlib\n", "- TC PRIMED overpass file data structure (Chapter 1b of this Learning Journey)\n", "- TC PRIMED environmental file data structure (Chapter 1c of this Learning Journey)\n", "\n", "## Learning Outcomes\n", "By working through this notebook, you will learn how to:\n", "- conduct a simple timeseries composite analysis using TC PRIMED data" ] }, { "cell_type": "markdown", "id": "f530e9b2-7a76-4de8-8e10-aeff6b66d57d", "metadata": { "id": "31f930d1" }, "source": [ "## Background\n", "One of the key concepts that is widely understood in the tropical cyclone community is the importance of robust convection in the tropical cyclone inner-core for achieving and maintaining strong tropical cyclone winds. Strong inner-core convection often coincide with more intense tropical cyclones that have a maximum 1-minute average tangential wind speed in the middle-to-higher end of the [Saffir-Simpson Hurricane Wind Scale](https://www.nhc.noaa.gov/aboutsshws.php#:~:text=The%20Saffir%2DSimpson%20Hurricane%20Wind,Scale%20estimates%20potential%20property%20damage.). Forecasters often analyze satellite passive microwave observations to gain insight into the convective structure of tropical cyclones and predict its intensity trend. In this notebook, you will learn to use passive microwave observations from TC PRIMED to conduct a simple timeseries composite, and relate the tropical cyclone convective structure to intensity.\n", "\n", "### Hurricane Florence (2018)\n", "In this example, we will use TC PRIMED files from Hurricane Florence (2018). If you have gone through the earlier notebooks in this series, you should be familiar with Hurricane Florence. Hurricane Florence was a long-lived hurricane that formed off the coast of Senegal and The Gambia, and tracked westward across the North Atlantic Ocean. During its track across the Atlantic, it briefly intensified to a Category 4 hurricane, weakened to a tropical storm, and re-intensified back to a Category 4 hurricane before making landfall along the southeastern coast of North Carolina as a high-end Category 1 hurricane. Florence brought [record-breaking rainfall](https://www.weather.gov/ilm/HurricaneFlorence) across eastern North Carolina and parts of northeastern South Carolina." ] }, { "cell_type": "markdown", "id": "28aecab2-bf98-4e5f-ac65-3d04bf3cbeac", "metadata": { "id": "31f930d1" }, "source": [ "
\n", "\"An\n", "\n", "
Figure 1. An image of Hurricane Florence (2018) captured by European Space Agency astronaut Alexander Gerst from aboard the International Space Station. Source: ESA
\n", "
" ] }, { "cell_type": "markdown", "id": "083143bf-0280-4791-acac-b08870dc2106", "metadata": { "id": "31f930d1" }, "source": [ "### Passive Microwave Observations in the 85 to 92 GHz Frequency Window\n", "In this notebook, we will relate the convective structure of Hurricane Florence to its intensity. More precisely, we will look at passive microwave signatures in the 85 to 92 GHz frequency window to infer the strength and location of convection. In this frequency window, large precipitation-sized ice particles, such as that found in deep convection, scatter radiation from the Earth. The scattering of Earth radiation results in observations of localized low brightness temperatures. Stronger convection produces larger ice particles, which result in stronger scattering of Earth radiation and therefore, lower brightness temperatures.\n", "\n", "Other sources can also influence passive microwave brightness temperatures to produce low or high brightness temperatures, like land. To remove the effect of varying brightness temperatures to the varying properties of the Earth's surface and isolate just the ice-scattering signatures, satellite analysts use the polarization-corrected brightness temperature (PCT), which uses a combination of the observations from the vertically- and horizontally- polarized brightness temperatures. In this notebook, we will use the equation for PCT from Cecil and Chronis (2018), where\n", "\n", "$$\n", " PCT = {TB}_{V} \\times 1.7 - {TB}_{H} \\times 0.7\n", "$$\n", "\n", "Here, ${TB}_{V}$ is the vertically-polarized brightness temperature and ${TB}_{H}$ is the horizontally-polarized brightness temperature." ] }, { "cell_type": "markdown", "id": "677bc7e7", "metadata": { "id": "677bc7e7" }, "source": [ "## Software\n", "This tutorial uses the Python programming language and packages. We will use:\n", "- `netCDF4` to read in the TC PRIMED file\n", "- `matplotlib` to plot the data\n", "- `numpy` for simple array operations\n", "- `scipy` for calculating bin statistics" ] }, { "cell_type": "markdown", "id": "741ece79", "metadata": { "id": "741ece79" }, "source": [ "### Install Packages\n", "Let's first check if we have the necessary Python packages to run this notebook. If we don't, let's install them." ] }, { "cell_type": "code", "execution_count": null, "id": "RGBUacPKe6oL", "metadata": { "id": "RGBUacPKe6oL" }, "outputs": [], "source": [ "import subprocess, sys\n", "packages = [\"netCDF4\", \"matplotlib\", \"numpy\", \"scipy\"]\n", "for package in packages:\n", " try:\n", " __import__(package)\n", " except ImportError:\n", " subprocess.check_call([sys.executable, '-m', 'pip', 'install', package])" ] }, { "cell_type": "markdown", "id": "JtpVbGoyfP7p", "metadata": { "id": "JtpVbGoyfP7p" }, "source": [ "Now, let's load the modules in the packages (e.g., `Dataset`) or load the packages and assign a shorter object name for the packages (e.g., `import matplotlib.pyplot as plt`) for a cleaner use throughout the notebook." ] }, { "cell_type": "code", "execution_count": null, "id": "29acec82", "metadata": { "id": "29acec82" }, "outputs": [], "source": [ "# Load the Python packages we will use in this notebook\n", "import datetime\n", "from netCDF4 import Dataset\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "from scipy import stats" ] }, { "cell_type": "markdown", "id": "a9baf22e", "metadata": { "id": "a9baf22e" }, "source": [ "## File Selection\n", "When choosing the files to conduct the analysis, there are several key aspects of passive microwave observations that users should note:\n", "- Cross-track-scanning passive microwave sensors have varying instantaneous fields-of-view (IFOV) across its swath, with the smallest IFOV (highest resolution) at nadir and the biggest IFOV (coarsest resolution) at the edge of its swath. Whereas conical-scanning passive microwave sensors have a constant IFOV/resolution across its swath.\n", "- Different passive microwave sensors have different instantaneous fields-of-view (IFOV). Some sensors have smaller IFOV (higher resolution) while other sensors have bigger IFOV (coarser resolution). For more information, see Figure 1 from Chapter 1b of this Learning Journey.\n", "- Some sensors are available on only one satellite (e.g., the Global Precipitation Measurement (GPM) Microwave Imager (GMI)), while other sensors are available on multiple satellites (e.g., the Special Sensor Microwave/Imager (SSM/I))\n", "- Different observing frequencies do not produce the same brightness temperature observation. In other words, given all else equal, the observation of a convective cell at the 85.5 GHz frequency would not yield the same brightness temperature value as the same observation in at the 89.0 GHz frequency.\n", "\n", "When doing a timeseries composite, particularly from only one storm, we want to select a sensor that is available on multiple satellites to increase our chances of obtaining multiple observations of the storm throughout its life. In addition, we want to ensure consistent observations such that the sensor characteristics do not influence the observed brightness temperatures. Therefore, we will use observations from only the conical-scanning SSMIS sensor in this notebook. Within the range of the 85 to 92 GHz observation frequency, the Special Sensor Microwave - Imager/Sounder (SSMIS) sensor has an observation frequency at 91.665 GHz (92 GHz, for brevity)." ] }, { "cell_type": "markdown", "id": "Niw6a8YTddh6", "metadata": { "id": "Niw6a8YTddh6" }, "source": [ "## Read Files Online\n", "Let's retrieve the files that we will use in this example. As we have mentioned above, the TC PRIMED files will be from SSMIS overpasses of Hurricane Florence (2018). We will use the Python `netCDF4` and `requests` packages to read and retrieve the information directly from the TC PRIMED files available on an Amazon Web Service S3 bucket as part of the NOAA Open Data Dissemination program (NODD), without downloading the file, and store the information from the file in an \"instance\" type called `DS`.\n", "\n", "**Note that here, we have pre-selected the overpasses with a good observational coverage of the storm and organized them in the order of increasing time. And, with the number of files we will be reading, this code block will take some time to run.**" ] }, { "cell_type": "code", "execution_count": null, "id": "-YsNOG2WKX6x", "metadata": { "id": "-YsNOG2WKX6x" }, "outputs": [], "source": [ "import requests\n", "\n", "# Specify the URL to the TC PRIMED folder on NODD\n", "NODD_URL = \"https://noaa-nesdis-tcprimed-pds.s3.amazonaws.com/v01r00/final/2018/AL/06/\"\n", "\n", "# Specify the name of the files we will use from the TC PRIMED folder on NODD\n", "OVERPASS_FILE_NAMES = [\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076709_20180830164830.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045726_20180830185530.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_060995_20180830195230.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076716_20180831052431.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061009_20180831193931.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045747_20180901072001.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061016_20180901081501.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076738_20180901180401.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076752_20180902175102.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045769_20180902200102.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061038_20180902205402.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076759_20180903062503.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045776_20180903083503.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061045_20180903092803.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045783_20180903194903.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061052_20180903204203.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045790_20180904082304.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061059_20180904091504.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076795_20180905185505.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045812_20180905210705.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076802_20180906072606.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045819_20180906093806.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061088_20180906102906.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076809_20180906184306.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045826_20180906205406.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061095_20180906214506.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076816_20180907071307.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045833_20180907092507.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061102_20180907101507.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045840_20180907204207.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061109_20180907213207.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045847_20180908091308.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061116_20180908100208.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076852_20180909194509.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076859_20180910081510.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045876_20180910102910.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061145_20180910111710.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076866_20180910193210.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061152_20180910223310.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076873_20180911080211.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045890_20180911101611.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061159_20180911110311.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045897_20180911213511.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061166_20180911222111.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076895_20180912204912.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076902_20180913091513.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045919_20180913113113.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061188_20180913121513.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076909_20180913203713.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045926_20180913225313.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061195_20180913233713.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076916_20180914090214.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045933_20180914111814.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061202_20180914120214.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F16_076923_20180914202414.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045940_20180914224014.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061209_20180914232414.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045947_20180915110615.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061216_20180915114915.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F18_045954_20180915222815.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061223_20180915231115.nc\",\n", " \"TCPRIMED_v01r00-final_AL062018_SSMIS_F17_061245_20180917130217.nc\"\n", "]\n", "\n", "# Declare DS as a dictionary\n", "DS = {}\n", "\n", "# Loop through each overpass file name\n", "for overpass_file_name in OVERPASS_FILE_NAMES:\n", "\n", " # Join NODD_URL and overpass_file_name to produce a complete link\n", " # Retrieve the contents of the TC PRIMED file from the complete link\n", " url_response = requests.get(NODD_URL + overpass_file_name)\n", "\n", " # Load the contents of the TC PRIMED file in an \"instance\" type into the\n", " # dictionary DS with the file name as the dictionary key\n", " DS[overpass_file_name] = Dataset(overpass_file_name, memory=url_response.content)" ] }, { "cell_type": "markdown", "id": "881570d4", "metadata": { "id": "881570d4" }, "source": [ "Since we want to relate the passive microwave convective signatures with the tropical cyclone intensity, let's retrieve and read information from the TC PRIMED environmental file." ] }, { "cell_type": "code", "execution_count": null, "id": "76211f36", "metadata": { "id": "76211f36" }, "outputs": [], "source": [ "# Specify the name of the file we will use from the TC PRIMED folder on NODD\n", "ENV_FILE_NAME = \"TCPRIMED_v01r00-final_AL062018_era5_s20180830060000_e20180918120000.nc\"\n", "\n", "# Join NODD_URL and ENV_FILE_NAME to produce a complete link\n", "# Retrieve the contents of the TC PRIMED file from the complete link\n", "url_response = requests.get(NODD_URL + ENV_FILE_NAME)\n", "\n", "# Load the contents of the TC PRIMED file in an \"instance\" type into the\n", "# dictionary DS with the filename as the dictionary key\n", "DS[ENV_FILE_NAME] = Dataset(ENV_FILE_NAME, memory=url_response.content)" ] }, { "cell_type": "markdown", "id": "c679bf91", "metadata": { "id": "c679bf91" }, "source": [ "First, let's load the intensity information from the TC PRIMED environmental file." ] }, { "cell_type": "code", "execution_count": null, "id": "9f0f65d2", "metadata": { "id": "9f0f65d2" }, "outputs": [], "source": [ "# Load the time and intensity data from the storm_metadata\n", "# group of the TC PRIMED environmental file\n", "storm_metadata_time = DS[ENV_FILE_NAME][\"/storm_metadata/time\"][:]\n", "storm_metadata_vmax = DS[ENV_FILE_NAME][\"/storm_metadata/intensity\"][:]\n", "\n", "# All time variables in TC PRIMED files are stored in units\n", "# of seconds since 1970-01-01, a.k.a., the Unix time stamp\n", "# Convert this Unix time stamp array into a Python datetime\n", "# array.\n", "# Then, convert this Python datetime array into a string array\n", "# in the form of \"month/day hour\"\n", "storm_metadata_datetime = [datetime.datetime.fromtimestamp(t) for t in storm_metadata_time]\n", "storm_metadata_datetime_str = [t.strftime(\"%m/%d %H\") for t in storm_metadata_datetime]" ] }, { "cell_type": "markdown", "id": "3ff00201", "metadata": { "id": "3ff00201" }, "source": [ "## Selecting Parameters for Timeseries Composite\n", "Since we want to present our data in the form of a timeseries, our output data array must have time as one of its dimensions. This time dimension corresponds to the time of the passive microwave observation throughout Hurricane Florence's life, which is the same as the number of TC PRIMED overpass files. We also want to show the evolution of the passive microwave convective signature — how strong it is and where it is located in Hurricane Florence. One way to do this is by taking the average passive microwave brightness temperature within various radial regions around the center of Hurricane Florence. Therefore, we will need to specify our radial bins for these radial regions. Let's do that first." ] }, { "cell_type": "code", "execution_count": null, "id": "527b1f8a", "metadata": { "id": "527b1f8a" }, "outputs": [], "source": [ "# Radial bin parameters\n", "radial_bins_min = 0 # Innermost radius used for binning, in km\n", "radial_bins_max = 301 # Outermost radius used for binning, in km\n", "radial_bins_size = 25 # Size of the radial bin, in km\n", "# Generate array of the radial bins\n", "radial_bins = np.arange(radial_bins_min,radial_bins_max,radial_bins_size)\n", "\n", "# When storing and plotting the mean brightness temperatures, we will want to use\n", "# the center of the radial bins, which has a size equivalent to len(radial_bins) - 1.\n", "# Let's obtain that.\n", "radial_bin_center = np.arange(radial_bins_min + (radial_bins_size/2),\n", " radial_bins_max - (radial_bins_size/2) + 1,\n", " radial_bins_size)\n", "\n", "# Initialize time array, which has the same size as the number of\n", "# selected observations of Hurricane Florence\n", "overpass_times = np.zeros(len(OVERPASS_FILE_NAMES))\n", "\n", "# Initialize array to store mean PCT values\n", "stat_pct92 = np.zeros((overpass_times.size, radial_bin_center.size))" ] }, { "cell_type": "markdown", "id": "f4f95932", "metadata": { "id": "f4f95932" }, "source": [ "## Timeseries Composite\n", "Compositing the timeseries consists of several steps. At each observation time:\n", "- Load the necessary variables\n", "- Using the x and y (or zonal and meridional) distance of the observation pixels for each overpass, calculate the radius of the observation pixels\n", "- Using the horizontally and vertically polarized 92 GHz observation, calculate the polarization-corrected brightness temperatures (PCT)\n", "- Bin the PCT into the radial bins and calculate the mean in each bin. This process is automatically handled by scipy's binned_statistic function." ] }, { "cell_type": "code", "execution_count": null, "id": "4a28a0ea", "metadata": { "id": "4a28a0ea" }, "outputs": [], "source": [ "# Loop through each file from each selected observation time\n", "# NOTE: we have already arranged the files in the order of increasing\n", "# time\n", "\n", "# Specify the statistic we want to calculate in each radial bin\n", "# Options include mean, std, median, count, sum, min, max, or\n", "# a user-defined or numerical function (e.g., np.nanmean)\n", "stat = 'mean'\n", "for file_idx, overpass_file_name in enumerate(OVERPASS_FILE_NAMES):\n", "\n", " # Load the overpass time variable\n", " overpass_time = DS[overpass_file_name][\"/overpass_metadata/time\"][:][0]\n", " # Put the overpass time variable into the array we specified above\n", " overpass_times[file_idx] = overpass_time\n", "\n", " # Load the x and y values for the pixels in the S4 swath\n", " # (corresponding to the swath for the 92 GHz observation)\n", " S4_x = DS[overpass_file_name][\"/passive_microwave/S4/x\"][:]\n", " S4_y = DS[overpass_file_name][\"/passive_microwave/S4/y\"][:]\n", " # Calculated the radius of the pixels in the S4 swath relative\n", " # to the storm center\n", " S4_r = np.sqrt(S4_x**2 + S4_y**2)\n", "\n", " # Load the horizontal and vertical polarization brightness temperature\n", " # at 92 GHz\n", " S4_v92 = DS[overpass_file_name][\"/passive_microwave/S4/TB_91.665V\"][:]\n", " S4_h92 = DS[overpass_file_name][\"/passive_microwave/S4/TB_91.665H\"][:]\n", "\n", " # Calculate the PCT using the horizontal and vertical polarization\n", " # brightness temperature\n", " S4_pct92 = S4_v92 * 1.7 - S4_h92 * 0.7\n", "\n", " # Using scipy's binned_statistic, bin the PCT into the radial bins we have\n", " # specified above and calculate the statistic\n", " # To ensure a single value is returned for each radial bin, we will have to\n", " # flatten the radius and PCT arrays\n", " stat_pct92[file_idx, :], \\\n", " bin_edges, \\\n", " bin_number = stats.binned_statistic(S4_r.flatten(), S4_pct92.flatten(),\n", " statistic=stat, bins=radial_bins)" ] }, { "cell_type": "markdown", "id": "04269cf5", "metadata": { "id": "04269cf5" }, "source": [ "## Plotting the Timeseries\n", "Now you are ready to plot the timeseries composite! To show how the passive microwave convective signature evolves with Hurricane Florence's intensity, we will also plot the intensity evolution on the same figure using the `twiny()` function. Therefore, the radius bins will be located on the axis at the bottom of the figure, while the tropical cyclone intensity will be located on the axis at the top of the figure. The mean 92 GHz PCT and tropical cyclone intensity will share the same y-axis corresponding to time." ] }, { "cell_type": "code", "execution_count": null, "id": "ab61a965", "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 890 }, "executionInfo": { "elapsed": 1216, "status": "ok", "timestamp": 1686598905014, "user": { "displayName": "Naufal Razin", "userId": "00945304052336708650" }, "user_tz": 360 }, "id": "ab61a965", "outputId": "c140e6ef-f39e-4b1c-ec81-60dedb4333fb" }, "outputs": [], "source": [ "# Set the figure size\n", "plt.figure(figsize=(7, 10))\n", "\n", "# Plot the mean 92 GHz PCT in each radial bin and at each selected\n", "# observation time\n", "# Specify the colormap and contour levels to use\n", "plt.contourf(radial_bin_center, overpass_times, stat_pct92,\n", " cmap=\"inferno_r\",\n", " levels=np.arange(220, 291, 2),\n", " extend=\"both\")\n", "# Plot and label the colorbar\n", "plt.colorbar(label=\"91.665-GHz Brightness Temperature (K)\")\n", "# Label the x axis\n", "plt.xlabel(\"Radial Bins (km)\")\n", "\n", "# Generate new x-axis sharing the y-axis with the plot above\n", "plt.twiny()\n", "\n", "# Plot the intensity values throughout the storm's life\n", "plt.plot(storm_metadata_vmax, storm_metadata_time, color=\"k\", lw=5)\n", "\n", "# Label the x axis\n", "plt.xlabel(\"Intensity (knots)\")\n", "\n", "# Recall that the time units are still in Unix time\n", "# Replace the Unix time with the time string array we\n", "# generated above and only plot the ticks at every\n", "# fourth entry\n", "plt.yticks(storm_metadata_time[::4], storm_metadata_datetime_str[::4]);" ] }, { "cell_type": "markdown", "id": "ea96ccc5", "metadata": { "id": "ea96ccc5" }, "source": [ "## Analysis\n", "First, notice that at different points throughout Hurricane Florence's life, pockets of low mean 92 GHz PCT (lower than 230 Kelvin) exist in radial bins less than 50 to 100 km from the storm center. Recall that low brightness temperatures in this observation frequency correspond to strong convection that produces large precipitation-sized ice particles that scatter Earth radiation. Therefore, you can infer that at these times and these radial bins that are close to the inner core, strong convection exist.\n", "\n", "If you compare these convective signals with the evolution of Hurricane Florence's intensity, you can see that they correspond to really strong intensities, above 80 knots!\n", "\n", "Second, notice at the times corresponding to stronger intensities, lower mean 92 GHz PCT (lower than 250 Kelvin) also extend farther out, radially. In the context of our averaging approach, the larger extent of lower mean 92 GHz PCT may correspond to an increase in the number of strong, isolated convective cells or an increase in the number of moderate, widespread convective cells.\n", "\n", "Nonetheless, the timeseries composite shows a strong relationship between the strength and location of convective signatures (hence, convection) and a tropical cyclone's intensity." ] }, { "cell_type": "markdown", "id": "28b5fed1", "metadata": { "id": "28b5fed1" }, "source": [ "## Practice\n", "1. Instead of calculating and plotting the mean in each bin, obtain and plot the number of pixel count (`count`) available in each radial bin. You will have to change the countour levels when making the plot. Why does the pixel count have that pattern? What does the pixel count pattern say about the area involved in the calculation of a statistic like the mean?\n", "2. We have seen how the passive microwave convective signatures relate to the intensity of Hurricane Florence. Repeat the timeseries composite above to show how the GPROF retrieved surface precipitation rate changes as the environmental humidity around Hurricane Florence changes.\n", "\n", " **Hint:** Experiment with a relative humidity time series at the vertical level and averaging region of your choice." ] }, { "cell_type": "markdown", "id": "TatB3zIhU08B", "metadata": { "id": "TatB3zIhU08B" }, "source": [ "## Close the File\n", "When loading data from a NetCDF file, **always remember to close the file**. A best practice would be to close the file immediately after loading the variable or attribute of interest. However, since we're loading various variables and attributes throughout this notebook, we will close the files at the end of this notebook using the command below." ] }, { "cell_type": "code", "execution_count": null, "id": "hvQruJ1NU73b", "metadata": { "id": "hvQruJ1NU73b" }, "outputs": [], "source": [ "DS[ENV_FILE_NAME].close()\n", "\n", "for overpass_file_name in OVERPASS_FILE_NAMES:\n", " DS[overpass_file_name].close()" ] }, { "cell_type": "markdown", "id": "33f46a3a", "metadata": { "id": "33f46a3a" }, "source": [ "## Final Thoughts\n", "In this tutorial, you learned how to generate a simple timeseries composite from observations of Hurricane Florence (2018) and saw how convection evolves with intensity and vice versa. This timeseries composite represents one of many ways you can use TC PRIMED data. You're not limited to generating a timeseries composite. You can create other types of composites, like a composite in the x and y dimensions, and using other criteria such as observations that meet only certain environmental characteristics." ] }, { "cell_type": "markdown", "id": "0764cbdf", "metadata": { "id": "0764cbdf" }, "source": [ "## Data Statement\n", "- Razin, Muhammad Naufal; Slocum, Christopher J.; Knaff, John A.; Brown, Paula J. 2023. Tropical Cyclone PRecipitation, Infrared, Microwave, and Environmental Dataset (TC PRIMED). v01r00. NOAA National Centers for Environmental Information. https://doi.org/10.25921/dmy1-0595." ] }, { "cell_type": "markdown", "id": "d65b93c4", "metadata": { "id": "d65b93c4" }, "source": [ "## References\n", "- Cecil, D. J., and T. Chronis, 2018: Polarization-corrected temperatures for 10-, 19-, 37-, and 89-GHz passive microwave frequencies. J. Appl. Meteor. Climatol., 57, 2249–2265, https://doi.org/10.1175/JAMC-D-18-0022.1." ] }, { "cell_type": "markdown", "id": "0b4beeaa", "metadata": { "id": "0b4beeaa" }, "source": [ "## Metadata\n", "- Language / package(s)\n", " - Python\n", " - NetCDF\n", " - Scipy\n", " - Matplotlib\n", "- Domain\n", " - NOAA\n", " - NASA\n", " - JTWC\n", "- Application keywords\n", " - Satellite passive microwave\n", " - Timeseries\n", "- Geophysical keywords\n", " - Tropical cyclones\n", " - Convection" ] }, { "cell_type": "code", "execution_count": null, "id": "5c443693", "metadata": { "id": "5c443693" }, "outputs": [], "source": [] } ], "metadata": { "colab": { "provenance": [] }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "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.9.15" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 5 }