IOOS System Test: Extreme Events Theme: Coastal Inundation

Can we compare observed and modeled wave parameters?

This notebook is based on IOOS System Test: Inundation

Methodology:

  • Define temporal and spatial bounds of interest, as well as parameters of interest
  • Search for available service endpoints in the NGDC CSW catalog meeting search criteria
  • Extract OPeNDAP data endpoints from model datasets and SOS endpoints from observational datasets
  • Obtain observation data sets from stations within the spatial boundaries
  • Plot observation stations on a map (red marker if not enough data)
  • Using DAP (model) endpoints find all available models data sets that fall in the area of interest, for the specified time range, and extract a model grid cell closest to all the given station locations
  • Plot modelled and observed time series wave data on same axes for comparison

import required libraries


In [1]:
import datetime as dt
from warnings import warn
from io import BytesIO
import folium
import netCDF4
from IPython.display import HTML
import iris
from iris.exceptions import CoordinateNotFoundError, ConstraintMismatchError
import matplotlib.pyplot as plt
from owslib.csw import CatalogueServiceWeb
from owslib import fes
import pandas as pd
from pyoos.collectors.ndbc.ndbc_sos import NdbcSos
import requests

from utilities import (fes_date_filter, collector2df, find_timevar, find_ij, nearxy, service_urls, mod_df, 
                       get_coordinates, get_station_longName, inline_map)

Speficy Temporal and Spatial conditions


In [2]:
bounding_box_type = "box" 

# Bounding Box [lon_min, lat_min, lon_max, lat_max]
area = {'Hawaii': [-160.0, 18.0, -154., 23.0],
        'Gulf of Maine': [-72.0, 41.0, -69.0, 43.0],
        'New York harbor region': [-75., 39., -71., 41.5],
        'Puerto Rico': [-75, 12, -55, 26],
        'East Coast': [-77, 34, -70, 40],
        'North West': [-130, 38, -121, 50],
        'Gulf of Mexico': [-92, 28, -84, 31],
        'Arctic': [-179, 63, -140, 80],
        'North East': [-74, 40, -69, 42],
        'Virginia Beach': [-76, 34, -74, 38]}

bounding_box = area['East Coast']

#temporal range - May 1 2014 - May 10 2014
start_date = dt.datetime(2014,5,1,0,50).strftime('%Y-%m-%d %H:%M')
end_date = dt.datetime(2014,5,10).strftime('%Y-%m-%d %H:00')
time_date_range = [start_date,end_date]  #start_date_end_date

jd_start = dt.datetime.strptime(start_date, '%Y-%m-%d %H:%M')
jd_stop = dt.datetime.strptime(end_date, '%Y-%m-%d %H:%M')

print start_date,'to',end_date


2014-05-01 00:50 to 2014-05-10 00:00

Specify data names of interest


In [3]:
#put the names in a dict for ease of access 
# put the names in a dict for ease of access 
data_dict = {}
sos_name = 'waves'
data_dict["waves"] = {"names":['sea_surface_wave_significant_height',
                               'significant_wave_height',
                               'significant_height_of_wave',
                               'sea_surface_wave_significant_height(m)',
                               'sea_surface_wave_significant_height (m)',
                               'water_surface_height'], 
                      "sos_name":["waves"]}

Search CSW for datasets of interest


In [4]:
endpoint = 'http://www.ngdc.noaa.gov/geoportal/csw' # NGDC Geoportal
csw = CatalogueServiceWeb(endpoint,timeout=60)

In [5]:
# convert User Input into FES filters
start,stop = fes_date_filter(start_date,end_date)
bbox = fes.BBox(bounding_box)

#use the search name to create search filter
or_filt = fes.Or([fes.PropertyIsLike(propertyname='apiso:AnyText',literal='*%s*' % val,
                    escapeChar='\\',wildCard='*',singleChar='?') for val in data_dict["waves"]["names"]])

# try request using multiple filters "and" syntax: [[filter1,filter2]]
filter_list = [fes.And([ bbox, start, stop, or_filt]) ]

csw.getrecords2(constraints=filter_list,maxrecords=1000,esn='full')
print str(len(csw.records)) + " csw records found"


63 csw records found

Dap URLs


In [6]:
dap_urls = service_urls(csw.records)
#remove duplicates and organize
dap_urls = sorted(set(dap_urls))
print "Total DAP:",len(dap_urls)
#print the first 5...
print "\n".join(dap_urls[0:5])


Total DAP: 44
http://ecowatch.ncddc.noaa.gov/thredds/dodsC/onomads/rtofs/rtofs_surface_agg/best
http://ecowatch.ncddc.noaa.gov/thredds/dodsC/onomads/rtofs/rtofs_volume_agg/best
http://geoport-dev.whoi.edu/thredds/dodsC/estofs/atlantic
http://geoport.whoi.edu/thredds/dodsC/coawst_4/use/fmrc/coawst_4_use_best.ncd
http://hfrnet.ucsd.edu/thredds/dodsC/HFRNet/USEGC/1km/hourly/GNOME

SOS URLs


In [7]:
sos_urls = service_urls(csw.records,service='sos:url')
#remove duplicates and organize
sos_urls = sorted(set(sos_urls))

print "Total SOS:",len(sos_urls)
print "\n".join(sos_urls)


Total SOS: 13
http://sdf.ndbc.noaa.gov/sos/server.php?service=SOS&request=GetCapabilities&acceptVersions=1.0.0
http://thredds.cdip.ucsd.edu/thredds/sos/cdip/archive/067p1/067p1_historic.nc?service=SOS&version=1.0.0&request=GetCapabilities
http://thredds.cdip.ucsd.edu/thredds/sos/cdip/archive/094p1/094p1_d12.nc?service=SOS&version=1.0.0&request=GetCapabilities
http://thredds.cdip.ucsd.edu/thredds/sos/cdip/archive/094p1/094p1_historic.nc?service=SOS&version=1.0.0&request=GetCapabilities
http://thredds.cdip.ucsd.edu/thredds/sos/cdip/archive/100p1/100p1_historic.nc?service=SOS&version=1.0.0&request=GetCapabilities
http://thredds.cdip.ucsd.edu/thredds/sos/cdip/archive/142p1/142p1_d14.nc?service=SOS&version=1.0.0&request=GetCapabilities
http://thredds.cdip.ucsd.edu/thredds/sos/cdip/archive/142p1/142p1_historic.nc?service=SOS&version=1.0.0&request=GetCapabilities
http://thredds.cdip.ucsd.edu/thredds/sos/cdip/archive/147p1/147p1_d10.nc?service=SOS&version=1.0.0&request=GetCapabilities
http://thredds.cdip.ucsd.edu/thredds/sos/cdip/archive/147p1/147p1_historic.nc?service=SOS&version=1.0.0&request=GetCapabilities
http://thredds.cdip.ucsd.edu/thredds/sos/cdip/archive/156p1/156p1_d07.nc?service=SOS&version=1.0.0&request=GetCapabilities
http://thredds.cdip.ucsd.edu/thredds/sos/cdip/archive/168p1/168p1_d05.nc?service=SOS&version=1.0.0&request=GetCapabilities
http://thredds.cdip.ucsd.edu/thredds/sos/cdip/archive/185p1/185p1_d02.nc?service=SOS&version=1.0.0&request=GetCapabilities
http://thredds.cdip.ucsd.edu/thredds/sos/cdip/archive/207p1/207p1_d01.nc?service=SOS&version=1.0.0&request=GetCapabilities

Get most recent observations from all stations in bounding box


In [8]:
start_time = dt.datetime.strptime(start_date,'%Y-%m-%d %H:%M')
end_time = dt.datetime.strptime(end_date,'%Y-%m-%d %H:%M')
iso_start = start_time.strftime('%Y-%m-%dT%H:%M:%SZ')
iso_end = end_time.strftime('%Y-%m-%dT%H:%M:%SZ')

# Define the SOS collector
collector = NdbcSos()
print collector.server.identification.title
collector.variables = data_dict["waves"]["sos_name"]
collector.server.identification.title

# Don't specify start and end date in the filter and the most recent observation will be returned
collector.filter(bbox=bounding_box,
                 variables=data_dict["waves"]["sos_name"])

response = collector.raw(responseFormat="text/csv")
obs_loc_df = pd.read_csv(BytesIO(response.encode('utf-8')),
                         parse_dates=True,
                         index_col='date_time')

# Now let's specify start and end times
collector.start_time = start_time
collector.end_time = end_time

ofrs = collector.server.offerings


National Data Buoy Center SOS
BBOX requests for IOOS SWE SOS services are not yet implemented

In [9]:
obs_loc_df.head()


Out[9]:
station_id sensor_id latitude (degree) longitude (degree) sea_surface_wave_significant_height (m) sea_surface_wave_peak_period (s) sea_surface_wave_mean_period (s) sea_surface_swell_wave_significant_height (m) sea_surface_swell_wave_period (s) sea_surface_wind_wave_significant_height (m) ... number_of_frequencies (count) center_frequencies (Hz) bandwidths (Hz) spectral_energy (m**2/Hz) mean_wave_direction (degree) principal_wave_direction (degree) polar_coordinate_r1 (1) polar_coordinate_r2 (1) calculation_method sampling_rate (Hz)
date_time
2013-05-09 15:50:00 urn:ioos:station:wmo:41001 urn:ioos:sensor:wmo:41001::wpm1 34.700 -72.730 1.30 5.56 5.28 1.21 NaN 0.47 ... 46 0.0325;0.0375;0.0425;0.0475;0.0525;0.0575;0.06... 0.0050;0.0050;0.0050;0.0050;0.0050;0.0050;0.00... 0;0;0;0;0;0;0;0;0.127096;0.217864;0.164025;0.1... 181.0;359.0;356.0;15.0;129.0;138.0;146.0;228.0... 173.0;356.0;354.0;328.0;120.0;119.0;143.0;152.... 0.450343;0.349387;0.181904;0.271063;0.192072;0... 0.247572;0.612917;0.511283;0.302214;0.58047;0.... Longuet-Higgins (1964) NaN
2014-08-21 18:50:00 urn:ioos:station:wmo:41025 urn:ioos:sensor:wmo:41025::wpm1 35.010 -75.400 0.72 9.09 6.07 0.69 NaN 0.21 ... 46 0.0325;0.0375;0.0425;0.0475;0.0525;0.0575;0.06... 0.0050;0.0050;0.0050;0.0050;0.0050;0.0050;0.00... 0;0;0;0;0;0;0;0.00332548;0.0106128;0.0199573;0... 267.0;86.0;89.0;134.0;300.0;302.0;343.0;34.0;1... 268.0;85.0;87.0;91.0;253.0;325.0;62.0;72.0;98.... 0.54974;0.426502;0.202809;0.247572;0.128895;0.... 0.947061;0.896925;0.695856;0.450343;0.313374;0... Longuet-Higgins (1964) NaN
2014-08-21 18:50:00 urn:ioos:station:wmo:41036 urn:ioos:sensor:wmo:41036::wpm1 34.210 -76.950 0.58 4.76 4.60 0.51 NaN 0.28 ... 46 0.0325;0.0375;0.0425;0.0475;0.0525;0.0575;0.06... 0.0050;0.0050;0.0050;0.0050;0.0050;0.0050;0.00... 0;0;0;0;0;0;0;0.00305586;0.00585562;0.0202496;... 341.0;154.0;165.0;170.0;352.0;174.0;160.0;124.... 348.0;168.0;173.0;170.0;339.0;160.0;235.0;52.0... 0.336945;0.450343;0.175426;0.149014;0.319107;0... 0.930045;0.896925;0.849442;0.849442;0.624131;0... Longuet-Higgins (1964) NaN
2011-05-06 06:50:00 urn:ioos:station:wmo:41x01 urn:ioos:sensor:wmo:41x01::wpm1 34.704 -72.734 1.44 10.81 8.53 NaN NaN NaN ... 46 0.0325;0.0375;0.0425;0.0475;0.0525;0.0575;0.06... 0.0050;0.0050;0.0050;0.0050;0.0050;0.0050;0.00... 0;0;0;0;0;0.0563005;0.477092;1.67018;2.39464;2... ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Longuet-Higgins (1964) NaN
2008-11-21 13:50:00 urn:ioos:station:wmo:44004 urn:ioos:sensor:wmo:44004::wpm1 38.480 -70.430 0.37 21.05 19.35 NaN NaN NaN ... 46 0.0325;0.0375;0.0425;0.0475;0.0525;0.0575;0.06... 0.0050;0.0050;0.0050;0.0050;0.0050;0.0050;0.00... 0;0;0.691109;0.912852;0;0;0;0;0.00760115;0;0;0... ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Longuet-Higgins (1964) NaN

5 rows × 25 columns


In [10]:
stations = [sta.split(':')[-1] for sta in obs_loc_df['station_id']]
obs_lon = [sta for sta in obs_loc_df['longitude (degree)']]
obs_lat = [sta for sta in obs_loc_df['latitude (degree)']]

Request CSV response from SOS and convert to Pandas DataFrames


In [11]:
ts_rng = pd.date_range(start=start_date, end=end_date)
ts = pd.DataFrame(index=ts_rng)

# Save all of the observation data into a list of dataframes
obs_df = []
# Create a list of dataframes for just wave heights for comparing with modeled wave heights later
Hs_obs_df = []

for sta in stations:
    raw_df = collector2df(collector, sta, sos_name)
    obs_df.append(pd.DataFrame(pd.concat([raw_df, ts],axis=1)))
    obs_df[-1].name = raw_df.name
    if raw_df.empty:
        Hs_obs_df.append(pd.DataFrame())
    else:
        Hs_obs_df.append(pd.DataFrame(pd.concat([raw_df, ts],axis=1)['sea_surface_wave_significant_height (m)']))

    Hs_obs_df[-1].name = raw_df.name


BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented
BBOX requests for IOOS SWE SOS services are not yet implemented

Plot the Observation Stations on Map


In [12]:
min_data_pts = 20

# Find center of bounding box
lat_center = abs(bounding_box[3]-bounding_box[1])/2 + bounding_box[1]
lon_center = abs(bounding_box[0]-bounding_box[2])/2 + bounding_box[0]
m = folium.Map(location=[lat_center, lon_center], zoom_start=6)

n = 0
for df in obs_df:
    #get the station data from the sos end point
    longname = df.name
    lat = obs_loc_df['latitude (degree)'][n]
    lon = obs_loc_df['longitude (degree)'][n]
    popup_string = ('<b>Station:</b><br>'+ longname)
    if len(df) > min_data_pts:
        m.simple_marker([lat, lon], popup=popup_string)
    else:
        #popup_string += '<br>No Data Available'
        popup_string += '<br>Not enough data available<br>requested pts: ' + str(min_data_pts ) + '<br>Available pts: ' + str(len(Hs_obs_df[n]))
        m.circle_marker([lat, lon], popup=popup_string, fill_color='#ff0000', radius=10000, line_color='#ff0000')
    n += 1
m.line(get_coordinates(bounding_box,bounding_box_type), line_color='#FF0000', line_weight=5)

inline_map(m)


Out[12]:

In [17]:
### Plot Hs and Tp for each station

In [13]:
for df in obs_df:
    if len(df) > min_data_pts:
        fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(20,5))
        df['sea_surface_wave_significant_height (m)'].plot(ax=axes[0], color='r')
        axes[0].set_title(df.name)
        axes[0].set_ylabel('Hs (m)')
        df['sea_surface_wave_peak_period (s)'].plot(ax=axes[1])
        axes[1].set_title(df.name)
        axes[1].set_ylabel('Tp (s)')


Get model output from OPeNDAP URLS

Try to open all the OPeNDAP URLS using Iris from the British Met Office. If we can open in Iris, we know it's a model result.


In [14]:
name_in_list = lambda cube: cube.standard_name in data_dict['waves']['names']
constraint = iris.Constraint(cube_func=name_in_list)

In [15]:
# Use only data within 0.04 degrees (about 4 km).
max_dist = 0.04
# Use only data where the standard deviation of the time series exceeds 0.01 m (1 cm).
# This eliminates flat line model time series that come from land points that should have had missing values.
min_var = 0.01
for url in dap_urls:
    if 'cdip' in url:
        # The CDIP buoys are known to be observed data, so let's just skip
        continue
    try:
        a = iris.load_cube(url, constraint)
        # take first 20 chars for model name
        mod_name = a.attributes['title'][0:20]
        r = a.shape
        timevar = find_timevar(a)
        lat = a.coord(axis='Y').points
        lon = a.coord(axis='X').points
        jd = timevar.units.num2date(timevar.points)
        start = timevar.units.date2num(jd_start)
        istart = timevar.nearest_neighbour_index(start)
        stop = timevar.units.date2num(jd_stop)
        istop = timevar.nearest_neighbour_index(stop)

        # Only proceed if we have data in the range requested.
        if istart != istop:
            nsta = len(stations)
            if len(r) == 3:
                print('[Structured grid model]:', url)
                d = a[0, :, :].data
                # Find the closest non-land point from a structured grid model.
                if len(lon.shape) == 1:
                    lon, lat = np.meshgrid(lon, lat)
                j, i, dd = find_ij(lon, lat, d, obs_lon, obs_lat)
                for n in range(nsta):
                    # Only use if model cell is within 0.01 degree of requested
                    # location.
                    if dd[n] <= max_dist:
                        arr = a[istart:istop, j[n], i[n]].data
                        if arr.std() >= min_var:
                            c = mod_df(arr, timevar, istart, istop,
                                       mod_name, ts)
                            name = Hs_obs_df[n].name
                            Hs_obs_df[n] = pd.concat([Hs_obs_df[n], c], axis=1)
                            Hs_obs_df[n].name = name
            elif len(r) == 2:
                print('[Unstructured grid model]:', url)
                # Find the closest point from an unstructured grid model.
                index, dd = nearxy(lon.flatten(), lat.flatten(),
                                   obs_lon, obs_lat)
                for n in range(nsta):
                    # Only use if model cell is within 0.1 degree of requested
                    # location.
                    if dd[n] <= max_dist:
                        arr = a[istart:istop, index[n]].data
                        if arr.std() >= min_var:
                            c = mod_df(arr, timevar, istart, istop,
                                       mod_name, ts)
                            name = Hs_obs_df[n].name
                            Hs_obs_df[n] = pd.concat([Hs_obs_df[n], c], axis=1)
                            Hs_obs_df[n].name = name
            elif len(r) == 1:
                print('[Data]:', url)
    except (ValueError, RuntimeError, CoordinateNotFoundError,
            ConstraintMismatchError) as e:
        warn("\n%s\n" % e)
        pass


/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable '3-D_Temperature_hybrid_layer' invalid units 'c'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'hybrid_layer' invalid units 'sigma'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable '3-D_Salinity_hybrid_layer' invalid units 'psu'
  warnings.warn(msg.format(msg_name, msg_units))
-c:65: UserWarning: 
Expected exactly one cube, found 0.

/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable '3-D_Salinity_ocean_mixed' invalid units 'psu'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable '3-D_Temperature_ocean_mixed' invalid units 'c'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'nbdv' invalid units 'nondimensional'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'neta' invalid units 'nondimensional'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'ibtypee' invalid units 'nondimensional'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'nvell' invalid units 'nondimensional'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'ibtype' invalid units 'nondimensional'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'nbvv' invalid units 'nondimensional'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'nvel' invalid units 'nondimensional'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'nvdll' invalid units 'nondimensional'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1216: UserWarning: Gracefully filling 'time' dimension coordinate masked points
  warnings.warn(msg.format(str(cf_coord_var.cf_name)))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'chlorophyll' invalid units 'milligrams_chlorophyll meter-3'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'phytoplankton' invalid units 'millimole_nitrogen meter-3'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'NO3' invalid units 'millimole_N03 meter-3'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'zooplankton' invalid units 'millimole_nitrogen meter-3'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'NH4' invalid units 'millimole_NH4 meter-3'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'surface_flag' invalid units 'none'
  warnings.warn(msg.format(msg_name, msg_units))
-c:65: UserWarning: 
NetCDF: Malformed or inaccessible DAP DDS

Exception AttributeError: "'CFReader' object has no attribute '_dataset'" in <bound method CFReader.__del__ of CFReader('http://sos.maracoos.org/stable/dodsC/wflow1127-agg.ncml')> ignored
Exception AttributeError: "'CFReader' object has no attribute '_dataset'" in <bound method CFReader.__del__ of CFReader('http://sos.maracoos.org/stable/dodsC/wflow397-agg.ncml')> ignored
Exception AttributeError: "'CFReader' object has no attribute '_dataset'" in <bound method CFReader.__del__ of CFReader('http://sos.maracoos.org/stable/dodsC/wflow697-agg.ncml')> ignored
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'ndvi' invalid units 'dimensionless'
  warnings.warn(msg.format(msg_name, msg_units))
Exception AttributeError: "'CFReader' object has no attribute '_dataset'" in <bound method CFReader.__del__ of CFReader('http://sos.maracoos.org/stable/dodsC/wflow700-agg.ncml')> ignored
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1280: UserWarning: Failed to create 'time' dimension coordinate: The points array must be strictly monotonic.
Gracefully creating 'time' auxiliary coordinate instead.
  error=e_msg))
('[Structured grid model]:', 'http://geoport.whoi.edu/thredds/dodsC/coawst_4/use/fmrc/coawst_4_use_best.ncd')
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'reftime1_ISO' invalid units 'ISO8601'
  warnings.warn(msg.format(msg_name, msg_units))
/Users/bobfratantonio/anaconda/envs/test_model_obs_waves/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1147: UserWarning: Ignoring netCDF variable 'reftime_ISO' invalid units 'ISO8601'
  warnings.warn(msg.format(msg_name, msg_units))

Plot Modeled vs Obs Wave Height


In [16]:
for df in Hs_obs_df:
    # Make sure there is obs data at the station for comparison
    if 'sea_surface_wave_significant_height (m)' in df.columns:
        ax = df.plot(figsize=(14, 6), title=df.name, legend=False)
        plt.setp(ax.lines[0], linewidth=4.0, color='0.7', zorder=1, marker='.')
        ax.legend()
        ax.set_ylabel('m')