proper pandas frame
This commit is contained in:
parent
b471a337aa
commit
9c94431791
1 changed files with 60 additions and 5 deletions
|
@ -3,6 +3,9 @@ from typing import Dict, Any, List
|
||||||
import json
|
import json
|
||||||
from datetime import datetime, date, time
|
from datetime import datetime, date, time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from kython.klogging import setup_logzero
|
||||||
|
|
||||||
BDIR = Path('/L/backups/jawbone')
|
BDIR = Path('/L/backups/jawbone')
|
||||||
PHASES_FILE = BDIR / 'phases.json'
|
PHASES_FILE = BDIR / 'phases.json'
|
||||||
|
@ -10,14 +13,16 @@ SLEEPS_FILE = BDIR / 'sleeps.json'
|
||||||
GRAPHS_DIR = BDIR / 'graphs'
|
GRAPHS_DIR = BDIR / 'graphs'
|
||||||
|
|
||||||
|
|
||||||
|
def get_logger():
|
||||||
|
return logging.getLogger('jawbone-provider')
|
||||||
|
|
||||||
|
|
||||||
fromtimestamp = datetime.fromtimestamp # TODO careful
|
fromtimestamp = datetime.fromtimestamp # TODO careful
|
||||||
|
|
||||||
XID = str # TODO how to shared with backup thing?
|
XID = str # TODO how to shared with backup thing?
|
||||||
|
|
||||||
|
|
||||||
Phases = Dict[XID, Any]
|
Phases = Dict[XID, Any]
|
||||||
|
|
||||||
|
|
||||||
phases: Phases = json.loads(PHASES_FILE.read_text())
|
phases: Phases = json.loads(PHASES_FILE.read_text())
|
||||||
|
|
||||||
# TODO namedtuple, cproperty?
|
# TODO namedtuple, cproperty?
|
||||||
|
@ -42,9 +47,12 @@ class SleepEntry:
|
||||||
def xid(self) -> XID:
|
def xid(self) -> XID:
|
||||||
return self.js['xid']
|
return self.js['xid']
|
||||||
|
|
||||||
|
@property
|
||||||
def _details(self):
|
def _details(self):
|
||||||
return self.js['details']
|
return self.js['details']
|
||||||
|
|
||||||
|
# TODO figure out timezones..
|
||||||
|
# not sure how.. I guess by the american ones
|
||||||
@property
|
@property
|
||||||
def created(self) -> datetime:
|
def created(self) -> datetime:
|
||||||
return fromtimestamp(self.js['time_created'])
|
return fromtimestamp(self.js['time_created'])
|
||||||
|
@ -55,14 +63,28 @@ class SleepEntry:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def asleep(self) -> datetime:
|
def asleep(self) -> datetime:
|
||||||
return fromtimestamp(self._details()['asleep_time'])
|
return fromtimestamp(self._details['asleep_time'])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sleep_start(self) -> datetime:
|
||||||
|
return self.asleep # TODO careful, maybe use same logic as emfit
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bed_time(self) -> int:
|
||||||
|
return int((self.sleep_end - self.sleep_start).total_seconds()) // 60
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sleep_end(self) -> datetime:
|
||||||
|
return fromtimestamp(self._details['awake_time'])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def graph(self) -> Path:
|
def graph(self) -> Path:
|
||||||
return GRAPHS_DIR / (self.xid + ".png")
|
return GRAPHS_DIR / (self.xid + ".png")
|
||||||
|
|
||||||
|
# TODO might be useful to cache these??
|
||||||
@property
|
@property
|
||||||
def phases(self) -> List[datetime]:
|
def phases(self) -> List[datetime]:
|
||||||
|
# TODO make sure they are consistent with emfit?
|
||||||
return [fromtimestamp(i['time']) for i in phases[self.xid]]
|
return [fromtimestamp(i['time']) for i in phases[self.xid]]
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
|
@ -161,11 +183,21 @@ def plot_one(sleep: SleepEntry, fig: Figure, axes: Axes, xlims=None, showtext=Tr
|
||||||
axes.text(xlims[1] - timedelta(hours=1.5), 20, str(sleep),)
|
axes.text(xlims[1] - timedelta(hours=1.5), 20, str(sleep),)
|
||||||
# plt.text(sleep.asleep(), 0, hhmm(sleep.asleep()))
|
# plt.text(sleep.asleep(), 0, hhmm(sleep.asleep()))
|
||||||
|
|
||||||
from kython import make_dict
|
from kython import make_dict, group_by_key
|
||||||
|
|
||||||
def sleeps_by_date() -> Dict[date, SleepEntry]:
|
def sleeps_by_date() -> Dict[date, SleepEntry]:
|
||||||
|
logger = get_logger()
|
||||||
|
|
||||||
sleeps = load_sleeps()
|
sleeps = load_sleeps()
|
||||||
sleeps = [s for s in sleeps if s.graph.exists()] # TODO careful..
|
sleeps = [s for s in sleeps if s.graph.exists()] # TODO careful..
|
||||||
return make_dict(sleeps, key=SleepEntry.date_)
|
res = {}
|
||||||
|
for dd, group in group_by_key(sleeps, key=lambda s: s.date_).items():
|
||||||
|
if len(group) == 1:
|
||||||
|
res[dd] = group[0]
|
||||||
|
else:
|
||||||
|
# TODO short ones I can ignore I guess. but won't bother now
|
||||||
|
logger.error('multiple sleeps on %s: %s', dd, group)
|
||||||
|
return res
|
||||||
|
|
||||||
# sleeps_count = 35 # len(sleeps) # apparently MPL fails at 298 with outofmemory or something
|
# sleeps_count = 35 # len(sleeps) # apparently MPL fails at 298 with outofmemory or something
|
||||||
# start = 40
|
# start = 40
|
||||||
|
@ -225,3 +257,26 @@ def plot():
|
||||||
# plt.savefig('res.png', asp)
|
# plt.savefig('res.png', asp)
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
import pandas as pd # type: ignore
|
||||||
|
def get_dataframe():
|
||||||
|
sleeps = sleeps_by_date()
|
||||||
|
items = []
|
||||||
|
for dd, s in sleeps.items():
|
||||||
|
items.append({
|
||||||
|
'date' : dd, # TODO not sure... # TODO would also be great to sync column names...
|
||||||
|
'sleep_start': s.sleep_start,
|
||||||
|
'sleep_end' : s.sleep_end,
|
||||||
|
'bed_time' : s.bed_time,
|
||||||
|
})
|
||||||
|
# TODO tz is in sleeps json
|
||||||
|
res = pd.DataFrame(items)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
setup_logzero(get_logger())
|
||||||
|
print(get_dataframe())
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
Loading…
Add table
Reference in a new issue