Skip to content

Instantly share code, notes, and snippets.

@pavi2410
Created September 14, 2022 16:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pavi2410/f69c0be890ae7c5183b04908796ceae0 to your computer and use it in GitHub Desktop.
Save pavi2410/f69c0be890ae7c5183b04908796ceae0 to your computer and use it in GitHub Desktop.
Dense Timeline plot
import pandas as pd
import matplotlib.pyplot as plt
import itertools
from datetime import datetime, timedelta
from matplotlib.patches import Patch
plt.figure(figsize=(30, 10), constrained_layout=True)
xscale = 3
sleep_start, sleep_end = 0.75, 1.375
min_per_day = 24 * 60
xd = hdf['date'].unique()
xs, xe, xt = hdf['date'].min(), hdf['date'].max(), hdf['date'].nunique()
period = pd.date_range(start=xs, end=xe)
days = len(period)
todate = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
tr = range(int(sleep_start*min_per_day), int(sleep_end*min_per_day)+1, 60)
for cur_date in period:
t = cur_date.day - xs.day
blocks = 1+(1+days)*xscale
xoff = (1+t)*xscale
x1, x2, x3 = round((xoff-.48)/blocks, 5), round((xoff+.55)/blocks, 5), round((xoff+1.48)/blocks, 5)
hhdf = hdf.query('date == @cur_date').eval('''
ys = (start.dt.hour * 60 + start.dt.minute) / @min_per_day
ye = (end.dt.hour * 60 + end.dt.minute) / @min_per_day
yd = 1 - ys + ye
''')
ahdf = hhdf.query('source == "apollo"')
ohdf = hhdf.query('source == "oura"')
if ahdf.size > 0:
plt.bar(x=t*xscale, align='edge',width=-1, color='dodgerblue', bottom=ahdf['ys'].values[0], height=ahdf['yd'].values[0])
if ohdf.size > 0:
plt.bar(x=t*xscale, align='edge', width=1, color='tomato', bottom=ohdf['ys'].values[0], height=ohdf['yd'].values[0])
for ts in sa_times:
tm = (ts.hour*60+ts.minute)/min_per_day
if ts.date() == cur_date and tm >= sleep_start:
plt.axhline(y=tm, xmin=x1, xmax=x2, color='lightsteelblue')
if ts.date() == cur_date + timedelta(days=1) and 1+tm <= sleep_end:
plt.axhline(y=1+tm, xmin=x1, xmax=x2, color='lightsteelblue')
for ts in dist_times:
tm = (ts.hour*60+ts.minute)/min_per_day
if ts.date() == cur_date and tm >= sleep_start:
plt.axhline(y=tm, xmin=x2, xmax=x3, color='brown')
if ts.date() == cur_date + timedelta(days=1) and 1+tm <= sleep_end:
plt.axhline(y=1+tm, xmin=x2, xmax=x3, color='brown')
plt.ylim((sleep_end, sleep_start))
plt.yticks([z/min_per_day for z in tr], [(todate + timedelta(minutes=m)).strftime("%I %p") for m in tr])
plt.xticks([t*xscale for t in range(days)], [d.strftime("%Y/%m/%d\n%a") for d in period], rotation=90)
plt.xlabel('bedtime start date')
plt.ylabel('local bedtime')
plt.legend([Patch(color='dodgerblue'), Patch(color='tomato'), plt.axhline(color='lightsteelblue'), plt.axhline(color='brown')], ['apollo', 'oura', 'stay asleep vibes', 'disturbances (oura)'])
plt.title("Timeline chart depicting the sleeping activity of a user over a time span")
plt.tight_layout()
plt.show()
@pavi2410
Copy link
Author

Preview

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment