SkewT and Hodograph

Unidata Logo

Upper Air and the Skew-T Log-P

Unidata Python Workshop


Example Skew-T

Questions

  1. Where can upper air data be found and what format is it in?
  2. How can I obtain upper air data programatically?
  3. How can MetPy be used to make a Skew-T Log-P diagram and associated fiducial lines?
  4. How are themodynamic calculations performed on upper-air data?

Table of Contents

  1. Obtain upper air data
  2. Make a Skew-T
  3. Thermodynamics
  4. Plotting a Hodograph
  5. Advanced Layout

1. Obtain upper air data

Overview

Upper air observations are generally reported as a plain text file in a tabular format that represents the down sampled raw data transmitted by the rawinsonde. Data are reported an mandatory levels and at levels of significant change. An example of sounding data may look like this:

-----------------------------------------------------------------------------
   PRES   HGHT   TEMP   DWPT   RELH   MIXR   DRCT   SKNT   THTA   THTE   THTV
    hPa     m      C      C      %    g/kg    deg   knot     K      K      K 
-----------------------------------------------------------------------------
 1000.0    270                                                               
  991.0    345   -0.3   -2.8     83   3.15      0      0  273.6  282.3  274.1
  984.0    403   10.2   -7.8     27   2.17    327      4  284.7  291.1  285.0
  963.0    581   11.8   -9.2     22   1.99    226     17  288.0  294.1  288.4
  959.7    610   11.6   -9.4     22   1.96    210     19  288.1  294.1  288.5

Data are available to download from the University of Wyoming archive, the Iowa State archive, and the Integrated Global Radiosonde Archive (IGRA). There is no need to download data manually. We can use the siphon library (also developed at Unidata) to request and download these data. Be sure to checkout the documentation on all of siphon's capabilities.

Getting our data

First, we need to create a datetime object that has the time of observation we are looking for. We can then request the data for a specific station. Note that if you provide an invalid time or station where no sounding data are present you will receive an error.

In [1]:
# Create a datetime for our request - notice the times are from laregest (year) to smallest (hour)
from datetime import datetime
request_time = datetime(1999, 5, 3, 12)
In [2]:
# Store the station name in a variable for flexibility and clarity
station = 'OUN'
In [3]:
# Import the Wyoming simple web service and request the data
# Don't worry about a possible warning from Pandas - it's related to our handling of units
from siphon.simplewebservice.wyoming import WyomingUpperAir
df = WyomingUpperAir.request_data(request_time, station)
In [4]:
# Let's see what we got in return
df.head()
Out[4]:
pressure height temperature dewpoint direction speed u_wind v_wind station station_number time latitude longitude elevation
0 966.0 345 18.2 16.9 180.0 15.0 -1.836970e-15 15.000000 OUN 72357 1999-05-03 12:00:00 35.18 -97.44 345.0
1 937.2 610 16.8 15.9 190.0 27.0 4.688501e+00 26.589809 OUN 72357 1999-05-03 12:00:00 35.18 -97.44 345.0
2 925.0 725 16.2 15.5 195.0 31.0 8.023390e+00 29.943701 OUN 72357 1999-05-03 12:00:00 35.18 -97.44 345.0
3 904.6 914 15.1 14.2 205.0 34.0 1.436902e+01 30.814465 OUN 72357 1999-05-03 12:00:00 35.18 -97.44 345.0
4 872.6 1219 13.3 12.1 210.0 38.0 1.900000e+01 32.908965 OUN 72357 1999-05-03 12:00:00 35.18 -97.44 345.0

We got a Pandas dataframe back, which is great. Sadly, Pandas does not play well with units, so we need to attach units and make some other kind of data structure. We've provided a helper function for this - it takes the dataframe with our special .units attribute and returns a dictionary where the keys are column (data series) names and the values are united arrays. This means we can still use the dictionary access syntax and mostly forget that it is not a data frame any longer.

Fist, let's look at the special attribute siphon added:

In [5]:
df.units
Out[5]:
{'pressure': 'hPa',
 'height': 'meter',
 'temperature': 'degC',
 'dewpoint': 'degC',
 'direction': 'degrees',
 'speed': 'knot',
 'u_wind': 'knot',
 'v_wind': 'knot',
 'station': None,
 'station_number': None,
 'time': None,
 'latitude': 'degrees',
 'longitude': 'degrees',
 'elevation': 'meter'}

Now let's import the helper and the units registry from MetPy and get units attached.

In [6]:
from metpy.units import pandas_dataframe_to_unit_arrays, units
sounding = pandas_dataframe_to_unit_arrays(df)
In [7]:
sounding
Out[7]:
{'pressure': array([966. , 937.2, 925. , 904.6, 872.6, 853. , 850. , 836. , 821. ,
        811.6, 782.3, 754.2, 726.9, 700. , 648.9, 624.6, 601.1, 595. ,
        587. , 576. , 555.7, 534.2, 524. , 500. , 473.3, 400. , 384.5,
        358. , 343. , 308.3, 300. , 276. , 273. , 268.5, 250. , 244.2,
        233. , 200. , 191.8, 190. , 174.2, 168. , 151. , 150. , 144. ,
        130.6, 118.4, 105. , 102.2, 100. ,  97.3,  94.7,  80.6,  76. ,
         73.7,  70. ,  61.8,  50. ,  48.6,  44.1,  34.6,  30. ,  29.9,
         26.4,  21.4,  20. ,  16.9,  16.2,  16.1,  15.4,  13.7,  11.3,
         10.7,  10.2,  10. ,   9.9]) <Unit('hectopascal')>,
 'height': array([  345,   610,   725,   914,  1219,  1411,  1441,  1581,  1734,
         1829,  2134,  2438,  2743,  3056,  3658,  3962,  4267,  4348,
         4453,  4600,  4877,  5182,  5331,  5690,  6096,  7340,  7620,
         8124,  8421,  9144,  9330,  9880,  9951, 10058, 10520, 10668,
        10967, 11930, 12192, 12252, 12802, 13032, 13716, 13760, 14021,
        14630, 15240, 15989, 16154, 16290, 16459, 16628, 17621, 17983,
        18167, 18480, 19244, 20550, 20726, 21336, 22860, 23750, 23774,
        24562, 25908, 26350, 27432, 27737, 27766, 28042, 28823, 30112,
        30480, 30785, 30940, 31008]) <Unit('meter')>,
 'temperature': array([ 18.2,  16.8,  16.2,  15.1,  13.3,  12.2,  12.4,  14. ,  14.4,
         13.7,  11.4,   9.1,   6.8,   4.4,  -1.4,  -4.4,  -7.3,  -8.1,
         -7.9,  -7.7,  -8.7,  -9.8, -10.3, -13.5, -17.1, -28.1, -30.7,
        -35.3, -37.1, -43.5, -45.1, -49.9, -50.4, -51.1, -54.1, -55. ,
        -56.7, -57.5, -59.3, -59.7, -55.3, -53.5, -54.2, -54.3, -56.1,
        -59.2, -62.3, -66.1, -62.6, -59.7, -60.7, -61.7, -62.3, -64.7,
        -65.9, -64.5, -62.1, -62.1, -61.8, -60.7, -57.9, -56.3, -56.3,
        -56.3, -51.6, -50.1, -50.6, -50.7, -50.7, -50.1, -48.5, -41.1,
        -41.7, -42.2, -42.5, -42.7]) <Unit('degree_Celsius')>,
 'dewpoint': array([ 16.9,  15.9,  15.5,  14.2,  12.1,  10.8,   8.6,   0. ,  -3.6,
         -4.4,  -6.9,  -9.5, -12. , -14.6, -15.8, -16.4, -16.9, -17.1,
        -27.9, -42.7, -44.1, -45.6, -46.3, -45.5, -47.1, -52.1, -50.4,
        -47.3, -57.1, -57.9, -58.1, -60.9, -61.4, -62.1, -65.1, -65.6,
        -66.7, -70.5, -72.3, -72.7, -72.6, -72.5, -78. , -78.3, -81.1,
        -83.3, -85.4, -88.1, -85.7, -83.7, -84.7, -85.7, -85.3, -87. ,
        -87.9, -87.5, -86.1, -86.1, -85.8, -84.9, -82.6, -81.3, -81.3,
        -81.3, -78.1, -77.1, -77.6, -77.7, -77.7, -77.4, -76.5, -71.1,
        -71.7, -72.2, -72.5, -71.7]) <Unit('degree_Celsius')>,
 'direction': array([180., 190., 195., 205., 210., 214., 215., 215., 215., 215., 230.,
        250., 260., 260., 275., 280., 280., 277., 274., 269., 260., 250.,
        250., 250., 255., 260., 255., 258., 260., 265., 260., 260., 260.,
        260., 260., 260., 261., 265., 265., 270., 280., 270., 240., 245.,
        252., 270., 245., 245., 245., 240., 240., 241., 244., 245., 230.,
        205., 175., 125., 120., 150.,  85.,  50.,  50.,  63.,  85.,  80.,
         75.,  70.,  71.,  85., 113., 157., 170., 310.,  nan,  nan]) <Unit('degree')>,
 'speed': array([15., 27., 31., 34., 38., 33., 32., 29., 26., 24., 18., 16., 20.,
        23., 25., 25., 26., 27., 29., 31., 35., 33., 33., 33., 31., 40.,
        39., 45., 48., 56., 57., 63., 64., 64., 58., 60., 60., 59., 57.,
        54., 37., 39., 43., 41., 35., 21., 22., 26., 27., 21., 20., 19.,
        15., 13., 11.,  8.,  8.,  9., 11.,  6., 15., 14., 14., 18., 25.,
        22., 17., 16., 16., 14., 10.,  3.,  1.,  4., nan, nan]) <Unit('knot')>,
 'u_wind': array([-1.83697020e-15,  4.68850080e+00,  8.02339040e+00,  1.43690209e+01,
         1.90000000e+01,  1.84533658e+01,  1.83544460e+01,  1.66337167e+01,
         1.49129873e+01,  1.37658345e+01,  1.37888000e+01,  1.50350819e+01,
         1.96961551e+01,  2.26505783e+01,  2.49048675e+01,  2.46201938e+01,
         2.56050016e+01,  2.67987461e+01,  2.89293575e+01,  3.09952785e+01,
         3.44682714e+01,  3.10098565e+01,  3.10098565e+01,  3.10098565e+01,
         2.99437006e+01,  3.93923101e+01,  3.76711072e+01,  4.40166420e+01,
         4.72707721e+01,  5.57869031e+01,  5.61340419e+01,  6.20428884e+01,
         6.30276962e+01,  6.30276962e+01,  5.71188497e+01,  5.90884652e+01,
         5.92613004e+01,  5.87754872e+01,  5.67830978e+01,  5.40000000e+01,
         3.64378869e+01,  3.90000000e+01,  3.72390924e+01,  3.71586193e+01,
         3.32869781e+01,  2.10000000e+01,  1.99387713e+01,  2.35640025e+01,
         2.44703102e+01,  1.81865335e+01,  1.73205081e+01,  1.66177744e+01,
         1.34819107e+01,  1.17820012e+01,  8.42648887e+00,  3.38094609e+00,
        -6.97245942e-01, -7.37236840e+00, -9.52627944e+00, -3.00000000e+00,
        -1.49429205e+01, -1.07246222e+01, -1.07246222e+01, -1.60381174e+01,
        -2.49048675e+01, -2.16657706e+01, -1.64207390e+01, -1.50350819e+01,
        -1.51282972e+01, -1.39467258e+01, -9.20504853e+00, -1.17219339e+00,
        -1.73648178e-01,  3.06417777e+00,             nan,             nan]) <Unit('knot')>,
 'v_wind': array([ 1.50000000e+01,  2.65898093e+01,  2.99437006e+01,  3.08144648e+01,
         3.29089653e+01,  2.73582399e+01,  2.62128654e+01,  2.37554093e+01,
         2.12979532e+01,  1.96596491e+01,  1.15701770e+01,  5.47232229e+00,
         3.47296355e+00,  3.99390809e+00, -2.17889357e+00, -4.34120444e+00,
        -4.51485262e+00, -3.29047227e+00, -2.02293774e+00,  5.41024600e-01,
         6.07768622e+00,  1.12866647e+01,  1.12866647e+01,  1.12866647e+01,
         8.02339040e+00,  6.94592711e+00,  1.00939428e+01,  9.35602609e+00,
         8.33511253e+00,  4.88072159e+00,  9.89794613e+00,  1.09398352e+01,
         1.11134834e+01,  1.11134834e+01,  1.00715943e+01,  1.04188907e+01,
         9.38606790e+00,  5.14218882e+00,  4.96787734e+00,  9.91963907e-15,
        -6.42498257e+00,  7.16418378e-15,  2.15000000e+01,  1.73273487e+01,
         1.08155948e+01,  3.85763742e-15,  9.29760176e+00,  1.09880748e+01,
         1.14106931e+01,  1.05000000e+01,  1.00000000e+01,  9.21138278e+00,
         6.57556720e+00,  5.49403740e+00,  7.07066371e+00,  7.25046230e+00,
         7.96955758e+00,  5.16218793e+00,  5.50000000e+00,  5.19615242e+00,
        -1.30733614e+00, -8.99902654e+00, -8.99902654e+00, -8.17182900e+00,
        -2.17889357e+00, -3.82025991e+00, -4.39992377e+00, -5.47232229e+00,
        -5.20909047e+00, -1.22018040e+00,  3.90731128e+00,  2.76151456e+00,
         9.84807753e-01, -2.57115044e+00,             nan,             nan]) <Unit('knot')>,
 'station': array(['OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN',
        'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN',
        'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN',
        'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN',
        'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN',
        'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN',
        'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN',
        'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN', 'OUN',
        'OUN', 'OUN', 'OUN', 'OUN'], dtype=object),
 'station_number': array([72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357,
        72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357,
        72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357,
        72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357,
        72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357,
        72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357,
        72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357,
        72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357, 72357,
        72357, 72357, 72357, 72357]),
 'time': array(['1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000',
        '1999-05-03T12:00:00.000000000', '1999-05-03T12:00:00.000000000'],
       dtype='datetime64[ns]'),
 'latitude': array([35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18,
        35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18,
        35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18,
        35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18,
        35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18,
        35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18,
        35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18,
        35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18, 35.18,
        35.18, 35.18, 35.18, 35.18]) <Unit('degree')>,
 'longitude': array([-97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44,
        -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44,
        -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44,
        -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44,
        -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44,
        -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44,
        -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44,
        -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44,
        -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44, -97.44,
        -97.44, -97.44, -97.44, -97.44]) <Unit('degree')>,
 'elevation': array([345., 345., 345., 345., 345., 345., 345., 345., 345., 345., 345.,
        345., 345., 345., 345., 345., 345., 345., 345., 345., 345., 345.,
        345., 345., 345., 345., 345., 345., 345., 345., 345., 345., 345.,
        345., 345., 345., 345., 345., 345., 345., 345., 345., 345., 345.,
        345., 345., 345., 345., 345., 345., 345., 345., 345., 345., 345.,
        345., 345., 345., 345., 345., 345., 345., 345., 345., 345., 345.,
        345., 345., 345., 345., 345., 345., 345., 345., 345., 345.]) <Unit('meter')>}

Top


2.Make a Skew-T

Now that we have data, we can actually start making our Skew-T Log-P diagram. This consists of:

  • Import matplotlib
  • Importing the SkewT object
  • Creating a figure
  • Creating a SkewT object based upon that figure
  • Plotting our data
In [8]:
import matplotlib.pyplot as plt
from metpy.plots import SkewT
%matplotlib inline
In [9]:
# Create a new figure. The dimensions here give a good aspect ratio
fig = plt.figure(figsize=(10, 10))
skew = SkewT(fig)
In [10]:
# Plot the data using normal plotting functions, all of the transforms
# happen in the background!
skew.plot(sounding['pressure'], sounding['temperature'], color='tab:red')
skew.ax.set_ylim(1050,100)
skew.ax.set_xlim(-50,20)
# Redisplay the figure
fig
Out[10]:
In [11]:
# Plot a isotherm using axvline (axis vertical line)
skew.ax.axvline([0] * units.degC, color='cyan', linestyle='--')

# Redisplay the figure
fig
Out[11]:
EXERCISE Part 1:
  • Download your own data using the Wyoming upper-air archive. Have a look at the documentation to help get started.
  • Attach units using the unit helper.
In [12]:
# Import the Wyoming simple web service upper air object
# YOUR CODE GOES HERE
In [13]:
# Create the datetime and station variables you'll need
# YOUR CODE GOES HERE
In [14]:
# Make the request for the data - assign it to a dataframe called my_df
# YOUR CODE GOES HERE
In [15]:
# Attach units to the data - assign it to the variable my_sounding
# YOUR CODE GOES HERE
SOLUTION
In [16]:
# %load solutions/skewt_get_data.py

# Cell content replaced by load magic replacement.
# Import the Wyoming simple web service upper air object
from siphon.simplewebservice.wyoming import WyomingUpperAir

# Create the datetime and station variables you'll need
request_time = datetime(2011, 4, 14, 18)
station = 'OUN'

# Make the request for the data
my_df = WyomingUpperAir.request_data(request_time, station)

# Attach units to the data
my_sounding = pandas_dataframe_to_unit_arrays(my_df)
EXERCISE Part 2:
  • Make a figure and SkewT object.
  • Plot the temperature and dewpoint in red and green lines.
  • Set the axis limits to sensible limits with set_xlim and set_ylim.
In [17]:
# Make a figure called my_fig

# Make a SkewT object called my_skew

# Plot the temperature and dewpoint
SOLUTION
In [18]:
# %load solutions/skewt_make_figure.py

# Cell content replaced by load magic replacement.
# Make a figure
my_fig = plt.figure(figsize=(10, 10))

# Make a SkewT object
my_skew = SkewT(my_fig)

# Plot the temperature and dewpoint
my_skew.plot(my_sounding['pressure'], my_sounding['temperature'], linewidth=2, color='tab:red')
my_skew.plot(my_sounding['pressure'], my_sounding['dewpoint'], linewidth=2, color='tab:blue')
Out[18]:
[<matplotlib.lines.Line2D at 0x7f5e8b6a79d0>]
EXERCISE Part 3:
  • Plot wind barbs using the plot_barbs method of the SkewT object.
  • Add the fiducial lines for dry adiabats, moist adiabats, and mixing ratio lines using the plot_dry_adiabats(), plot_moist_adiabats(), plot_mixing_lines() functions.
In [19]:
# Plot wind barbs

# Add dry adiabats

# Add moist adiabats

# Add mixing ratio lines

# Redisplay figure
SOLUTION
In [20]:
# %load solutions/skewt_wind_fiducials.py

# Cell content replaced by load magic replacement.
# Plot wind barbs
my_skew.plot_barbs(my_sounding['pressure'], my_sounding['u_wind'], my_sounding['v_wind'])

# Add dry adiabats
my_skew.plot_dry_adiabats()

# Add moist adiabats
my_skew.plot_moist_adiabats()

# Add mixing ratio lines
my_skew.plot_mixing_lines()

# Redisplay figure
my_fig
Out[20]:

Top


3.Thermodynamics

Using MetPy's calculations functions we can calculate thermodynamic paramters like LCL, LFC, EL, CAPE, and CIN. Let's start off with the LCL.

In [21]:
# Add the dewpoint line to our plot we were working with
skew.plot(sounding['pressure'], sounding['dewpoint'], linewidth=2, color='tab:blue')
Out[21]:
[<matplotlib.lines.Line2D at 0x7f5e8b494750>]
In [22]:
# Get our basic plot we were working with ready to plot new things on

# Set some good axis limits
skew.ax.set_xlim(-60, 30)
skew.ax.set_ylim(1000, 100)

# Add relevant fiducial lines
skew.plot_dry_adiabats()
skew.plot_moist_adiabats()
skew.plot_mixing_lines()

fig
Out[22]:
In [23]:
import metpy.calc as mpcalc
In [24]:
lcl_pressure, lcl_temperature = mpcalc.lcl(sounding['pressure'][0],
                                           sounding['temperature'][0],
                                           sounding['dewpoint'][0])
print(lcl_pressure, lcl_temperature)
947.5050980075163 hectopascal 16.5956981693401 degree_Celsius

We can this as a point on our sounding using the scatter method.

In [25]:
skew.ax.axhline(y=lcl_pressure, color='k', linewidth=0.75)
fig
Out[25]:

We can also calculate the ideal parcel profile and plot it.

In [26]:
sounding['profile'] = mpcalc.parcel_profile(sounding['pressure'], sounding['temperature'][0], sounding['dewpoint'][0])
print(sounding['profile'])
[291.34999999999997 289.3328742971223 288.83644733895886 287.98694490856474 286.6022061473723 285.720203249939 285.5828020058605 284.93283458953607 284.21985805296583 283.76393842487647 282.29490892845496 280.81233547092194 279.2954220523558 277.71888551880875 274.46643913578544 272.78321395298457 271.05879097547745 270.5943305023465 269.97405171792434 269.0996727167148 267.41643753922017 265.5263779708061 264.58763137213907 262.2615281871119 259.4590386032502 250.32395058674635 248.0653598159943 243.88985430707118 241.33663505392926 234.85386523891404 233.17624886311145 228.03032505204118 227.35516500400587 226.3286939486981 221.93062666264655 220.49074933321572 217.6240032208801 208.4615550485471 206.00199651687453 205.4514147025197 200.44233152694054 198.38445151202512 192.44148432697258 192.0770470318521 189.8527261196877 184.6325200127664 179.53384878058887 173.4798302074525 172.14577055358134 171.0791302167014 169.74689612106994 168.43879338225148 160.85851076807472 158.1810248694957 156.79866017263024 154.5087128843014 149.10687664352014 140.3506548398376 139.21677124549166 135.40622798809386 126.34089665263664 121.29636599855316 121.1807420338651 116.94734799407591 110.13966195597962 108.031610947383 102.95772415074347 101.72118885642519 101.5414425967192 100.26034635785595 96.96592701235348 91.77585859574747 90.35673956525376 89.1300463179209 88.62732979907548 88.37327405149297] kelvin
In [27]:
# Plot the profile
skew.plot(sounding['pressure'], sounding['profile'], color='black')

# Redisplay the figure
fig
Out[27]: