tylrktran/eating_patterns
0
1import pandas as pd2import numpy as np3 4FOODS_PATH = "data/foods.parquet" 5WINDOWS_PATH = "data/windows.parquet" # columns: user_number, start95, end95, eating_interval6 7# constants8HOUR_COLS = [str(i) for i in range(4, 28)] # '4'..'27'9HAB_COLS = ["7+", "8+", "9+", "10+", "11+", "12+", "13+", "=14"]10 11 12def label_hour(col_str: str) -> str:13 h = int(col_str) % 2414 return f"{h:02d}:00"15 16 17def clock_label(v) -> str:18 if pd.isna(v):19 return "—"20 v = float(v) % 2421 h = int(v)22 m = int(round((v - h) * 60))23 if m == 60:24 h, m = (h + 1) % 24, 025 ampm = "AM" if h < 12 else "PM"26 h12 = h % 12 or 1227 return f"{h12}:{m:02d} {ampm}"28 29 30def duration_label(v) -> str:31 return f"{int(round(v))}h"32 33 34def axis_ticks(series: pd.Series, is_duration=False):35 s = series.dropna().astype(float)36 if s.empty:37 return [], []38 lo = int(np.ceil(s.min()))39 hi = int(np.floor(s.max()))40 vals = list(range(lo, hi + 1))41 texts = [duration_label(v) if is_duration else f"{v % 24:02d}:00" for v in vals]42 return vals, texts43 44 45_df_foods = None46_df_windows = None47 48 49def get_foods_df():50 global _df_foods51 if _df_foods is None:52 df = pd.read_parquet(FOODS_PATH)53 df["_search"] = df["item"].astype(str).str.lower()54 for b in ["is_habitual", "is_top100"]:55 if b in df.columns and df[b].dtype != bool:56 df[b] = df[b].astype(int).astype(bool)57 missing = [c for c in HOUR_COLS if c not in df.columns]58 if missing:59 raise ValueError(f"Foods file missing hour columns: {missing}")60 _df_foods = df61 return _df_foods62 63 64def get_windows_df():65 global _df_windows66 if _df_windows is None:67 df = pd.read_parquet(WINDOWS_PATH)68 for c in ["start95", "end95", "eating_interval"]:69 df[c] = pd.to_numeric(df[c], errors="coerce")70 _df_windows = df71 return _df_windows72 