Objectives:
Introduction: Siphon is a python package that makes it possible to download data from Unidata data technologies. Here we will compare the data availability in 2 different TDS servers that distribute HFR data. We will first assess the metadata availableo on each server and then attempt to sub set identical regions of data, plot them and compare them.
But first! Bookmark these resources for when you want to use Siphon later:
First, we'll import the TDSCatalog class from Siphon and put the special 'matplotlib' line in so our map will show up later in the notebook. Let's construct an instance of TDSCatalog pointing to our dataset of interest.
Starting with east coast and Gulf of Mexico 1km resolution HF Radar data
In [1]:
from siphon.catalog import TDSCatalog
NDBC_HFR = TDSCatalog('http://sdf.ndbc.noaa.gov/thredds/'
'catalog.xml?dataset=hfradar_usegc_1km')
print('NDBC:')
print('\n'.join(NDBC_HFR.datasets.keys()))
In [2]:
SIO_HFR = TDSCatalog('http://hfrnet.ucsd.edu/thredds/'
'HFRADAR_USEGC_hourly_RTV.xml?dataset=HFRNet/USEGC/1km/hourly/RTV')
print('SIO:')
print('\n'.join(SIO_HFR.datasets.keys()))
In [3]:
NDBC_HFR.metadata
Out[3]:
In [4]:
SIO_HFR.metadata
Out[4]:
In [5]:
NDBC_ds = list(NDBC_HFR.datasets.values())[0]
NDBC_ds.access_urls
Out[5]:
In [6]:
SIO_ds = list(SIO_HFR.datasets.values())[0]
SIO_ds.access_urls
Out[6]:
In [7]:
from siphon.ncss import NCSS
NDBC_ncss = NCSS(NDBC_ds.access_urls['NetcdfSubset'])
SIO_ncss = NCSS(SIO_ds.access_urls['NetcdfSubset'])
In [8]:
NDBC_ncss.metadata.time_span
Out[8]:
In [9]:
NDBC_ncss.metadata.lat_lon_box
Out[9]:
In [10]:
NDBC_ncss.variables
Out[10]:
In [11]:
SIO_ncss.metadata.time_span
Out[11]:
In [12]:
SIO_ncss.metadata.lat_lon_box
Out[12]:
In [13]:
SIO_ncss.variables
Out[13]:
Both sites have the same variables and spatial extent but NDBC only has data from the last 6 days. SIO has data from January 1, 2012 'till today.
Now we can then use the ncss
objects to create a new query object, which facilitates asking for data from the server.
In [14]:
NDBC_query = NDBC_ncss.query()
SIO_query = SIO_ncss.query()
We construct a query asking for data corresponding to a latitude and longitude box for the mid-Atlantic where 42 lat is the northern extent, 35 lat is the southern extent, -80 long is the western extent and -69 is the eastern extent.
In [15]:
from datetime import datetime, timedelta
pos = dict(north=42, south=40.5, west=-72.6, east=-71)
end = datetime.utcnow()
start = end - timedelta(days=3)
NDBC_query.lonlat_box(**pos)
NDBC_query.time_range(start=start, end=end)
NDBC_query.variables('u', 'v')
SIO_query.lonlat_box(**pos)
SIO_query.time_range(start=start, end=end)
SIO_query.variables('u', 'v')
Out[15]:
We now request data from the server using this query. The NCSS
class handles parsing this NetCDF data (using the netCDF4
module). If we print out the variable names, we see our requested variables, as well as a few others (more metadata information)
In [16]:
NDBCdata = NDBC_ncss.get_data(NDBC_query)
list(NDBCdata.variables.keys())
Out[16]:
In [17]:
SIOdata = SIO_ncss.get_data(SIO_query)
list(SIOdata.variables.keys())
Out[17]:
In [18]:
%matplotlib inline
import numpy.ma as ma
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
from cmocean import cm
def parse_data(data):
u = ma.masked_invalid(data['u'][:])
v = ma.masked_invalid(data['v'][:])
speed = ma.sqrt(u**2 + v**2)
lon = data['lon'][:]
lat = data['lat'][:]
time = data['time'][:]
time = [''.join(t.astype(str).tolist()) for t in time]
return dict(u=u, v=v, speed=speed, lon=lon, lat=lat, time=time)
In [19]:
fig, (ax0, ax1) = plt.subplots(
figsize=(11, 5), ncols=2, sharex=True, sharey=True
)
k = 0
scale = 10
ndbc_ds = parse_data(NDBCdata)
sio_ds = parse_data(SIOdata)
ax0.set_title('NDBC')
ax0.quiver(ndbc_ds['lon'], ndbc_ds['lat'],
ndbc_ds['u'][k, ...], ndbc_ds['v'][k, ...],
ndbc_ds['speed'][k, ...], scale=scale, cmap=cm.speed)
ax1.set_title('SIO')
ax1.quiver(sio_ds['lon'], sio_ds['lat'],
sio_ds['u'][k, ...], sio_ds['v'][k, ...],
sio_ds['speed'][k, ...], scale=scale, cmap=cm.speed)
axis = ax0.axis([-72.2, -71.3, 40.8, 41.4])
In [20]:
import numpy as np
from JSAnimation import IPython_display
from matplotlib.animation import FuncAnimation
def anim(frames, interval=100):
# Static.
fig, ax = plt.subplots(figsize=(9, 9),
subplot_kw=dict(projection=ccrs.PlateCarree()))
ax.coastlines('10m', color='k')
ax.set_extent([pos['west'], pos['east'], pos['south'], pos['north']])
# Animated.
title = ax.set_title('')
empty = np.zeros((ndbc_ds['lat'].size, ndbc_ds['lon'].size)) * np.NaN
Q = ax.quiver(ndbc_ds['lon'], ndbc_ds['lat'], empty, empty, scale=10, cmap=cm.speed)
# Static.
ax.quiverkey(Q, -72.5, 41.5, 1, r'm s$^{-1}$', coordinates='data')
def init():
return Q, title
def animate(k):
Q.set_UVC(ndbc_ds['u'][k, ...], ndbc_ds['v'][k, ...], ndbc_ds['speed'][k, ...])
title = ax.set_title(ndbc_ds['time'][k])
return Q, title
return FuncAnimation(fig, animate, init_func=init,
frames=frames, interval=interval)
IPython_display.display_animation(anim(frames=len(ndbc_ds['time'])))
Out[20]: