Skew-T Analysis

Create a Skew-T plot using remote data from University of Wyoming.

This example uses example data from the University of Wyoming sounding archive for 12 UTC 31 October 2016 for Minneapolis, MN (MPX).

Imports

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

import metpy.calc as mpcalc
from metpy.cbook import get_test_data
from metpy.plots import add_metpy_logo, SkewT
from metpy.units import units

from datetime import datetime
from siphon.simplewebservice.wyoming import WyomingUpperAir

Obtain Data and Format

This requires an internet connection to access the sounding data from a remote server at the University of Wyoming.

First we will create variables for date, time and station.
Format: datetime(YYYY, MM, DD, HH)

The station entry will need the be the three letter identifier of the station you want to look at. The National Center for Atmospheric Research (NCAR) Research Applications Labratory (RAL) continously updates a detailed list of all stations.

# Create variables for preferred date, time and station
preferred_date = datetime(2016, 10, 26, 12)
station = 'MPX'
# Read remote sounding data based on preferred_date and station
sounding_data = WyomingUpperAir.request_data(preferred_date, station)
---------------------------------------------------------------------------
HTTPError                                 Traceback (most recent call last)
Cell In[3], line 2
      1 # Read remote sounding data based on preferred_date and station
----> 2 sounding_data = WyomingUpperAir.request_data(preferred_date, station)

File ~/miniconda3/envs/cookbook-dev/lib/python3.10/site-packages/siphon/simplewebservice/wyoming.py:50, in WyomingUpperAir.request_data(cls, time, site_id, **kwargs)
     30 r"""Retrieve upper air observations from the Wyoming archive.
     31 
     32 Parameters
   (...)
     47 
     48 """
     49 endpoint = cls()
---> 50 df = endpoint._get_data(time, site_id)
     51 return df

File ~/miniconda3/envs/cookbook-dev/lib/python3.10/site-packages/siphon/simplewebservice/wyoming.py:70, in WyomingUpperAir._get_data(self, time, site_id)
     53 def _get_data(self, time, site_id):
     54     r"""Download and parse upper air observations from an online archive.
     55 
     56     Parameters
   (...)
     68 
     69     """
---> 70     raw_data = self._get_data_raw(time, site_id)
     71     soup = BeautifulSoup(raw_data, 'html.parser')
     72     tabular_data = StringIO(soup.find_all('pre')[0].contents[0])

File ~/miniconda3/envs/cookbook-dev/lib/python3.10/site-packages/siphon/simplewebservice/wyoming.py:144, in WyomingUpperAir._get_data_raw(self, time, site_id)
    126 """Download data from the University of Wyoming's upper air archive.
    127 
    128 Parameters
   (...)
    138 
    139 """
    140 path = ('?region=naconf&TYPE=TEXT%3ALIST'
    141         '&YEAR={time:%Y}&MONTH={time:%m}&FROM={time:%d%H}&TO={time:%d%H}'
    142         '&STNM={stid}').format(time=time, stid=site_id)
--> 144 resp = self.get_path(path)
    145 # See if the return is valid, but has no data
    146 if resp.text.find("Can't") != -1:

File ~/miniconda3/envs/cookbook-dev/lib/python3.10/site-packages/siphon/http_util.py:457, in HTTPEndPoint.get_path(self, path, query)
    434 def get_path(self, path, query=None):
    435     """Make a GET request, optionally including a query, to a relative path.
    436 
    437     The path of the request includes a path on top of the base URL
   (...)
    455 
    456     """
--> 457     return self.get(self.url_path(path), query)

File ~/miniconda3/envs/cookbook-dev/lib/python3.10/site-packages/siphon/http_util.py:492, in HTTPEndPoint.get(self, path, params)
    490     else:
    491         text = resp.text
--> 492     raise requests.HTTPError('Error accessing {0}\n'
    493                              'Server Error ({1:d}: {2})'.format(resp.request.url,
    494                                                                 resp.status_code,
    495                                                                 text))
    496 return resp

HTTPError: Error accessing http://weather.uwyo.edu/cgi-bin/sounding/?region=naconf&TYPE=TEXT%3ALIST&YEAR=2016&MONTH=10&FROM=2612&TO=2612&STNM=MPX
Server Error (503: Sorry, the server is too busy to process your request.
Please try again later.
)
sounding_data
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[4], line 1
----> 1 sounding_data

NameError: name 'sounding_data' is not defined

Assign Units

We will pull the data out of the example dataset into individual variables and assign units. This is explained in further detain in the Simple Sounding notebook and in the Metpy documentation.

pres = sounding_data['pressure'].values * units.hPa
temp = sounding_data['temperature'].values * units.degC
dewpoint = sounding_data['dewpoint'].values * units.degC
wind_speed = sounding_data['speed'].values * units.knots
wind_dir = sounding_data['direction'].values * units.degrees
u = sounding_data['u_wind'].values * units.knots
v = sounding_data['v_wind'].values * units.knots
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[5], line 1
----> 1 pres = sounding_data['pressure'].values * units.hPa
      2 temp = sounding_data['temperature'].values * units.degC
      3 dewpoint = sounding_data['dewpoint'].values * units.degC

NameError: name 'sounding_data' is not defined

Create Sounding Plot

# Create figure and set size
fig = plt.figure(figsize=(9, 9))
skew = SkewT(fig, rotation=45)

# Plot temperature and dewpoint lines
skew.plot(pres, temp, 'red')
skew.plot(pres, dewpoint, 'green')

# Plot wind barbs
my_interval = np.arange(100, 1000, 25) * units('hPa')
ix = mpcalc.resample_nn_1d(pres, my_interval)
skew.plot_barbs(pres[ix], u[ix], v[ix], y_clip_radius=0.001)

# Improve labels and set axis limits
skew.ax.set_xlabel('Temperature (\N{DEGREE CELSIUS})')
skew.ax.set_ylabel('Pressure (hPa)')
skew.ax.set_ylim(1000, 100)

# Add the relevant special lines
skew.plot_dry_adiabats(t0=np.arange(233, 533, 10) * units.K, alpha=0.25, color='orangered')
skew.plot_moist_adiabats(t0=np.arange(233, 400, 5) * units.K, alpha=0.25, color='tab:green')
skew.plot_mixing_lines(pressure=np.arange(1000, 99, -25) * units.hPa, linestyle='dotted', color='tab:blue')

# Add the MetPy logo!
fig = plt.gcf()
add_metpy_logo(fig, 115, 100, size='small');

# Add some descriptive titles
plt.title('{} Sounding'.format(station), loc='left')
plt.title('Valid Time: {}'.format(preferred_date), loc='right');
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[6], line 6
      3 skew = SkewT(fig, rotation=45)
      5 # Plot temperature and dewpoint lines
----> 6 skew.plot(pres, temp, 'red')
      7 skew.plot(pres, dewpoint, 'green')
      9 # Plot wind barbs

NameError: name 'pres' is not defined
../../_images/0d8b4da5877b635b64ad090c4a73c3612c1f29ee324dc522c523f3b54360d0fd.png