Skip to content

Instantly share code, notes, and snippets.

@rameshvarun
Last active May 17, 2021 22:39
Show Gist options
  • Save rameshvarun/ee1803ea367833738ffcabe630844683 to your computer and use it in GitHub Desktop.
Save rameshvarun/ee1803ea367833738ffcabe630844683 to your computer and use it in GitHub Desktop.
Plot FitBit sleep schedule using Matplotlib.
#!/usr/bin/env python3
import glob
import csv
import itertools
from datetime import datetime, timedelta, time
from collections import namedtuple
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
def consume(iterator, n=None):
"Advance the iterator n-steps ahead. If n is None, consume entirely."
if n is None:
collections.deque(iterator, maxlen=0)
else:
next(itertools.islice(iterator, n, n), None)
SleepEntry = namedtuple("SleepEntry", ["start", "end"])
DATE_FORMAT = "%Y-%m-%d %I:%M%p"
BLOCKS_PER_DAY = 24 * 2
SPLIT_HOUR = 12 + 4
if __name__ == "__main__":
sleep_entries = []
for file in glob.iglob("./data/*.csv"):
with open(file, "r") as f:
reader = csv.reader(f)
consume(reader, 2)
for row in reader:
if len(row) > 2:
sleep_entries.append(
SleepEntry(
start=datetime.strptime(row[0], DATE_FORMAT),
end=datetime.strptime(row[1], DATE_FORMAT),
)
)
earliest_time = min([e.start for e in sleep_entries])
latest_time = max([e.end for e in sleep_entries])
print("Earliest Time: %s, Latest Time: %s" % (earliest_time, latest_time))
print(len(sleep_entries), "entries.")
start_date = datetime.combine(earliest_time.date(), time(SPLIT_HOUR, 0))
end_date = datetime.combine(latest_time.date(), time(SPLIT_HOUR, 0))
days = (end_date - start_date).days
print(days, "days.")
sleep_matrix = np.zeros((BLOCKS_PER_DAY, days))
for i, j in itertools.product(range(BLOCKS_PER_DAY), range(days)):
dt = start_date + timedelta(days=j, hours=i // 2, minutes=30 * (i % 2))
if any([(dt >= entry.start and dt < entry.end) for entry in sleep_entries]):
sleep_matrix[i, j] = 1.0
fig, ax = plt.subplots()
im = ax.imshow(sleep_matrix)
ax.set_yticks(range(BLOCKS_PER_DAY))
ax.set_yticklabels(
[
time((SPLIT_HOUR + i // 2) % 24, 30 * (i % 2)).strftime("%-I:%M%p")
for i in range(BLOCKS_PER_DAY)
]
)
ax.set_xticks(range(days))
ax.set_xticklabels(
[(start_date + timedelta(days=j)).strftime("%b-%-d") for j in range(days)],
rotation="vertical",
)
patches = [
mpatches.Patch(color=im.cmap(im.norm(0)), label="Awake"),
mpatches.Patch(color=im.cmap(im.norm(1)), label="Sleep"),
]
ax.legend(handles=patches)
for label in ax.yaxis.get_ticklabels()[1::2]:
label.set_visible(False)
for label in ax.xaxis.get_ticklabels():
label.set_visible(False)
for label in ax.xaxis.get_ticklabels()[::5]:
label.set_visible(True)
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment