python-awips/examples/notebooks/Upper_Air_BUFR_Soundings.ipynb

190 lines
121 KiB
Text
Raw Normal View History

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following notebook takes you through the stepd of retreiving an Upper Air vertical profile from an AWIPS EDEX server, and plotting with Matplotlib and MetPy.\n",
"\n",
"The **bufrua** plugin returns separate objects for parameters at **mandatory levels** and at **significant temperature levels**. For the SkewT/LogP plot, significant temperature levels are used to plot the pressure, temperature, and dewpoint lines, while mandatory levels are used to plot the wind profile."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"%matplotlib inline\n",
"from awips.dataaccess import DataAccessLayer\n",
"import matplotlib.tri as mtri\n",
"import matplotlib.pyplot as plt\n",
"from mpl_toolkits.axes_grid1.inset_locator import inset_axes\n",
"import numpy as np\n",
"import math\n",
"from metpy.calc import get_wind_speed, get_wind_components, lcl, dry_lapse, parcel_profile\n",
"from metpy.plots import SkewT, Hodograph\n",
"from metpy.units import units, concatenate\n",
"\n",
"# Set EDEX host\n",
"DataAccessLayer.changeEDEXHost(\"edex-cloud.unidata.ucar.edu\")\n",
"request = DataAccessLayer.newDataRequest()\n",
"\n",
"# Data type bufrua\n",
"request.setDatatype(\"bufrua\")\n",
"availableLocs = DataAccessLayer.getAvailableLocationNames(request)\n",
"availableLocs.sort()"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# Parameters\n",
"MAN_PARAMS = set(['prMan', 'htMan', 'tpMan', 'tdMan', 'wdMan', 'wsMan'])\n",
"SIGT_PARAMS = set(['prSigT', 'tpSigT', 'tdSigT'])\n",
"request.setParameters(\"wmoStaNum\", \"validTime\", \"rptType\", \"staElev\", \"numMand\",\n",
" \"numSigT\", \"numSigW\", \"numTrop\", \"numMwnd\", \"staName\")\n",
"request.getParameters().extend(MAN_PARAMS)\n",
"request.getParameters().extend(SIGT_PARAMS)\n",
"\n",
"station = \"72562\" # KLBF\n",
"request.setLocationNames(station)\n",
"\n",
"datatimes = DataAccessLayer.getAvailableTimes(request)\n",
"\n",
"# Get most recent record\n",
"response = DataAccessLayer.getGeometryData(request,times=datatimes[-2].validPeriod)\n",
"\n",
"# Initialize data arrays\n",
"prMan,wdMan,wsMan = np.array([]),np.array([]),np.array([])\n",
"prSig,tpSig,tdSig = np.array([]),np.array([]),np.array([])\n",
"manGeos = []\n",
"sigtGeos = []\n",
"\n",
"# Build ordered arrays\n",
"for ob in response:\n",
" if set(ob.getParameters()) & MAN_PARAMS:\n",
" manGeos.append(ob)\n",
" prMan = np.append(prMan,ob.getNumber(\"prMan\"))\n",
" wdMan = np.append(wdMan,ob.getNumber(\"wdMan\"))\n",
" wsMan = np.append(wsMan,ob.getNumber(\"wsMan\"))\n",
" continue\n",
" if set(ob.getParameters()) & SIGT_PARAMS:\n",
" sigtGeos.append(ob)\n",
" prSig = np.append(prSig,ob.getNumber(\"prSigT\"))\n",
" tpSig = np.append(tpSig,ob.getNumber(\"tpSigT\"))\n",
" tdSig = np.append(tdSig,ob.getNumber(\"tdSigT\"))\n",
" continue"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"sounding_title = str(ob.getLocationName()) + \" \" + str(ob.getDataTime())\n",
"\n",
"# Need to sort mandatory (not sigT) levels because of the 1000.MB interpolation inclusion\n",
"ps = prMan.argsort()[::-1]\n",
"wpres = prMan[ps]\n",
"direc = wdMan[ps]\n",
"spd = wsMan[ps]\n",
"\n",
"prSig[prSig <= -9999] = np.nan\n",
"tpSig[tpSig <= -9999] = np.nan\n",
"tdSig[tdSig <= -9999] = np.nan\n",
"wpres[wpres <= -9999] = np.nan\n",
"direc[direc <= -9999] = np.nan\n",
"spd[spd <= -9999] = np.nan\n",
"\n",
"u,v = get_wind_components(spd, np.deg2rad(direc))\n",
"p = (prSig/100) * units.mbar\n",
"wpres = (wpres/100) * units.mbar\n",
"T = (tpSig-273.15) * units.degC\n",
"Td = (tdSig-273.15) * units.degC"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA9EAAANsCAYAAABcZCvYAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAAPYQAAD2EBqD+naQAAIABJREFUeJzs3Xd8VuX9//HXlYQR2UsEAQUFWYosZ60oiKh1oFVx27q+\nVat1a7VFRf1ZrXW01lmcuBCso0UFwVUVCQFZLjayd1iBJPf5/XHuJDcx407us+77ej8fjzw4uXPu\ncz7vXFH45JzrOsZxHERERERERESkZllhFyAiIiIiIiKSLtREi4iIiIiIiCRJTbSIiIiIiIhIktRE\ni4iIiIiIiCRJTbSIiIiIiIhIktREi4iIiIiIiCRJTbSIiIiIiIhIktREi4iIiIiIiCRJTbSIiIiI\niIhIktREi4iIiIiIiCRJTbSIiIiIiIhIktREi4iIiIiIiCRJTbSIiIiIiIhIktREi4iIiIiIiCRJ\nTbSIiIiIiIhIktREi4iIiIiIiCRJTbSIiIiIiIhIktREi4iIiIiIiCRJTbSIiIiIiIhIktREi4iI\niIiIiCRJTbSIiIiIiIhIktREi4iIiIiIiCRJTbSIiIiIiIhIktREi4iIiIiIiCRJTbSIiIiIiIhI\nktREi4iIiIiIiCRJTbSIiIiIiIhIktREi4iIiIiIiCRJTbSIiIiIiIhIktREi4iIiIiIiCRJTbSI\niIiIiIhIktREi4iIiIiIiCRJTbSIiIiIiIhIktREi4iIiIiIiCRJTbSIiIiIiIhIktREi4iIiIiI\niCRJTbSIiIiIiIhIktREi4iIiIiIiCRJTbSIiIiIiIhIktREi4iIiIiIiCRJTbSIiIiIiIhIktRE\ni4iIiIiIiCRJTbSIiIiIiIhIktREi4iIiIiIiCRJTbSIiIiIiIhIktREi4iIiIiIiCRJTbSIiIiI\niIj4xhhzjjHGhF2HV9REi4iIiIiIiC+MMQOAV4D/S3itlzEmbXvRtC1cREREREREIq+05+wOYIxp\nCMwBHg2tohSpiRYRERERERG/rI3/2Sb+Z1H8zwEh1OIJNdEiIiIiIiLil92aaMdxShI/T0dqokVE\nRERERMQv2+J/Vmya1USLiIhI+jPGPGeMiVXzcUh8vyxjzK3GmMnGmHXGmF3GmCXGmMeMMS0qOW5l\nxyoxxtxcRR2/McZMNcZsNcZsN8bMMMacmvD1bsaYx40xs+Nf326MmWaMuTjJnAOMMaONMd8bYwqN\n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\n4i8ljDF/wm2gRzmOc08
"text/plain": [
"<matplotlib.figure.Figure at 0x7f50dd00be90>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Create a skewT plot\n",
"plt.rcParams['figure.figsize'] = (8, 10)\n",
"skew = SkewT()\n",
"\n",
"# Plot the data using normal plotting functions, in this case using\n",
"# log scaling in Y, as dictated by the typical meteorological plot\n",
"skew.plot(p, T, 'r', linewidth=2)\n",
"skew.plot(p, Td, 'g', linewidth=2)\n",
"skew.plot_barbs(wpres, u, v)\n",
"skew.ax.set_ylim(1000, 100)\n",
"skew.ax.set_xlim(-30, 30)\n",
"plt.title(sounding_title)\n",
"\n",
"# Calculate LCL height and plot as black dot\n",
"l = lcl(p[0], T[0], Td[0])\n",
"lcl_temp = dry_lapse(concatenate((p[0], l)), T[0])[-1].to('degC')\n",
"skew.plot(l, lcl_temp, 'ko', markerfacecolor='black')\n",
"\n",
"# An example of a slanted line at constant T -- in this case the 0 isotherm\n",
"l = skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)\n",
"\n",
"# Draw hodograph\n",
"ax_hod = inset_axes(skew.ax, '30%', '30%', loc=3)\n",
"h = Hodograph(ax_hod, component_range=max(wsMan))\n",
"h.add_grid(increment=20)\n",
"h.plot_colormapped(u, v, spd)\n",
"\n",
"# Show the plot\n",
"plt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.10"
}
},
"nbformat": 4,
"nbformat_minor": 0
}