From 3059fd85cbce0fdda8d5002d37c34ec3d9f1d92e Mon Sep 17 00:00:00 2001 From: Dima Gerasimov Date: Sat, 17 Aug 2019 09:35:04 +0100 Subject: [PATCH] use blood test data --- body/blood.py | 91 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 12 deletions(-) diff --git a/body/blood.py b/body/blood.py index 4b51797..9919030 100755 --- a/body/blood.py +++ b/body/blood.py @@ -1,25 +1,55 @@ #!/usr/bin/env python3 from datetime import datetime from typing import Iterable, NamedTuple, Optional +from itertools import chain import porg from kython import listify from kython.org import parse_org_date +from kython.kerror import Res, echain -from ..paths import LOGS +from ..paths import LOGS, MY + +import pandas as pd # type: ignore +blood_tests_log = MY / 'blood.org' blood_log = LOGS / 'blood.org' class Entry(NamedTuple): dt: datetime - ket: Optional[float] - glu: Optional[float] - extra: str + + ket: Optional[float]=None + glu: Optional[float]=None + + vitd: Optional[float]=None + b12: Optional[float]=None + + hdl: Optional[float]=None + ldl: Optional[float]=None + trig: Optional[float]=None + + extra: Optional[str]=None -def iter_data() -> Iterable[Entry]: - o = porg.Org.from_file(blood_log) +Result = Res[Entry] + +class ParseError(Exception): + pass + + +def try_float(s: str) -> Optional[float]: + l = s.split() + if len(l) == 0: + return None + x = l[0].strip() + if len(x) == 0: + return None + return float(x) + + +def iter_gluc_keto_data() -> Iterable[Result]: + o = porg.Org.from_file(str(blood_log)) tbl = o.xpath('//table') for l in tbl.lines: kets = l['ket'].strip() @@ -27,8 +57,8 @@ def iter_data() -> Iterable[Entry]: extra = l['notes'] dt = parse_org_date(l['datetime']) assert isinstance(dt, datetime) - ket = None if len(kets) == 0 else float(kets) - glu = None if len(glus) == 0 else float(glus) + ket = try_float(kets) + glu = try_float(glus) yield Entry( dt=dt, ket=ket, @@ -36,14 +66,51 @@ def iter_data() -> Iterable[Entry]: extra=extra, ) + +def iter_tests_data() -> Iterable[Result]: + o = porg.Org.from_file(str(blood_tests_log)) + tbl = o.xpath('//table') + for d in tbl.lines: + try: + dt = parse_org_date(d['datetime']) + assert isinstance(dt, datetime) + # TODO rest + + F = lambda n: try_float(d[n]) + yield Entry( + dt=dt, + + vitd=F('VD nm/L'), + b12 =F('B12 pm/L'), + + hdl =F('HDL mm/L'), + ldl =F('LDL mm/L'), + trig=F('Trig mm/L'), + + extra=d['misc'], + ) + except Exception as e: + print(e) + yield echain(ParseError(str(d)), e) + + def data(): - datas = list(iter_data()) - return list(sorted(datas, key=lambda d: d.dt)) + datas = list(chain(iter_gluc_keto_data(), iter_tests_data())) + return list(sorted(datas, key=lambda d: getattr(d, 'dt', datetime.min))) +@listify(wrapper=pd.DataFrame) def dataframe(): - import pandas as pd - return pd.DataFrame(map(lambda e: e._asdict(), data())) + for d in data(): + if isinstance(d, Exception): + yield {'error': str(d)} + else: + yield d._asdict() + + +def test(): + print(dataframe()) + assert len(dataframe()) > 10 def main():