SECOORA Notebook 3

Sea Surface Salinity time-series maps

Run 00-fetch_data.ipynb and 01-skill_score.ipynb first.

Load configuration


In [1]:
import os

try:
    import cPickle as pickle
except ImportError:
    import pickle

run_name = '2014-07-07'
fname = os.path.join(run_name, 'config.pkl')
with open(fname, 'rb') as f:
    config = pickle.load(f)

Load skill_score


In [2]:
try:
    import cPickle as pickle
except ImportError:
    import pickle

fname = os.path.join(run_name, 'skill_score.pkl')
with open(fname, 'rb') as f:
    skill_score = pickle.load(f)

In [3]:
from mpld3 import save_html
import matplotlib.pyplot as plt
from mpld3.plugins import LineLabelTooltip, connect

from utilities import make_map

bbox = config['bbox']
units = config['units']
run_name = config['run_name']
secoora_models = config['secoora_models']

kw = dict(line=True, states=False, hf_radar=True, layers=False)
mapa = make_map(bbox, **kw)

ROMS stations files (SABGOM and USEAST)


In [4]:
import folium

roms_stations = [(-77.7866, 34.2133),
                 (-78.9183, 33.6550),
                 (-81.0000, 30.3966),
                 (-80.1600, 25.7300),
                 (-81.8116, 24.5550),
                 (-82.6137, 26.1300),
                 (-82.8320, 27.9770),
                 (-86.4987, 30.1520)]

for station in roms_stations:
    location = station[::-1]
    popup = '[SABGOM/USEAST]\nROMS station file'
    kw = dict(radius=700, fill_color='red', popup=popup,
              fill_opacity=0.75)
    folium.CircleMarker(location=location, **kw).add_to(mapa)

Clusters


In [5]:
from glob import glob
from operator import itemgetter

import iris
from pandas import DataFrame, read_csv
from folium.plugins import MarkerCluster

fname = '{}-all_obs.csv'.format(run_name)
all_obs = read_csv(os.path.join(run_name, fname), index_col='name')

big_list = []
for fname in glob(os.path.join(run_name, "*.nc")):
    if 'OBS_DATA' in fname:
        continue
    cube = iris.load_cube(fname)
    model = fname.split('-')[-1].split('.')[0]
    lons = cube.coord(axis='X').points
    lats = cube.coord(axis='Y').points
    stations = cube.coord('station name').points
    models = [model]*lons.size
    lista = zip(models, lons.tolist(), lats.tolist(), stations.tolist())
    big_list.extend(lista)

big_list.sort(key=itemgetter(3))
df = DataFrame(big_list, columns=['name', 'lon', 'lat', 'station'])
df.set_index('station', drop=True, inplace=True)
groups = df.groupby(df.index)


locations, popups = [], []
for station, info in groups:
    sta_name = all_obs['station'][all_obs['station'] == station].index[0]
    for lat, lon, name in zip(info.lat, info.lon, info.name):
        locations.append([lat, lon])
        popups.append('[{}]: {}'.format(name, sta_name))

mapa.add_children(MarkerCluster(locations=locations, popups=popups))

Model and observations plots


In [6]:
from folium.element import IFrame
from utilities import load_secoora_ncs

mean_bias = skill_score['mean_bias'].applymap('{:.2f}'.format).replace('nan', '--')
low_pass_r2 = skill_score['low_pass_resampled_3H_r2'].applymap('{:.2f}'.format).replace('nan', '--')

resolution, width, height = 75, 7, 3

def make_plot():
    fig, ax = plt.subplots(figsize=(width, height))
    ax.set_ylabel('Sea surface salinity ({})'.format(units))
    ax.grid(True)
    return fig, ax


dfs = load_secoora_ncs(run_name)
# SABGOM dt = 3 hours.
dfs = dfs.swapaxes('items', 'major').resample('3H').swapaxes('items', 'major')

for station in dfs:
    df = dfs[station].dropna(axis=1, how='all')
    if df.empty:
        continue
    labels = []
    fig, ax = make_plot()
    for col in df.columns:
        serie = df[col].dropna()
        lines = ax.plot(serie.index, serie, label=col,
                        linewidth=2.5, alpha=0.5)
        if 'OBS_DATA' not in col:
            text0 = col
            text1 = mean_bias.get(station).get(col, '--')
            text2 = low_pass_r2.get(station).get(col, '--')
            tooltip = '{}:\nbias {}\nskill: {}'.format
            labels.append(tooltip(text0, text1, text2))
        else:
            labels.append('OBS_DATA')
    kw = dict(loc='upper center', bbox_to_anchor=(0.5, 1.05), numpoints=1,
              ncol=2, framealpha=0)
    l = ax.legend(**kw)
    l.set_title("")  # Workaround str(None).

    [connect(fig, LineLabelTooltip(line, name))
     for line, name in zip(ax.lines, labels)]

    html = 'station_{}.html'.format(station)
    figname = '{}/{}'.format(run_name, html)
    save_html(fig, figname)
    plt.close(fig)

    with open(figname, 'r') as f:
        html = f.read()
    iframe = IFrame(html, width=(width*resolution)+75, height=(height*resolution)+50)
    popup = folium.Popup(iframe, max_width=2650)

    if (df.columns == 'OBS_DATA').all():
        icon = folium.Icon(color='blue', icon_color='white', icon='ok')
    else:
        conj = set(df.columns)
        conj.intersection_update(secoora_models)
        if conj:
            icon = folium.Icon(color='green', icon_color='white', icon='ok-sign')
        else:
            icon = folium.Icon(color='green', icon_color='white', icon='ok')
    obs = all_obs[all_obs['station'] == station].squeeze()
    folium.Marker(location=[obs['lat'], obs['lon']], icon=icon, popup=popup).add_to(mapa)

Bad stations


In [7]:
bad_station = all_obs[all_obs['bad_station']]

if not bad_station.empty:
    for station, obs in bad_station.iterrows():
        popup = '[Station]: {}'
        popup = popup.format(station)
        icon = folium.Icon(color='red', icon_color='white', icon='question-sign')
        folium.Marker(location=[obs['lat'], obs['lon']], icon=icon, popup=popup).add_to(mapa)

Map


In [8]:
mapa.save(os.path.join(run_name, 'mapa.html'))
mapa


/home/filipe/miniconda3/envs/secoora-skill/lib/python2.7/site-packages/IPython/core/formatters.py:90: DeprecationWarning: DisplayFormatter._ipython_display_formatter_default is deprecated: use @default decorator instead.
  def _ipython_display_formatter_default(self):
/home/filipe/miniconda3/envs/secoora-skill/lib/python2.7/site-packages/IPython/core/formatters.py:96: DeprecationWarning: DisplayFormatter._formatters_default is deprecated: use @default decorator instead.
  def _formatters_default(self):
/home/filipe/miniconda3/envs/secoora-skill/lib/python2.7/site-packages/IPython/core/formatters.py:675: DeprecationWarning: PlainTextFormatter._deferred_printers_default is deprecated: use @default decorator instead.
  def _deferred_printers_default(self):
/home/filipe/miniconda3/envs/secoora-skill/lib/python2.7/site-packages/IPython/core/formatters.py:667: DeprecationWarning: PlainTextFormatter._singleton_printers_default is deprecated: use @default decorator instead.
  def _singleton_printers_default(self):
/home/filipe/miniconda3/envs/secoora-skill/lib/python2.7/site-packages/IPython/core/formatters.py:670: DeprecationWarning: PlainTextFormatter._type_printers_default is deprecated: use @default decorator instead.
  def _type_printers_default(self):
/home/filipe/miniconda3/envs/secoora-skill/lib/python2.7/site-packages/IPython/core/formatters.py:667: DeprecationWarning: PlainTextFormatter._singleton_printers_default is deprecated: use @default decorator instead.
  def _singleton_printers_default(self):
/home/filipe/miniconda3/envs/secoora-skill/lib/python2.7/site-packages/IPython/core/formatters.py:670: DeprecationWarning: PlainTextFormatter._type_printers_default is deprecated: use @default decorator instead.
  def _type_printers_default(self):
/home/filipe/miniconda3/envs/secoora-skill/lib/python2.7/site-packages/IPython/core/formatters.py:675: DeprecationWarning: PlainTextFormatter._deferred_printers_default is deprecated: use @default decorator instead.
  def _deferred_printers_default(self):
Out[8]: