
Colored Surface Temperature¶
Python-AWIPS Tutorial Notebook
![[image text]](/myst_assets_folder../images/colored_surface_temp_preview.png)
Objectives¶
Use python-awips to connect to an edex server
Define and filter data request for METAR surface obs
Define a color threshold and use it to plot a useful map
Create a product similar to existing products in GEMPAK and CAVE
Table of Contents¶
Imports¶
The imports below are used throughout the notebook. Note the first import is coming directly from python-awips and allows us to connect to an EDEX server. The subsequent imports are for data manipulation and visualization.
from awips.dataaccess import DataAccessLayer
from dynamicserialize.dstypes.com.raytheon.uf.common.time import TimeRange
from datetime import datetime, timedelta, UTC
import numpy as np
import cartopy.crs as ccrs
import warnings
import matplotlib.pyplot as plt
from shapely.geometry import Polygon
from metpy.plots import StationPlotInitial Setup¶
Geographic Filter¶
By defining a bounding box for the Continental US (CONUS), we’re able to optimize the data request sent to the EDEX server.
# CONUS bounding box and envelope geometry
bbox=[-130, -70, 15, 55]
envelope = Polygon([(bbox[0],bbox[2]),(bbox[0],bbox[3]),
(bbox[1], bbox[3]),(bbox[1],bbox[2]),
(bbox[0],bbox[2])])EDEX Connection¶
First we establish a connection to Unidata’s public EDEX server. With that connection made, we can create a new data request object and set the data type to obs, and use the geographic envelope we just created.
# New obs request
edexServer = "edex-cloud.unidata.ucar.edu"
DataAccessLayer.changeEDEXHost(edexServer)
request = DataAccessLayer.newDataRequest("obs", envelope=envelope)
params = ["temperature", "longitude", "latitude", "stationName"]
request.setParameters(*(params))Filter by Time¶
We then want to limit our results based on time, so we create a time range for the last 15 minutes, and then send the request to the EDEX server to get our results, which are kept in the obs variable.
# Get records from the last 15 minutes
lastHourDateTime = datetime.now(UTC) - timedelta(minutes = 15)
start = lastHourDateTime.strftime('%Y-%m-%d %H:%M:%S')
end = datetime.now(UTC).strftime('%Y-%m-%d %H:%M:%S')
beginRange = datetime.strptime( start , "%Y-%m-%d %H:%M:%S")
endRange = datetime.strptime( end , "%Y-%m-%d %H:%M:%S")
timerange = TimeRange(beginRange, endRange)
# Get response
response = DataAccessLayer.getGeometryData(request,timerange)
obs = DataAccessLayer.getMetarObs(response)
lats = obs['latitude']
lons = obs['longitude']
print("Found " + str(len(response)) + " total records")
print("Using " + str(len(obs['temperature'])) + " temperature records")Found 2066 total records
Using 1966 temperature records
Access and Convert Temp Data¶
We access the temperature data from the obs variable which is stored in degrees Celsius (°C). To make it more relatable, we then convert the data to degrees Fahreheit (°F)
# # Suppress nan masking warnings
warnings.filterwarnings("ignore",category =RuntimeWarning)
# get all temperature values and convert them from °C to °F
tair = np.array(obs['temperature'], dtype=float)
tair[tair == -9999.0] = 'nan'
tair = (tair*1.8)+32Define Temperature Thresholds¶
In order to distinguish the temperatures, we’ll create a color map to separate the values into different colors. This mapping will be used when plotting the temperature values on the map of the United States.
thresholds = {
'15': 'purple',
'25': 'c',
'35': 'royalblue',
'45': 'darkgreen',
'55': 'green',
'65': 'y',
'75': 'orange',
'85': 'red'
}Plot the Data!¶
Here we create a plot and cycle through all the values from our color mapping. For each segement of our color mapping, mask the temperature values to only include the relevent temperatures and draw those on the plot. Do this for every segment of the color mapping to produce the final, colored figure.
fig, ax = plt.subplots(figsize=(16,12),subplot_kw=dict(projection=ccrs.LambertConformal()))
ax.set_extent(bbox)
ax.coastlines(resolution='50m')
ax.set_title(str(response[-1].getDataTime()) + " | Surface Temps (degF) | " + edexServer)
# get the temperature limit (x) and color (value)
for x, value in thresholds.items():
# create a new temperature value array
subtair = tair.copy()
# pair down the temperature values to a subset
if x==max(thresholds):
subtair[(subtair < int(x))] = 'nan'
elif x==min(thresholds):
subtair[(subtair >= int(x)+10)] = 'nan'
else:
subtair[(subtair < int(x))] = 'nan'
subtair[(subtair >= int(x)+10)] = 'nan'
# add these stations and their color to the stationplots
stationplot = StationPlot(ax, lons, lats, transform=ccrs.PlateCarree(), fontsize=14)
stationplot.plot_parameter('C', subtair, color=value)
