get sleep for each night
This commit is contained in:
parent
5658327883
commit
e11cef6f91
2 changed files with 48 additions and 14 deletions
|
@ -2,12 +2,17 @@ from kython import json_load
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from os.path import join
|
from os.path import join
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
import logging
|
||||||
from datetime import timedelta, datetime
|
from datetime import timedelta, datetime, date
|
||||||
from typing import List, Dict, Iterator, NamedTuple
|
from typing import List, Dict, Iterator, NamedTuple
|
||||||
|
|
||||||
|
from collections import OrderedDict as odict
|
||||||
|
|
||||||
fromts = datetime.fromtimestamp
|
fromts = datetime.fromtimestamp
|
||||||
|
|
||||||
|
def get_logger():
|
||||||
|
return logging.getLogger('emfit-provider')
|
||||||
|
|
||||||
def hhmm(minutes):
|
def hhmm(minutes):
|
||||||
return '{:02d}:{:02d}'.format(*divmod(minutes, 60))
|
return '{:02d}:{:02d}'.format(*divmod(minutes, 60))
|
||||||
|
|
||||||
|
@ -16,14 +21,12 @@ PATH = "/L/backups/emfit/"
|
||||||
EXCLUDED = [
|
EXCLUDED = [
|
||||||
'***REMOVED***', # pretty weird, detected sleep and HR (!) during the day when I was at work
|
'***REMOVED***', # pretty weird, detected sleep and HR (!) during the day when I was at work
|
||||||
'***REMOVED***',
|
'***REMOVED***',
|
||||||
|
|
||||||
|
'***REMOVED***', # some weird sleep during the day?
|
||||||
]
|
]
|
||||||
|
|
||||||
AWAKE = 4
|
AWAKE = 4
|
||||||
|
|
||||||
class Point(NamedTuple):
|
|
||||||
ts: int
|
|
||||||
pulse: float
|
|
||||||
|
|
||||||
class Emfit:
|
class Emfit:
|
||||||
def __init__(self, sid: str, jj):
|
def __init__(self, sid: str, jj):
|
||||||
self.sid = sid
|
self.sid = sid
|
||||||
|
@ -37,6 +40,7 @@ class Emfit:
|
||||||
def hrv_evening(self):
|
def hrv_evening(self):
|
||||||
return self.jj['hrv_rmssd_evening']
|
return self.jj['hrv_rmssd_evening']
|
||||||
|
|
||||||
|
# ok, I guess that's reasonable way of defining sleep date
|
||||||
@property
|
@property
|
||||||
def date(self):
|
def date(self):
|
||||||
return self.end.date()
|
return self.end.date()
|
||||||
|
@ -59,6 +63,15 @@ class Emfit:
|
||||||
def epochs(self):
|
def epochs(self):
|
||||||
return self.jj['sleep_epoch_datapoints']
|
return self.jj['sleep_epoch_datapoints']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def epoch_series(self):
|
||||||
|
tss = []
|
||||||
|
eps = []
|
||||||
|
for [ts, e] in self.epochs:
|
||||||
|
tss.append(ts)
|
||||||
|
eps.append(e)
|
||||||
|
return tss, eps
|
||||||
|
|
||||||
@property # type: ignore
|
@property # type: ignore
|
||||||
@lru_cache()
|
@lru_cache()
|
||||||
def sleep_start(self) -> datetime:
|
def sleep_start(self) -> datetime:
|
||||||
|
@ -98,6 +111,10 @@ class Emfit:
|
||||||
def hrv_hf(self):
|
def hrv_hf(self):
|
||||||
return self.jj['hrv_hf']
|
return self.jj['hrv_hf']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def recovery(self):
|
||||||
|
return self.hrv_morning - self.hrv_evening
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def summary(self):
|
def summary(self):
|
||||||
return f"""in bed for {hhmm(self.time_in_bed)}
|
return f"""in bed for {hhmm(self.time_in_bed)}
|
||||||
|
@ -105,7 +122,7 @@ emfit time: {hhmm(self.sleep_minutes_emfit)}; covered: {self.sleep_hr_coverage:.
|
||||||
hrv morning: {self.hrv_morning:.0f}
|
hrv morning: {self.hrv_morning:.0f}
|
||||||
hrv evening: {self.hrv_evening:.0f}
|
hrv evening: {self.hrv_evening:.0f}
|
||||||
avg hr: {self.measured_hr_avg:.0f}
|
avg hr: {self.measured_hr_avg:.0f}
|
||||||
recovery: {self.hrv_morning - self.hrv_evening:3.0f}
|
recovery: {self.recovery:3.0f}
|
||||||
{self.hrv_lf}/{self.hrv_hf}"""
|
{self.hrv_lf}/{self.hrv_hf}"""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -178,18 +195,22 @@ recovery: {self.hrv_morning - self.hrv_evening:3.0f}
|
||||||
# act in csv.. so it must be activity? wonder how is it measured.
|
# act in csv.. so it must be activity? wonder how is it measured.
|
||||||
# but I guess makes sense. yeah, "measured_activity_avg": 595, about that
|
# but I guess makes sense. yeah, "measured_activity_avg": 595, about that
|
||||||
# makes even more sense given tossturn datapoints only have timestamp
|
# makes even more sense given tossturn datapoints only have timestamp
|
||||||
yield Point(ts=ts, pulse=pulse)
|
yield ts, pulse
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def sleep_hr(self):
|
def sleep_hr(self):
|
||||||
tss = []
|
tss = []
|
||||||
res = []
|
res = []
|
||||||
for p in self.iter_points():
|
for ts, pulse in self.iter_points():
|
||||||
if self.sleep_start < fromts(p.ts) < self.sleep_end:
|
if self.sleep_start < fromts(ts) < self.sleep_end:
|
||||||
tss.append(p.ts)
|
tss.append(ts)
|
||||||
res.append(p.pulse)
|
res.append(pulse)
|
||||||
return tss, res
|
return tss, res
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sleep_hr_series(self):
|
||||||
|
return self.sleep_hr
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hrv(self):
|
def hrv(self):
|
||||||
tss = []
|
tss = []
|
||||||
|
@ -234,6 +255,18 @@ def iter_datas() -> Iterator[Emfit]:
|
||||||
|
|
||||||
def get_datas() -> List[Emfit]:
|
def get_datas() -> List[Emfit]:
|
||||||
return list(sorted(list(iter_datas()), key=lambda e: e.start))
|
return list(sorted(list(iter_datas()), key=lambda e: e.start))
|
||||||
|
|
||||||
|
|
||||||
# TODO move away old entries if there is a diff??
|
# TODO move away old entries if there is a diff??
|
||||||
|
|
||||||
|
from kython import group_by_key
|
||||||
|
def by_night() -> Dict[date, Emfit]:
|
||||||
|
logger = get_logger()
|
||||||
|
res: Dict[date, Emfit] = odict()
|
||||||
|
# TODO shit. I need some sort of interrupted sleep detection?
|
||||||
|
for dd, sleeps in group_by_key(get_datas(), key=lambda s: s.date).items():
|
||||||
|
if len(sleeps) > 1:
|
||||||
|
logger.warning("multiple sleeps per night, not handled yet: %s", sleeps)
|
||||||
|
continue
|
||||||
|
[s] = sleeps
|
||||||
|
res[s.date] = s
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
1
plot.py
1
plot.py
|
@ -91,6 +91,7 @@ def plot_recovery_vs_hr_percentage():
|
||||||
|
|
||||||
|
|
||||||
# TODO ah. it's only last segment?
|
# TODO ah. it's only last segment?
|
||||||
|
# ok, handled in dashboard now
|
||||||
def plot_hr():
|
def plot_hr():
|
||||||
jj = get_datas()[-1]
|
jj = get_datas()[-1]
|
||||||
tss, uu = jj.sleep_hr
|
tss, uu = jj.sleep_hr
|
||||||
|
|
Loading…
Add table
Reference in a new issue