Spaces:
Running
Running
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() | |