Read in data from 1_calc_daily_noise.ipynb and plot using Bokeh.
from datetime import datetime, timedelta
import pandas as pd
# Load modules for interactive plotting
import bokeh
from bokeh.models import Line, Span, ColumnDataSource, DatetimeTickFormatter, HoverTool, CustomJS
from bokeh.plotting import figure, output_notebook, show, output_file
from bokeh import events
import time
output_notebook()
# Set x-axis limits for plotting
# datetime(YEAR, MONTH, DAY)
tmin = datetime(2020, 2, 9)
tmax = datetime(2020, 5, 15)
fname = 'LD.CPNY.2020-02-09.2020-05-15.5_15Hz.BHZ'
datadir = './Data/'
df = pd.read_csv(datadir+fname+'.csv',parse_dates=['t_cent'])
# NYC stay at home 2020/3/22 8pm EST (UTC - 4)
nyc_SAH = datetime(2020,3,22,20,0) + timedelta(0,4*60*60)
# NYC First COVID-19 death 2020/3/14 EST (UTC - 4)
nyc_1st = datetime(2020,3,14,0,0)
# NYC subway closed 1am-5am 2020/5/6 EST (UTC - 4)
nyc_subway = datetime(2020,5,6,0,0)
# Convert timestamps to NYC local time
df = df.set_index('t_cent').tz_localize('UTC').tz_convert('America/New_York')
df = df.reset_index()
df
# Manually shift timezone to NYC local time since Bokeh doesn't understand timezones
dfnyc = df.copy()
dfnyc['t_cent'] = dfnyc.t_cent.dt.tz_localize(None)
for ii, f in enumerate(df):
hr_utcoffset = pd.Timestamp.utcoffset(df.t_cent[ii]).total_seconds()/60/60
dfnyc['t_cent'][ii] = df['t_cent'][ii] + pd.Timedelta(hours=hr_utcoffset)
df = dfnyc
df.head()
/Users/russell/anaconda/lib/python3.5/site-packages/ipykernel/__main__.py:30: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
t_cent | disp_avg | daily_average | |
---|---|---|---|
0 | 2020-02-08 19:30:00 | 1.107801e-09 | NaN |
1 | 2020-02-08 20:30:00 | 1.079529e-09 | NaN |
2 | 2020-02-08 21:30:00 | 1.026666e-09 | NaN |
3 | 2020-02-08 22:30:00 | 9.982165e-10 | NaN |
4 | 2020-02-08 23:30:00 | 9.570202e-10 | NaN |
# Build interactive plots using Bokeh
# Define figure attributes
p = figure(x_axis_type='datetime',plot_width=800, plot_height=500, sizing_mode = 'scale_width',
x_range=(df.t_cent.min(),df.t_cent.max()), y_range=([df.disp_avg.min()*1e9*0.7, df.disp_avg.max()*1e9*1.05]),
x_axis_label='Date', y_axis_label='Average Ground Displacement (nm)', title='NYC Seismic Noise (5-15 Hz)',
tools=['save','box_zoom','xwheel_zoom','ywheel_zoom','reset','crosshair','pan'])
# Plot lines for hourly and daily displacement
# create a datetime string for the hover tool
df['t_centstr'] = df.t_cent.dt.strftime("%Y-%m-%d %H:%M")
source = ColumnDataSource(data={'t_cent':df.t_cent, 'disp_avg':df.disp_avg*1e9,
'daily_average':df.daily_average*1e9, 't_centstr':df.t_centstr})
# Plot hourly noise
l1 = p.line('t_cent', 'disp_avg', source=source, line_color="lightsteelblue",
line_width=2, legend_label="Hourly Noise")
p.add_tools(HoverTool(renderers=[l1], tooltips=[("Date", "@t_centstr"),("Hourly Noise Level","@disp_avg")]))
# Plot daily noise
l2 = p.line('t_cent', 'daily_average', source=source, line_color="steelblue",
line_width=4, legend_label="Daily Noise")
p.add_tools(HoverTool(renderers=[l2], tooltips=[("Date", "@t_centstr"),("Daily Noise Level","@daily_average")]))
/Users/russell/anaconda/lib/python3.5/site-packages/bokeh/plotting/helpers.py:689: UserWarning: WheelZoomTool are being repeated warnings.warn("%s are being repeated" % ",".join(repeated_tools))
# Plot vertical lines marking stay at home and first nyc death
# First need to convert datetime to milliseconds for some reason...
nyc_SAH_ms = time.mktime(nyc_SAH.timetuple())*1000
nyc_1st_ms = time.mktime(nyc_1st.timetuple())*1000
nyc_subway_ms = time.mktime(nyc_subway.timetuple())*1000
# Add vertical line for first NYC fatality
nyc_1st_start = Span(location=nyc_1st_ms, dimension='height', line_color='firebrick',
line_dash='solid', line_width=3)
p.add_layout(nyc_1st_start)
# Add a phantom line for legend purposes since Span does not have legend property
p.line([], [], legend_label="First NYC COVID-19 fatality", line_color='firebrick', line_dash='solid', line_width=3)
# Add vertical line for stay at home order
nyc_SAH_start = Span(location=nyc_SAH_ms, dimension='height', line_color='firebrick',
line_dash='dashed', line_width=3)
p.add_layout(nyc_SAH_start)
p.line([], [], legend_label="NYC stay at home order", line_color='firebrick', line_dash='dashed', line_width=3)
# Add vertical line when NYC subway closes
nyc_subway_start = Span(location=nyc_subway_ms, dimension='height', line_color='firebrick',
line_dash='dotted', line_width=3)
p.add_layout(nyc_subway_start)
p.line([], [], legend_label="Subway closes overnight", line_color='firebrick', line_dash='dotted', line_width=3)
Tip: Double click to toggle legend on/of
p.legend.location = "top_right"
# p.legend.click_policy = "hide"
# Set up double click toggle legend
def show_hide_legend(legend=p.legend[0]):
legend.visible = not legend.visible
p.js_on_event(events.DoubleTap, CustomJS.from_py_func(show_hide_legend))
# Save local file
output_file(fname+'.html')
# Show plot in browser
show(p)
BokehDeprecationWarning: 'from_py_func' is deprecated and will be removed in an eventual 2.0 release. Use CustomJS directly instead.