{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "
\n", "\n", "
\n", "\"Unidata\n", "
\n", "\n", "

MetPy Skew-T

\n", "

Unidata AMS 2021 Student Conference

\n", "\n", "
\n", "
\n", "\n", "---\n", "\n", "
\"Skew-T
\n", "\n", "\n", "### Focuses\n", "* Read in sounding data from the University of Wyoming archive.\n", "* Plot the data on a skew-T diagram using MetPy.\n", "* Add a hodograph inset to the skew-T\n", "\n", "\n", "### Objectives\n", "1. [Access archived sounding data](#1.-Access-archived-sounding-data)\n", "1. [Plot the Skew-T](#2.-Plot-the-Skew-T)\n", "1. [Add a hodograph](#3.-Add-a-hodograph)\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Imports" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from datetime import datetime\n", "\n", "import matplotlib.pyplot as plt\n", "from mpl_toolkits.axes_grid1.inset_locator import inset_axes\n", "from metpy.plots import SkewT, Hodograph\n", "from metpy.units import pandas_dataframe_to_unit_arrays, units\n", "import numpy as np\n", "from siphon.simplewebservice.wyoming import WyomingUpperAir\n", "from metpy.calc import wind_speed" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Access archived sounding data\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first step in plotting a skew-T is accessing the sounding data. We're going to download some observed sounding data from the University of Wyoming sounding archive from 00z on 15 April 2015 at Topeka, KS during a major tornado outbreak. First, we create a datetime object for MetPy to use to select the correct time and station from the Wyoming archive." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dt = datetime(2012, 4, 15, 0)\n", "station = 'TOP'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we'll download the data from the Wyoming archive into a Pandas dataframe with units. You'll need an internet connection for this step." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df = WyomingUpperAir.request_data(dt, station)\n", "data = pandas_dataframe_to_unit_arrays(df)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we'll split that Pandas dataframe up into individual arrays for each variable with units, and calculate wind speed from the wind components." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "p = data['pressure']\n", "T = data['temperature']\n", "Td = data['dewpoint']\n", "u = data['u_wind']\n", "v = data['v_wind']\n", "spd = wind_speed(u,v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "Top\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Plot the Skew-T\n", "\n", "Now we'll plot the data we downloaded on a skew-T diagram.\n", "\n", "First, we'll create a figure using Matplotlib and modify it into a skew-T plot\n", "using MetPy's SkewT class." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig = plt.figure(figsize=(9, 11))\n", "skew = SkewT(fig, rotation=45)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we'll add code to plot temperature and dewpoint data as red and green lines on the Skew-T, and add the wind data as barbs along the right side of the plot." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "skew.plot(p, T, 'r')\n", "skew.plot(p, Td, 'g')\n", "skew.plot_barbs(p[::3], u[::3], v[::3], y_clip_radius=0.03)\n", "fig" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can set the limits of the plot using set_xlim and set_ylim." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "skew.ax.set_xlim(-30, 40)\n", "skew.ax.set_ylim(1020, 100)\n", "fig" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also add dry adiabats, moist adiabats, and mixing ratio lines with the next three lines of code." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "skew.plot_dry_adiabats(alpha=0.25, color='orangered')\n", "skew.plot_moist_adiabats(alpha=0.25, color='tab:green')\n", "skew.plot_mixing_lines(linestyle='dotted', color='tab:blue')\n", "fig" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, let's add a title to the plot" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "skew.ax.set_title('{} Sounding'.format(station), loc='left')\n", "skew.ax.set_title('Valid Time: {}'.format(dt), loc='right')\n", "fig" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Top\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Add a hodograph\n", "\n", "In this section, we'll add a hodograph inset to the plot.\n", "The first section of code here is the same as the previous skew-T plot. The next two lines add a hodograph inset using matplotlib's inset_axes functionality and MetPy's Hodograph class." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig = plt.figure(figsize=(9, 11))\n", "skew = SkewT(fig, rotation=45)\n", "skew.plot(p, T, 'r')\n", "skew.plot(p, Td, 'g')\n", "skew.plot_barbs(p[::3], u[::3], v[::3], y_clip_radius=0.03)\n", "skew.ax.set_xlim(-30, 40)\n", "skew.ax.set_ylim(1020, 100)\n", "skew.plot_dry_adiabats(alpha=0.25, color='orangered')\n", "skew.plot_moist_adiabats(alpha=0.25, color='tab:green')\n", "skew.plot_mixing_lines(linestyle='dotted', color='tab:blue')\n", "skew.ax.set_title('{} Sounding'.format(station), loc='left')\n", "skew.ax.set_title('Valid Time: {}'.format(dt), loc='right')\n", "\n", "#Add hodograph inset using matplotlib and MetPy\n", "ax_hod = inset_axes(skew.ax, '30%', '30%', loc=1)\n", "h = Hodograph(ax_hod, component_range=80)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we'll add a grid to the hodograph." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "h.add_grid(increment=20)\n", "fig" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, we'll plot the wind data below 150 hPa on the hodograph and color it by speed." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "h.plot_colormapped(u[p>150*units('hPa')], v[p>150*units('hPa')], spd[p>150*units('hPa')])\n", "fig" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Top\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## See also\n", "\n", "Documentation for:\n", "\n", "* [metpy.plots.SkewT](https://unidata.github.io/MetPy/latest/api/generated/metpy.plots.SkewT.html#metpy.plots.SkewT)\n", "* [metpy.plots.Hodograph](https://unidata.github.io/MetPy/latest/api/generated/metpy.plots.Hodograph.html#metpy.plots.Hodograph)\n", "\n", "## Other Notebooks\n", "\n", "* [MetPy and Soundings: Calculations](https://nbviewer.jupyter.org/github/Unidata/pyaos-ams-2021/blob/master/notebooks/analysis/metpy-soundings-calculations.ipynb)\n", "* [A more detailed introduction to plotting Skew-Ts](https://unidata.github.io/python-training/workshop/Skew_T/skewt-and-hodograph/)\n", "* [MetPy Mondays Skew-T Example Video](https://www.unidata.ucar.edu/blogs/developer/en/entry/metpy-mondays-making-a-basic)\n", "* [Skew-T Using Python-AWIPS Data](https://nbviewer.jupyter.org/github/Unidata/pyaos-ams-2021/blob/master/notebooks/visualization/python-awips-WorkingWithUpperAirObs.ipynb)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Top\n", "\n", "---" ] } ], "metadata": { "kernelspec": { "display_name": "Python [conda env:pyaos-ams-2021]", "language": "python", "name": "conda-env-pyaos-ams-2021-py" }, "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.7.9" } }, "nbformat": 4, "nbformat_minor": 4 }