karpathy-sleep / app.py
Hannah
add data
33ecdbc
raw
history blame
5.11 kB
import gradio as gr
import numpy as np
import pandas as pd
def load_health_data():
# Load the CSV file into a pandas DataFrame
df = pd.read_csv('healthdata.csv', header=2)
# Replace null values with empty strings
df = df.replace({np.nan: "", None: ""})
return df
def get_device_data(device):
df = load_health_data()
# Common columns for all devices
base_cols = ['Day', 'Date', 'Day of Week']
if device == "AppleWatch + AutoSleep":
# Get columns with AS suffix + base columns
device_cols = base_cols + [col for col in df.columns if 'AS' in col]
elif device == "8sleep Pod 4 Ultra":
# Get columns with 8S suffix + base columns
device_cols = base_cols + [col for col in df.columns if '8S' in col]
elif device == "Oura":
# Get columns with OU suffix + base columns
device_cols = base_cols + [col for col in df.columns if 'OU' in col]
elif device == "Whoop":
# Get columns with WH suffix + base columns
device_cols = base_cols + [col for col in df.columns if 'WH' in col]
else:
return df
# Add the Average and Notes columns if they exist
if 'Average' in df.columns:
device_cols.append('Average')
if 'Notes' in df.columns:
device_cols.append('Notes')
return df[device_cols]
def get_color_for_value(val, min_val, max_val):
"""Return a color based on where the value falls in the range"""
if min_val == max_val:
return "" # No color if all values are the same
normalized = (val - min_val) / (max_val - min_val)
if normalized < 0.33:
return "" # Low values are blank
elif normalized < 0.66:
# Medium values are green
intensity = int(255 * ((normalized - 0.33) / 0.33))
return f"background-color: rgba(0, {intensity}, 0, 0.3)"
else:
# High values are red
intensity = int(255 * ((normalized - 0.66) / 0.34))
return f"background-color: rgba({intensity}, 0, 0, 0.3)"
def prepare_data_with_styling(df):
data = df.values.tolist()
headers = list(df.columns)
# Get min/max for each numeric column
col_ranges = {}
for i, col in enumerate(headers):
if col not in ['Day', 'Date', 'Day of Week', 'Notes']:
try:
values = [float(row[i]) for row in data if row[i] != "" and pd.notna(row[i])]
if values:
col_ranges[i] = {'min': min(values), 'max': max(values)}
except (ValueError, TypeError):
continue
# Create styling
styling = []
for row in data:
row_styling = []
for i, val in enumerate(row):
if i in col_ranges and val != "" and pd.notna(val):
try:
val_float = float(val)
style = get_color_for_value(val_float, col_ranges[i]['min'], col_ranges[i]['max'])
row_styling.append(["", f"width: var(--cell-width-3); left: auto; {style}"])
except (ValueError, TypeError):
row_styling.append(["", ""])
else:
row_styling.append(["", ""])
styling.append(row_styling)
return {
"data": data,
"headers": headers,
"metadata": {
"styling": styling
}
}
column_widths = [70,150,150,150,150]
# Create the Gradio application using Blocks
with gr.Blocks(title="@Andrej Karpathy's Sleep Data") as demo:
gr.Markdown("# @karpathy's Sleep Data")
gr.Markdown("This app displays Andrej Karpathy's sleep tracking data from multiple devices. See his [blog post](https://karpathy.bearblog.dev/finding-the-best-sleep-tracker/) to learn more about the data and the process of finding the best sleep tracker.")
with gr.Tabs():
with gr.TabItem("AppleWatch + AutoSleep"):
df = get_device_data("AppleWatch + AutoSleep")
gr.Dataframe(prepare_data_with_styling(df), show_search="search", column_widths=column_widths, show_copy_button=True, pinned_columns=1)
with gr.TabItem("8sleep Pod 4 Ultra"):
df = get_device_data("8sleep Pod 4 Ultra")
gr.Dataframe(prepare_data_with_styling(df), show_search="search", column_widths=column_widths, show_copy_button=True, pinned_columns=1)
with gr.TabItem("Oura"):
df = get_device_data("Oura")
gr.Dataframe(prepare_data_with_styling(df), show_search="search", column_widths=column_widths, show_copy_button=True, pinned_columns=1)
with gr.TabItem("Whoop"):
df = get_device_data("Whoop")
gr.Dataframe(prepare_data_with_styling(df), show_search="search", column_widths=column_widths, show_copy_button=True, pinned_columns=1)
with gr.TabItem("All Data"):
df = load_health_data()
gr.Dataframe(prepare_data_with_styling(df), show_search="search", column_widths=column_widths, show_copy_button=True, pinned_columns=1)
if __name__ == "__main__":
demo.launch()