ATM 433/533 Week 1 Sample Notebook

This is an example Jupyter notebook that uses built-in Python functions, as well as external packages such as Cartopy, Matplotlib, Datetime, MetPy, and Pandas to visualize data from the New York State Mesonet, headquartered right here at UAlbany.

Import the necessary libraries

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from datetime import datetime
from cartopy import crs as ccrs
from cartopy import feature as cfeature
from metpy.calc import wind_components
from metpy.units import units
from metpy.plots import StationPlot

Specify the format of the date/time string that is used in the NYSM data files

timeFormat = "%Y-%m-%d %H:%M:%S"

Define a function will iterate over each string in a 1-d array, and use Pandas’ implementation of strptime to convert the string into a datetime object

parseTime = lambda x: datetime.strptime(x, timeFormat)

Use Pandas to read in the most recent table of NYSM observations, and define objects corresponding to the various columns in the table

nysm_data = pd.read_csv('/data2/www/htdocs/products/nysm/nysm_latest.csv',parse_dates=['time'], date_parser=parseTime)
stid = nysm_data['station']
lats = nysm_data['lat']
lons = nysm_data['lon']
elev = nysm_data['elevation']
name = nysm_data['name']
tmpc = nysm_data['temp_2m [degC]']
rh   = nysm_data['relative_humidity [percent]']
pres = nysm_data['station_pressure [mbar]']
gust = nysm_data['max_wind_speed_prop [m/s]']
wspd = nysm_data['avg_wind_speed_sonic [m/s]']
drct = nysm_data['wind_direction_sonic [degrees]']

Represent the date and time as a string, which we’ll use in the title of our map.

timeStr = datetime.strftime(nysm_data['time'][0],"%c")
timeStr
'Fri Sep 22 15:35:00 2023'

Perform some unit conversions (Celsius to Fahrneheit, and meters per second to knots)

tmpf = tmpc * 1.8 + 32
wspk = wspd * 1.94384

Break the horizontal wind vector into its to u- and v- components

u, v = wind_components(wspk.values * units.knots, drct.values * units.degree)

Reduce station pressure to what it would be at sea level. Source: https://www.sandhurstweather.org.uk/barometric.pdf

sensorHeight = .5
slp = pres/np.exp(-1*(elev+sensorHeight)/((tmpc+273.15) * 29.263))

Calculate the dew point temperature from air temperature and relative humidity

dwpc = 243.04*(np.log(rh/100)+((17.625*tmpc)/(243.04+tmpc)))/(17.625-np.log(rh/100)-((17.625*tmpc)/(243.04+tmpc)))
dwpf = dwpc * 1.8 + 32

Set the domain over which we will plot the map, and specify a map projection.

latN = 45.2
latS = 40.2
lonW = -80.0
lonE = -72.0
cLat = (latN + latS)/2
cLon = (lonW + lonE )/2
proj = ccrs.LambertConformal(central_longitude=cLon, central_latitude=cLat)

Create the map; first, add some cartographic features, and then plot the Mesonet observations at each station.

fig = plt.figure(figsize=(18,12),dpi=150) # Increase the dots per inch from default 100 to make plot easier to read
ax = fig.add_subplot(1,1,1,projection=proj)
ax.set_extent ([lonW,lonE,latS,latN])
# Choose the medium resolution of Natural Earth's cartographic features' shapefiles.
res = '50m'
# Set the default background color to that of a water body. This will be faster than plotting Cartopy's `OCEAN` feature's shapefile.
ax.set_facecolor(cfeature.COLORS['water'])
ax.add_feature (cfeature.LAND.with_scale(res))
ax.add_feature(cfeature.COASTLINE.with_scale(res))
ax.add_feature (cfeature.LAKES.with_scale(res))
ax.add_feature (cfeature.STATES.with_scale(res));

# Create a station plot pointing to an Axes to draw on as well as the location of points. Transform the station locations from lat-
stationplot = StationPlot(ax, lons, lats, transform=ccrs.PlateCarree(),
                          fontsize=8)

stationplot.plot_parameter('NW', tmpf, color='red')
stationplot.plot_parameter('SW', dwpf, color='green')

# A more complex example uses a custom formatter to control how the sea-level pressure
# values are plotted. This uses the standard trailing 3-digits of the pressure value
# in tenths of millibars.

stationplot.plot_parameter('NE', slp.values, color='purple', formatter=lambda v: format(10 * v, '.0f')[-3:])
stationplot.plot_barb(u, v,zorder=10)
ax.set_title ('Temperature and Dewpoint ($^\circ$F), SLP (hPa), Wind (kts) ' + timeStr);

# Save the figure to the current directory.
fig.savefig('nysm_sfcmap.png')
../../_images/a79a6d42acc8c16ffc0c121be49a462d966154348a7e5abd4942f19bb3c752ab.png

Remember to Close and Shutdown this notebook when you are finished!