2018-10-04 17:25:20 -06:00
|
|
|
{
|
|
|
|
"cells": [
|
|
|
|
{
|
|
|
|
"cell_type": "code",
|
|
|
|
"execution_count": 1,
|
|
|
|
"metadata": {},
|
|
|
|
"outputs": [],
|
|
|
|
"source": [
|
|
|
|
"%matplotlib inline"
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"cell_type": "markdown",
|
|
|
|
"metadata": {},
|
|
|
|
"source": [
|
|
|
|
"\n",
|
|
|
|
"Station Plot with Layout\n",
|
|
|
|
"========================\n",
|
|
|
|
"\n",
|
|
|
|
"Make a station plot, complete with sky cover and weather symbols, using a\n",
|
|
|
|
"station plot layout built into MetPy.\n",
|
|
|
|
"\n",
|
|
|
|
"The station plot itself is straightforward, but there is a bit of code to perform the\n",
|
|
|
|
"data-wrangling (hopefully that situation will improve in the future). Certainly, if you have\n",
|
|
|
|
"existing point data in a format you can work with trivially, the station plot will be simple.\n",
|
|
|
|
"\n",
|
|
|
|
"The `StationPlotLayout` class is used to standardize the plotting various parameters\n",
|
|
|
|
"(i.e. temperature), keeping track of the location, formatting, and even the units for use in\n",
|
|
|
|
"the station plot. This makes it easy (if using standardized names) to re-use a given layout\n",
|
|
|
|
"of a station plot.\n",
|
|
|
|
"\n"
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"cell_type": "markdown",
|
|
|
|
"metadata": {},
|
|
|
|
"source": [
|
|
|
|
"The setup\n",
|
|
|
|
"---------\n",
|
|
|
|
"\n",
|
|
|
|
"First read in the data. We use `numpy.loadtxt` to read in the data and use a structured\n",
|
|
|
|
"`numpy.dtype` to allow different types for the various columns. This allows us to handle\n",
|
|
|
|
"the columns with string data.\n",
|
|
|
|
"\n"
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"cell_type": "code",
|
|
|
|
"execution_count": 2,
|
|
|
|
"metadata": {},
|
|
|
|
"outputs": [],
|
|
|
|
"source": [
|
|
|
|
"from awips.dataaccess import DataAccessLayer\n",
|
|
|
|
"from dynamicserialize.dstypes.com.raytheon.uf.common.time import TimeRange\n",
|
|
|
|
"from datetime import datetime, timedelta\n",
|
|
|
|
"import numpy as np\n",
|
|
|
|
"\n",
|
|
|
|
"import cartopy.crs as ccrs\n",
|
|
|
|
"import cartopy.feature as cfeature\n",
|
|
|
|
"import matplotlib.pyplot as plt\n",
|
|
|
|
"import pandas as pd\n",
|
|
|
|
"\n",
|
|
|
|
"from metpy.calc import wind_components\n",
|
|
|
|
"from metpy.cbook import get_test_data\n",
|
|
|
|
"from metpy.plots import (add_metpy_logo, simple_layout, StationPlot,\n",
|
|
|
|
" StationPlotLayout, wx_code_map)\n",
|
|
|
|
"from metpy.units import units\n",
|
|
|
|
"\n",
|
|
|
|
"def get_cloud_cover(code):\n",
|
|
|
|
" if 'OVC' in code:\n",
|
|
|
|
" return 1.0\n",
|
|
|
|
" elif 'BKN' in code:\n",
|
|
|
|
" return 6.0/8.0\n",
|
|
|
|
" elif 'SCT' in code:\n",
|
|
|
|
" return 4.0/8.0\n",
|
|
|
|
" elif 'FEW' in code:\n",
|
|
|
|
" return 2.0/8.0\n",
|
|
|
|
" else:\n",
|
|
|
|
" return 0\n",
|
|
|
|
"\n",
|
|
|
|
"# Pull out these specific stations (prepend K for AWIPS identifiers)\n",
|
|
|
|
"selected = ['PDX', 'OKC', 'ICT', 'GLD', 'MEM', 'BOS', 'MIA', 'MOB', 'ABQ', 'PHX', 'TTF',\n",
|
|
|
|
" 'ORD', 'BIL', 'BIS', 'CPR', 'LAX', 'ATL', 'MSP', 'SLC', 'DFW', 'NYC', 'PHL',\n",
|
|
|
|
" 'PIT', 'IND', 'OLY', 'SYR', 'LEX', 'CHS', 'TLH', 'HOU', 'GJT', 'LBB', 'LSV',\n",
|
|
|
|
" 'GRB', 'CLT', 'LNK', 'DSM', 'BOI', 'FSD', 'RAP', 'RIC', 'JAN', 'HSV', 'CRW',\n",
|
|
|
|
" 'SAT', 'BUY', '0CO', 'ZPC', 'VIH', 'BDG', 'MLF', 'ELY', 'WMC', 'OTH', 'CAR',\n",
|
|
|
|
" 'LMT', 'RDM', 'PDT', 'SEA', 'UIL', 'EPH', 'PUW', 'COE', 'MLP', 'PIH', 'IDA', \n",
|
|
|
|
" 'MSO', 'ACV', 'HLN', 'BIL', 'OLF', 'RUT', 'PSM', 'JAX', 'TPA', 'SHV', 'MSY',\n",
|
|
|
|
" 'ELP', 'RNO', 'FAT', 'SFO', 'NYL', 'BRO', 'MRF', 'DRT', 'FAR', 'BDE', 'DLH',\n",
|
|
|
|
" 'HOT', 'LBF', 'FLG', 'CLE', 'UNV']\n",
|
|
|
|
"selected = ['K{0}'.format(id) for id in selected]\n",
|
|
|
|
"data_arr = []"
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"cell_type": "code",
|
|
|
|
"execution_count": 3,
|
|
|
|
"metadata": {},
|
|
|
|
"outputs": [],
|
|
|
|
"source": [
|
|
|
|
"# EDEX Request\n",
|
|
|
|
"edexServer = \"edex-cloud.unidata.ucar.edu\"\n",
|
|
|
|
"DataAccessLayer.changeEDEXHost(edexServer)\n",
|
|
|
|
"request = DataAccessLayer.newDataRequest(\"obs\")\n",
|
|
|
|
"availableProducts = DataAccessLayer.getAvailableParameters(request)\n",
|
|
|
|
"\n",
|
|
|
|
"single_value_params = [\"timeObs\", \"stationName\", \"longitude\", \"latitude\", \n",
|
|
|
|
" \"temperature\", \"dewpoint\", \"windDir\",\n",
|
|
|
|
" \"windSpeed\", \"seaLevelPress\"]\n",
|
|
|
|
"multi_value_params = [\"presWeather\", \"skyCover\", \"skyLayerBase\"]\n",
|
|
|
|
"pres_weather, sky_cov, sky_layer_base = [],[],[]\n",
|
|
|
|
"params = single_value_params + multi_value_params\n",
|
|
|
|
"obs = dict({params: [] for params in params})\n",
|
|
|
|
"\n",
|
|
|
|
"request.setParameters(*(params))\n",
|
|
|
|
"request.setLocationNames(*(selected))"
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"cell_type": "markdown",
|
|
|
|
"metadata": {},
|
|
|
|
"source": [
|
|
|
|
"Here we use the Python-AWIPS class **TimeRange** to prepare a beginning and end time span for requesting observations (the last hour):"
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"cell_type": "code",
|
|
|
|
"execution_count": 4,
|
|
|
|
"metadata": {},
|
|
|
|
"outputs": [],
|
|
|
|
"source": [
|
|
|
|
"# Time range\n",
|
|
|
|
"lastHourDateTime = datetime.utcnow() - timedelta(hours = 1)\n",
|
|
|
|
"start = lastHourDateTime.strftime('%Y-%m-%d %H')\n",
|
|
|
|
"beginRange = datetime.strptime( start + \":00:00\", \"%Y-%m-%d %H:%M:%S\")\n",
|
|
|
|
"endRange = datetime.strptime( start + \":59:59\", \"%Y-%m-%d %H:%M:%S\")\n",
|
|
|
|
"timerange = TimeRange(beginRange, endRange)\n",
|
|
|
|
"\n",
|
|
|
|
"response = DataAccessLayer.getGeometryData(request,timerange)"
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"cell_type": "code",
|
|
|
|
"execution_count": 5,
|
|
|
|
"metadata": {},
|
|
|
|
"outputs": [],
|
|
|
|
"source": [
|
|
|
|
"station_names = []\n",
|
|
|
|
"for ob in response:\n",
|
|
|
|
" avail_params = [x.decode('utf-8') for x in ob.getParameters()]\n",
|
|
|
|
" if \"presWeather\" in avail_params:\n",
|
|
|
|
" pres_weather.append(ob.getString(\"presWeather\"))\n",
|
|
|
|
" elif \"skyCover\" in avail_params and \"skyLayerBase\" in avail_params:\n",
|
|
|
|
" sky_cov.append(ob.getString(\"skyCover\"))\n",
|
|
|
|
" sky_layer_base.append(ob.getNumber(\"skyLayerBase\"))\n",
|
|
|
|
" else:\n",
|
|
|
|
" # If we already have a record for this stationName, skip\n",
|
|
|
|
" if ob.getString('stationName') not in station_names:\n",
|
|
|
|
" station_names.append(ob.getString('stationName'))\n",
|
|
|
|
" for param in single_value_params: \n",
|
|
|
|
" if param in avail_params:\n",
|
|
|
|
" if param == 'timeObs':\n",
|
|
|
|
" obs[param].append(datetime.fromtimestamp(ob.getNumber(param)/1000.0))\n",
|
|
|
|
" else:\n",
|
|
|
|
" try:\n",
|
|
|
|
" obs[param].append(ob.getNumber(param))\n",
|
|
|
|
" except TypeError:\n",
|
|
|
|
" obs[param].append(ob.getString(param))\n",
|
|
|
|
" else:\n",
|
|
|
|
" obs[param].append(None)\n",
|
|
|
|
" \n",
|
|
|
|
" obs['presWeather'].append(pres_weather);\n",
|
|
|
|
" obs['skyCover'].append(sky_cov);\n",
|
|
|
|
" obs['skyLayerBase'].append(sky_layer_base);\n",
|
|
|
|
" pres_weather = []\n",
|
|
|
|
" sky_cov = []\n",
|
|
|
|
" sky_layer_base = []"
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"cell_type": "markdown",
|
|
|
|
"metadata": {},
|
|
|
|
"source": [
|
|
|
|
"Next grab the simple variables out of the data we have (attaching correct units), and\n",
|
|
|
|
"put them into a dictionary that we will hand the plotting function later:\n",
|
|
|
|
"\n",
|
|
|
|
"- Get wind components from speed and direction\n",
|
|
|
|
"- Convert cloud fraction values to integer codes [0 - 8]\n",
|
|
|
|
"- Map METAR weather codes to WMO codes for weather symbols"
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"cell_type": "code",
|
2018-10-05 17:09:43 -06:00
|
|
|
"execution_count": 9,
|
2018-10-04 17:25:20 -06:00
|
|
|
"metadata": {},
|
|
|
|
"outputs": [],
|
|
|
|
"source": [
|
|
|
|
"data = dict()\n",
|
|
|
|
"data['stid'] = np.array(obs['stationName'])\n",
|
|
|
|
"data['latitude'] = np.array(obs['latitude'])\n",
|
|
|
|
"data['longitude'] = np.array(obs['longitude'])\n",
|
|
|
|
"data['air_temperature'] = np.array(obs['temperature'], dtype=float)* units.degC\n",
|
|
|
|
"data['dew_point_temperature'] = np.array(obs['dewpoint'], dtype=float)* units.degC\n",
|
|
|
|
"data['air_pressure_at_sea_level'] = np.array(obs['seaLevelPress'])* units('mbar')\n",
|
|
|
|
"\n",
|
|
|
|
"direction = np.array(obs['windDir'])\n",
|
|
|
|
"direction[direction == -9999.0] = 'nan'\n",
|
|
|
|
"\n",
|
|
|
|
"u, v = wind_components(np.array(obs['windSpeed']) * units('knots'),\n",
|
|
|
|
" direction * units.degree)\n",
|
|
|
|
"data['eastward_wind'], data['northward_wind'] = u, v\n",
|
|
|
|
"data['cloud_coverage'] = [int(get_cloud_cover(x)*8) for x in obs['skyCover']]\n",
|
|
|
|
"data['present_weather'] = obs['presWeather']"
|
|
|
|
]
|
|
|
|
},
|
2018-10-05 17:09:43 -06:00
|
|
|
{
|
|
|
|
"cell_type": "code",
|
|
|
|
"execution_count": 10,
|
|
|
|
"metadata": {},
|
|
|
|
"outputs": [
|
|
|
|
{
|
|
|
|
"name": "stdout",
|
|
|
|
"output_type": "stream",
|
|
|
|
"text": [
|
|
|
|
"['K0CO', 'KMLF', 'KCPR', 'KLNK', 'KFSD', 'KPIT', 'KMRF', 'KCLE', 'KFAR', 'KOLY', 'KBDG', 'KTTF', 'KGRB', 'KBDE', 'KOTH', 'KUNV', 'KBIS', 'KMSP', 'KLAX', 'KNYC', 'KELP', 'KSAT', 'KORD', 'KPHX', 'KEPH', 'KGJT', 'KGLD', 'KICT', 'KDFW', 'KATL', 'KCLT', 'KRAP', 'KACV', 'KABQ', 'KSEA', 'KLBF', 'KOKC', 'KBIL', 'KDRT', 'KVIH', 'KELY', 'KFAT', 'KHSV', 'KLBB', 'KPDX', 'KMSO', 'KUIL', 'KTLH', 'KPIH', 'KMIA', 'KMLP', 'KMSY', 'KTPA', 'KHLN', 'KHOT', 'KHOU', 'KIDA', 'KPUW', 'KLMT', 'KOLF', 'KPDT', 'KBOI', 'KPHL', 'KCAR', 'KCRW', 'KDSM', 'KJAN', 'KLEX', 'KIND', 'KMEM', 'KBOS', 'KBRO', 'KSYR', 'KRIC', 'KBUY', 'KSLC', 'KCOE', 'KRNO', 'KRUT', 'KNYL', 'KPSM', 'KRDM', 'KFLG', 'KWMC', 'KCHS', 'KJAX', 'KMOB', 'KSFO', 'KSHV', 'KLSV']\n"
|
|
|
|
]
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"source": [
|
|
|
|
"print(obs['stationName'])"
|
|
|
|
]
|
|
|
|
},
|
2018-10-04 17:25:20 -06:00
|
|
|
{
|
|
|
|
"cell_type": "markdown",
|
|
|
|
"metadata": {},
|
|
|
|
"source": [
|
|
|
|
"## MetPy Surface Obs Plot"
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"cell_type": "code",
|
2018-10-05 17:09:43 -06:00
|
|
|
"execution_count": 12,
|
2018-10-04 17:25:20 -06:00
|
|
|
"metadata": {},
|
|
|
|
"outputs": [
|
|
|
|
{
|
|
|
|
"data": {
|
2018-10-05 17:09:43 -06:00
|
|
|
"image/png": "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
|
2018-10-04 17:25:20 -06:00
|
|
|
"text/plain": [
|
|
|
|
"<Figure size 1440x720 with 1 Axes>"
|
|
|
|
]
|
|
|
|
},
|
|
|
|
"metadata": {
|
|
|
|
"needs_background": "light"
|
|
|
|
},
|
|
|
|
"output_type": "display_data"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"source": [
|
|
|
|
"proj = ccrs.LambertConformal(central_longitude=-95, central_latitude=35,\n",
|
|
|
|
" standard_parallels=[35])\n",
|
2018-10-05 17:09:43 -06:00
|
|
|
"\n",
|
|
|
|
"# Change the DPI of the figure\n",
|
2018-10-04 17:25:20 -06:00
|
|
|
"plt.rcParams['savefig.dpi'] = 255\n",
|
|
|
|
"\n",
|
2018-10-05 17:09:43 -06:00
|
|
|
"# Winds, temps, dewpoint, station id\n",
|
|
|
|
"custom_layout = StationPlotLayout()\n",
|
|
|
|
"custom_layout.add_barb('eastward_wind', 'northward_wind', units='knots')\n",
|
|
|
|
"custom_layout.add_value('NW', 'air_temperature', fmt='.0f', units='degF', color='darkred')\n",
|
|
|
|
"custom_layout.add_value('SW', 'dew_point_temperature', fmt='.0f', units='degF', color='darkgreen')\n",
|
|
|
|
"custom_layout.add_value('E', 'precipitation', fmt='0.1f', units='inch', color='blue')\n",
|
2018-10-04 17:25:20 -06:00
|
|
|
"\n",
|
2018-10-05 17:09:43 -06:00
|
|
|
"# Create the figure\n",
|
2018-10-04 17:25:20 -06:00
|
|
|
"fig = plt.figure(figsize=(20, 10))\n",
|
|
|
|
"add_metpy_logo(fig, 1080, 290, size='large')\n",
|
|
|
|
"ax = fig.add_subplot(1, 1, 1, projection=proj)\n",
|
2018-10-05 17:09:43 -06:00
|
|
|
"\n",
|
|
|
|
"# Add various map elements\n",
|
2018-10-04 17:25:20 -06:00
|
|
|
"ax.add_feature(cfeature.LAND)\n",
|
|
|
|
"ax.add_feature(cfeature.OCEAN)\n",
|
|
|
|
"ax.add_feature(cfeature.LAKES)\n",
|
|
|
|
"ax.add_feature(cfeature.COASTLINE)\n",
|
|
|
|
"ax.add_feature(cfeature.STATES)\n",
|
|
|
|
"ax.add_feature(cfeature.BORDERS, linewidth=2)\n",
|
2018-10-05 17:09:43 -06:00
|
|
|
"\n",
|
2018-10-04 17:25:20 -06:00
|
|
|
"# Set plot bounds\n",
|
|
|
|
"ax.set_extent((-118, -73, 23, 50))\n",
|
|
|
|
"ax.set_title(str(ob.getDataTime()) + \" | METAR | \" + edexServer)\n",
|
|
|
|
"\n",
|
|
|
|
"stationplot = StationPlot(ax, data['longitude'], data['latitude'], clip_on=True,\n",
|
|
|
|
" transform=ccrs.PlateCarree(), fontsize=10)\n",
|
|
|
|
"stationplot.plot_text((2, 0), data['stid'])\n",
|
2018-10-05 17:09:43 -06:00
|
|
|
"custom_layout.plot(stationplot, data)\n",
|
|
|
|
"plt.show()"
|
2018-10-04 17:25:20 -06:00
|
|
|
]
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"metadata": {
|
|
|
|
"kernelspec": {
|
|
|
|
"display_name": "Python 3",
|
|
|
|
"language": "python",
|
|
|
|
"name": "python3"
|
|
|
|
},
|
|
|
|
"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.6.6"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"nbformat": 4,
|
|
|
|
"nbformat_minor": 1
|
|
|
|
}
|