|
| 1 | +{ |
| 2 | + "cells": [ |
| 3 | + { |
| 4 | + "cell_type": "markdown", |
| 5 | + "metadata": {}, |
| 6 | + "source": [ |
| 7 | + "# Upperair Obs with Contours\n", |
| 8 | + "\n", |
| 9 | + "By: Kevin Goebbert\n", |
| 10 | + "\n", |
| 11 | + "An example using the declarative syntax to plot upperair observations and overlay contours." |
| 12 | + ] |
| 13 | + }, |
| 14 | + { |
| 15 | + "cell_type": "code", |
| 16 | + "execution_count": null, |
| 17 | + "metadata": {}, |
| 18 | + "outputs": [], |
| 19 | + "source": [ |
| 20 | + "from datetime import datetime, timedelta\n", |
| 21 | + "\n", |
| 22 | + "import cartopy.crs as ccrs\n", |
| 23 | + "from metpy.io import add_station_lat_lon\n", |
| 24 | + "from metpy.plots.declarative import *\n", |
| 25 | + "from metpy.units import units\n", |
| 26 | + "import numpy as np\n", |
| 27 | + "from siphon.simplewebservice.iastate import IAStateUpperAir\n", |
| 28 | + "import xarray as xr" |
| 29 | + ] |
| 30 | + }, |
| 31 | + { |
| 32 | + "cell_type": "markdown", |
| 33 | + "metadata": {}, |
| 34 | + "source": [ |
| 35 | + "## Get Upperair Observations\n", |
| 36 | + "\n", |
| 37 | + "Using the functionality from Siphon to get all of the upperair data from the Iowa State archive. This example uses the current time and determines the date for yesterday to make sure data is available. This data doesn't have lat/lon information, so we add it using the functionality from MetPy to add that information to a dataFrame." |
| 38 | + ] |
| 39 | + }, |
| 40 | + { |
| 41 | + "cell_type": "code", |
| 42 | + "execution_count": null, |
| 43 | + "metadata": {}, |
| 44 | + "outputs": [], |
| 45 | + "source": [ |
| 46 | + "# Set the date for data and plot\n", |
| 47 | + "yesterday = datetime.utcnow() - timedelta(days=1)\n", |
| 48 | + "date = datetime(yesterday.year, yesterday.month, yesterday.day, 12)\n", |
| 49 | + "\n", |
| 50 | + "# Request data using Siphon request for data from Iowa State Archive\n", |
| 51 | + "data = IAStateUpperAir.request_all_data(date)\n", |
| 52 | + "\n", |
| 53 | + "# Add lat/lon information to dataframe\n", |
| 54 | + "data = add_station_lat_lon(data, data.station.name)" |
| 55 | + ] |
| 56 | + }, |
| 57 | + { |
| 58 | + "cell_type": "markdown", |
| 59 | + "metadata": {}, |
| 60 | + "source": [ |
| 61 | + "## Get GFS data\n", |
| 62 | + "\n", |
| 63 | + "For plotting contours we need some gridded output. Using the UCAR THREDDS data server to obtain the appropriate model initial conditions to contour on top of our upperair observations." |
| 64 | + ] |
| 65 | + }, |
| 66 | + { |
| 67 | + "cell_type": "code", |
| 68 | + "execution_count": null, |
| 69 | + "metadata": {}, |
| 70 | + "outputs": [], |
| 71 | + "source": [ |
| 72 | + "# Get GFS data for contouring\n", |
| 73 | + "ds = xr.open_dataset('https://thredds.ucar.edu/thredds/dodsC/grib/NCEP/GFS/'\n", |
| 74 | + " f'Global_onedeg_ana/GFS_Global_onedeg_ana_{date:%Y%m%d}_0000.grib2').metpy.parse_cf()" |
| 75 | + ] |
| 76 | + }, |
| 77 | + { |
| 78 | + "cell_type": "markdown", |
| 79 | + "metadata": {}, |
| 80 | + "source": [ |
| 81 | + "## Make Plot\n", |
| 82 | + "\n", |
| 83 | + "Using the declarative syntax from MetPy, we plot observations and contours on the same map panel.\n", |
| 84 | + "\n", |
| 85 | + "There are also sqaures added to each observation location by using the axes that are generate by the declarative syntax to plot them using classic Matplotlib methods." |
| 86 | + ] |
| 87 | + }, |
| 88 | + { |
| 89 | + "cell_type": "code", |
| 90 | + "execution_count": null, |
| 91 | + "metadata": {}, |
| 92 | + "outputs": [], |
| 93 | + "source": [ |
| 94 | + "# Add point observations\n", |
| 95 | + "obs = PlotObs()\n", |
| 96 | + "obs.data = data\n", |
| 97 | + "obs.level = 500 * units.hPa\n", |
| 98 | + "obs.time = date\n", |
| 99 | + "obs.fields = ['temperature', 'dewpoint', 'height']\n", |
| 100 | + "obs.locations = ['NW', 'SW', 'ENE']\n", |
| 101 | + "obs.vector_field = ['u_wind', 'v_wind']\n", |
| 102 | + "obs.vector_field_length = 8\n", |
| 103 | + "\n", |
| 104 | + "# Add contours of geopotential height\n", |
| 105 | + "cntr = ContourPlot()\n", |
| 106 | + "cntr.data = ds.sel(lat=slice(80, 10), lon=slice(360-140, 360-40))\n", |
| 107 | + "cntr.level = obs.level\n", |
| 108 | + "cntr.field = 'Geopotential_height_isobaric'\n", |
| 109 | + "cntr.clabels = True\n", |
| 110 | + "cntr.contours = list(range(0, 10000, 60))\n", |
| 111 | + "\n", |
| 112 | + "# set map panel features\n", |
| 113 | + "panel = MapPanel()\n", |
| 114 | + "panel.projection = 'lcc'\n", |
| 115 | + "panel.area = [-125, -65, 22, 55]\n", |
| 116 | + "panel.layers = ['states', 'borders', 'coastline']\n", |
| 117 | + "panel.plots = [obs, cntr]\n", |
| 118 | + "\n", |
| 119 | + "# Add map panel to figure\n", |
| 120 | + "pc = PanelContainer()\n", |
| 121 | + "pc.size = (20, 20)\n", |
| 122 | + "pc.panels = [panel]\n", |
| 123 | + "\n", |
| 124 | + "# Add a square marker at sounding site\n", |
| 125 | + "panel.ax.scatter(data.longitude, data.latitude, s=50, marker='s', color='black', transform=ccrs.PlateCarree())\n", |
| 126 | + "\n", |
| 127 | + "pc.show()" |
| 128 | + ] |
| 129 | + }, |
| 130 | + { |
| 131 | + "cell_type": "code", |
| 132 | + "execution_count": null, |
| 133 | + "metadata": {}, |
| 134 | + "outputs": [], |
| 135 | + "source": [] |
| 136 | + } |
| 137 | + ], |
| 138 | + "metadata": { |
| 139 | + "kernelspec": { |
| 140 | + "display_name": "Python 3", |
| 141 | + "language": "python", |
| 142 | + "name": "python3" |
| 143 | + }, |
| 144 | + "language_info": { |
| 145 | + "codemirror_mode": { |
| 146 | + "name": "ipython", |
| 147 | + "version": 3 |
| 148 | + }, |
| 149 | + "file_extension": ".py", |
| 150 | + "mimetype": "text/x-python", |
| 151 | + "name": "python", |
| 152 | + "nbconvert_exporter": "python", |
| 153 | + "pygments_lexer": "ipython3", |
| 154 | + "version": "3.7.3" |
| 155 | + } |
| 156 | + }, |
| 157 | + "nbformat": 4, |
| 158 | + "nbformat_minor": 4 |
| 159 | +} |
0 commit comments