#!/usr/bin/env python # coding: utf-8 # # PMV Storm Surge Alert Feed Generator # # Notebook to generate `pmv.xml` feed while `nowcast.workers.make_feeds` # worker is in development. # In[1]: import datetime import os from pprint import pprint import arrow import docutils.core from feedgen.feed import FeedGenerator import mako.template import netCDF4 as nc import numpy as np from salishsea_tools import ( nc_tools, stormtools, unit_conversions, wind_tools, ) from salishsea_tools.places import PLACES from nowcast import figures # In[67]: get_ipython().system('sshfs skookum:/results results') # In[2]: today = arrow.now('Canada/Pacific').floor('day') forecast = 'forecast2' run_date = today if forecast == 'forecast' else today.replace(days=-1) os.path.join(forecast, run_date.format('DDMMMYY').lower()) # #### Calculating the Values to use in the Template # # The `nowcast.figures.plot_threshold_website()` has code # (reproduced below) that calculates: # * The maximum sea surface height in a `grid_T` run results file # * The time at which it occurs # In[69]: from importlib import reload reload(figures) reload(nc_tools) # In[3]: tide_gauge_stn = 'Point Atkinson' results_file = ('results/SalishSea/{forecast}/{dmy}/{}.nc' .format(tide_gauge_stn.replace(' ', ''), forecast=forecast, dmy=run_date.format('DDMMMYY').lower())) print(results_file) grid_T_15m = nc.Dataset(results_file) tidal_predictions = 'results/nowcast-sys/tools/SalishSeaNowcast/nowcast/tidal_predictions/' ssh_model, t_model = nc_tools.ssh_timeseries_at_point(grid_T_15m, 0, 0, datetimes=True) ttide = figures.get_tides(tide_gauge_stn, tidal_predictions) ssh_corr = figures.correct_model_ssh(ssh_model, t_model, ttide) max_ssh = np.max(ssh_corr) + PLACES[tide_gauge_stn]['mean sea lvl'] max_ssh_time = t_model[np.argmax(ssh_corr)] # From those results we can calculate: # * Maximum water level above chart datum in metres # * Date and time of the maximum water level with the appropriate timezone indicated # In[4]: max_ssh, arrow.get(max_ssh_time).to('local') # Formating the date/time would be easy if it weren't for adding the timezone name: # In[5]: a = arrow.get(max_ssh_time).to('local') '{datetime} [{tzname}]'.format(datetime=a.format('ddd MMM DD, YYYY HH:mm'), tzname=a.tzinfo.tzname(a.datetime)) # In[6]: unit_conversions.humanize_time_of_day(a) # In[7]: risk_level = stormtools.storm_surge_risk_level('Point Atkinson', max_ssh, ttide) print(risk_level) # In[16]: weather_path = 'results/forcing/atmospheric/GEM2.5/operational/fcst' weather = nc.Dataset(os.path.join(weather_path, '{:ops_y%Ym%md%d.nc}'.format(max_ssh_time))) print(os.path.join(weather_path, '{:ops_y%Ym%md%d.nc}'.format(max_ssh_time))) wind = nc_tools.uv_wind_timeseries_at_point(weather, *PLACES[tide_gauge_stn]['wind grid ji']) i_max_ssh_wind = np.asscalar( np.where( wind.time == arrow.get( max_ssh_time.year, max_ssh_time.month, max_ssh_time.day, max_ssh_time.hour))[0]) print(i_max_ssh_wind, wind.time[i_max_ssh_wind].to('local')) print(wind.u[i_max_ssh_wind], wind.v[i_max_ssh_wind]) # In[17]: wind_tools.wind_speed_dir(wind.u[i_max_ssh_wind], wind.v[i_max_ssh_wind]) # In[58]: u_wind_4h_avg = np.mean(wind.u[max(i_max_ssh_wind-4, 0):i_max_ssh_wind]) v_wind_4h_avg = np.mean(wind.v[max(i_max_ssh_wind-4, 0):i_max_ssh_wind]) u_wind_4h_avg, v_wind_4h_avg # In[59]: wind_speed_4h_avg, wind_dir_4h_avg = wind_tools.wind_speed_dir(u_wind_4h_avg, v_wind_4h_avg) wind_speed_4h_avg, wind_dir_4h_avg # In[60]: unit_conversions.mps_kph(wind_speed_4h_avg), unit_conversions.mps_knots(wind_speed_4h_avg) # In[61]: unit_conversions.wind_to_from(wind_dir_4h_avg) # In[62]: unit_conversions.bearing_heading(unit_conversions.wind_to_from(wind_dir_4h_avg)) # #### Rendering the Template for the `summary` Element # # We'll start with a reStructuredText template based on `SalishSeaNowcast/nowcast/www/templates/surgetext.mako`: # In[63]: max_ssh_time_local = arrow.get(max_ssh_time).to('local') values = { 'city': 'Vancouver', 'tide_gauge_stn': 'Point Atkinson', 'conditions': { 'Point Atkinson': { 'risk_level': risk_level, 'max_ssh_msl': max_ssh, 'wind_speed_4h_avg_kph': unit_conversions.mps_kph(wind_speed_4h_avg), 'wind_speed_4h_avg_knots': unit_conversions.mps_knots(wind_speed_4h_avg), 'wind_dir_4h_avg_heading':unit_conversions.bearing_heading( unit_conversions.wind_to_from(wind_dir_4h_avg)), 'wind_dir_4h_avg_bearing': unit_conversions.wind_to_from(wind_dir_4h_avg), 'max_ssh_time': max_ssh_time_local, 'max_ssh_time_tzname': max_ssh_time_local.tzinfo.tzname(max_ssh_time_local.datetime), 'humanized_max_ssh_time': unit_conversions.humanize_time_of_day(max_ssh_time_local), }, }, } # In[64]: fg = FeedGenerator() utcnow = arrow.utcnow() fg.title('Salish Sea NEMO Model Storm Surge Alerts for Port Metro Vancouver') fg.id( 'tag:salishsea.eos.ubc.ca,2015-12-12:/storm-surge/atom/pmv/{utcnow}' .format(utcnow=utcnow.format('YYYYMMDDHHmmss'))) fg.language('en-ca') fg.author(name='Salish Sea MEOPAR Project', uri='http://salishsea.eos.ubc.ca/') fg.rights( 'Copyright {this_year}, Salish Sea MEOPAR Project Contributors and The University of British Columbia' .format(this_year=utcnow.year)) fg.link(href='http://salishsea.eos.ubc.ca/storm-surge/atom/pmv.xml', rel='self', type='application/atom+xml') fg.link(href='http://salishsea.eos.ubc.ca/storm-surge/forecast.html', rel='related', type='text/html') if risk_level is not None: rendered_rst = mako.template.Template( filename='../../tools/SalishSeaNowcast/nowcast/www/templates/storm_surge_advisory.mako').render(**values) html = docutils.core.publish_parts(rendered_rst, writer_name='html') now = arrow.now() fe = fg.add_entry() fe.title('Storm Surge Alert for Point Atkinson') fe.id( 'tag:salishsea.eos.ubc.ca,{today}:/storm-surge/atom/pmv/{now}' .format( today=now.format('YYYY-MM-DD'), now=now.format('YYYYMMDDHHmmss'))) fe.author(name='Salish Sea MEOPAR Project', uri='http://salishsea.eos.ubc.ca/') fe.content(html['body'], type='html') fe.link( rel='alternate', type='text/html', href='http://salishsea.eos.ubc.ca/nemo/results/{forecast}/publish_{day}.html' .format(forecast=forecast, day=today.replace(days=+1).format('DDMMMYY').lower()), ) pprint(fg.atom_str(pretty=True).decode('utf8')) # In[65]: fg.atom_file('pmv.xml', pretty=True) # In[66]: get_ipython().system('scp pmv.xml skookum:public_html/MEOPAR/nowcast/www/salishsea-site/site/storm-surge/atom/') # On `skookum`: # ``` # scp /home/dlatorne/public_html/MEOPAR/nowcast/www/salishsea-site/site/storm-surge/atom/pmv.xml shelob:/www/salishsea/data/storm-surge/atom/ # ```