体調管理
世の中、節電の為に偽サマータイムなんぞが実施されてて、その影響が報告されてた。朝起きるのが辛いとか、 子供の送り迎え予定が狂っちゃったとかがあるみたい。
一方、お父さんが早く帰ってくるので子供と遊べるようになり、すっかり企業戦士から家庭人に変身して しまった人も居るようだ。これをきっかけに、仕事第一から家庭第一へと比重が移って行くんでしょうかね?
昔、ドイツに駐留してた時、現地人相手にトレーニングをした事が有った。興が乗って定時を過ぎても ビシバシと鬼軍曹宜しくやってたんだけど、受講生の嫁さんが迎えに来たんで、また明日にして貰えないか と申し訳なさそうに申告された。きりが悪いんでもう少しだけやらせてって言ったら、嫁さん怖いなんて 言い出した。育児と料理の当番になってるとか。仕事より家庭なんですかね? それとも、単に嫁さんが 怖かっただけ?
翌日聞いたら、仕事と家庭とどっちが大切なのよと、戦争状態だったらしい。節電を機に、すっかり家庭人 になってしまうおとうさん。また、普通の状態に戻って、子供と嫁さんにそっぽを向かれないように、 注意めされよ。
Bluetooth
おいらの歯はBluetoothのごとく丈夫で通してきた。幼少の頃の虫歯の治療以来、50年は安定稼動してきた。 そんじょそこらの原発より丈夫だよ。
でも、去年から定期点検と保守を受ける事にし、今年もその時期が巡ってきた。歯槽膿漏防止のための 歯石取りメンテナンスだ。5月から通っているんだけど、まだ続いている。保険の適用が、一回の治療で 4本までと言う制限があるらしく、それが原因で延びているんだ。
それと、昔虫歯の治療で穴を埋めた金属が体に悪いらしく、それを入れ替える事を勧められた。ドリルで 古い金属をひっぺがし、穴が安定するまで待ってから、穴型を取り、あらかじめ作っておいた型をはめる と言うのが一工程になる。
ドリルで開けた穴を仮埋めとかやってると、一本の補修に3回も通院が必要。どこかの道路工事を連想 してしまうのは、私だけだろうか? そして、最後の仕上げは、美白らしい。これはもう、遠慮しようかな。 どうせ美白したって、タバコとコーヒーと赤ワインですぐに、染まってしまうんだから。
健康診断
こちらに引っ越してきて、初めての町でやってる健康診断を受けてきた。会場は、田園風景が広がる所に ぽつんと立っている集会場の大広間。
畳みに座っての健康診断は生まれて初めての経験で、新鮮でしたよ。採血も血圧測定も問診も、座卓を 前にしてですからね。さすが、メタボの診断で腹周りを測られた時は、立ったままでしたけど。
最後に、保健婦さんの総括がありました。電卓片手にBMIを計算してました。22ですって。そのかわり 血圧が高め。一度、医者の診断を受けてくださいって勧められた。
家に血圧計があるならば、事前に何回か測ってそのデータを持ってくといいですよーと入れ知恵された。 一日のうちでも測る時間によって変わるので、同じ条件で測ってくださいね、とか。
はいはい、そういう事は合点承知の助。幸い家には、在庫処分の時に2500円で買ったやつがあるんで、 朝起きた時と、寝る前に測る事にしよう。
ただし、この血圧計、安いだけあって測定値をUSBで取り出すとかの機能は付いていない。30回のデータを メモリーする機能しかないんだ。昔使っていた万歩計は、Webに登録して競う機能が付いていたのになあ。 四国のお遍路さんを模して、今日は、何番の札所まで進みましたなんて事を出来たんですけどね。
しゃーない、血圧記録をパソコンで管理するようにしよう。無いものは自分で作れですからね。
記録するぞ
すぐに思いつくのは、EXCELかな。今だと、OpenOffice系がいいんかな。CQ誌でも連載してるし。でも、そ んなのありきたりでつまんない。そうすると、次の候補は、統計処理ソフトのRかな。でも、これも 昔使ったからなあ。いわば既製品だから、面白くない。
ぼけ防止を兼ねて、スクラッチから書こう。前にやった、my/qsl/logに習うか。でも、おいらSQLは はっきり言って嫌いなんよ。
と言う事で、Pythonでやります。血圧の記録って事は、データの永続化が必要。まあ、データはログ だから、測定日をキーにして、最高血圧、最低血圧、脈拍を保持。これらの値は、CSVっぽくカンマ 区切りでいいか。
ここまで決めるとデータ構造は、Pythonの辞書、一般に言うとHashでいいな。この辞書を一発でファイルに 落としたり、呼び戻したり出来れば楽チンだ。GDBMとかNDBMでもいいんだろうけど、もしもの時のために 生データが見えた(編集出来る)方が良い。
ここで、シリアライズと言うかマーシャリングの登場です。シリアライズと言えば、 UTF-8もUCS-4のシリアライズなんですね。 そして、JSONは、Web好きな人ご用達。
Pythonには、マーシャリングがcoreの機能と して備わっている。core機能だとCで書かれてるんで、どんな風になってるか知るにはちと荷が重い。 調べたら、pickleとか言うモジュールで書かれたやつが提供されてた。(pickleって西洋漬物、どういうネーミングだ。そうか、Pythonの 外側じゃ役に立たないけど、Python上だと滋養に満ち溢れたって事か)どこでも使える、ポータブル版ですな。
どうでもいいけど、Schemeだと、シリアライズ用に、write手続きが用意されてる。writeを使って書き出した S式は、readによって呼び戻せる事が保障されてる。Rとかだと、終了する時に、今までの環境一式を 保存しちゃう機能がついてるな。SmallTalkだと、そんなのは裏でこっそりやってくれてるのかな。
データが際限もなく大きくなって行くのはいやなんで、 一年毎に、新しいファイルに記録してく事にします。一日に2回測ったとして、1年で730データぐらい だから、お手ごろサイズかな。
使い方
>>> Traceback (most recent call last): File "C:\homes\WORK\blood.py", line 113, in <module> if __name__ == '__main__': main() File "C:\homes\WORK\blood.py", line 94, in main load() File "C:\homes\WORK\blood.py", line 20, in load with open(logfile, 'rb') as pk: IOError: [Errno 2] No such file or directory: 'ketu2011.pkl' >>>
初回の起動時は、データファイルが無いのでエラーになります。まあ、1年に一度の事ですから許してね。 データファイル名は、スクリプトの中で指定してますので、年が改まったら、ファイル名を変更して おきます。
>>> save() Saved 0 datas!! >>> main() Loaded 0 datas!! 07>
取りあえず、save()して、殻(空)ファイルを作りました。ここでスクリプトを再起動してもいいし、main() を呼び出して、ミニ・インタープリタに入ってもかまいません。ミニ・インタープリタのプロンプトに 示される2桁の数字は、データ入力する時の月の挿入データとして使っています。
一度でもエラーを見るのは気分を害すると言うなら、スクリプト中で指定した(新しい年度の)ファイルに、
(dp0 .
こんなデータを、あらかじめ入れておきます。
まずはデータが無いと話にならないので、広告の裏にメモしたデータを、しこしこと入力して行きます。
07> 3.04 123 78 59 07> 12.21 119 82 63 07> 4.05 128 88 61 07> cat 0703.04 123 78 59 0704.05 128 88 61 0712.21 119 82 63 07> save Saved 3 datas!!
冒頭が数字で始まると、データ入力とみなされます。測定日.時 最高血圧 最低血圧 脈拍 と言う 順番で入れて行きます。catは、入力されたデータの確認です(オプションは後述)。そして、saveは、データの保存です。
ここまでで、データファイルは、次のようになってました。
(dp0 S'0703.04' p1 S'123,78,59' p2 sS'0712.21' p3 S'119,82,63' p4 sS'0704.05' p5 S'128,88,61' p6 s.
続いて入力して行きます。
07> mm 06 06> 28.04 133 87 65 06> 30.21 129 85 61 06> save Saved 5 datas!!
メモを見たら、6月のデータも有ったので、mm コマンドで月を6月にセットして入力しました。 同じ月なのにいちいち月を入力するのは、うざいので、なるべく省エネ(省キー入力)出来るように してます。
06> cat 4. 0630.21 129 85 61 0703.04 123 78 59 0704.05 128 88 61 0712.21 119 82 63 06> cat 06 0628.04 133 87 65 0630.21 129 85 61
cat(に限りませんが)には、2種類のオプションが有る。数字の後ろにドットを付けると、直近の 指定したデータ分を表示、もう一つは、測定月日.時間 による検索だ。(上記は、6月のデータ表示に 相当)
06> stat size: 5 min: 119.0 78.0 59.0 medean: 128.0 85.0 61.0 max: 133.0 88.0 65.0 mean: 126.4 84.0 61.8 std: 4.9 3.6 2.0 06> stat 07 size: 3 min: 119.0 78.0 59.0 medean: 123.0 82.0 61.0 max: 128.0 88.0 63.0 mean: 123.3 82.7 61.0 std: 3.7 4.1 1.6
データを入力してくだけでは、目的半分だ。自分の体がどうなってるかを、統計を使って分析してみる。 最小、中央値、最大値、平均、標準偏差が取りあえず、確認出来る。(グラフ表示は、オプションに なりますが、まだ開発されてません)
データを訂正したい場合は、次のようにする。
06> 30.21 139 85 61 0630.21: 129,85,61 Sure ? update or del, "yes" to allow yes
間違って、上書きしちゃうのを防ぐ為、確認を求めるようにした。特定データを削除する場合も 同様です。従って、この確認が表れない場合、新たなデータとして入力されちまった事になります。(月を またいだ、変更時に発生してまう事があるので、注意)
06> rm 0712.21 0712.21: 119,82,63 Sure ? update or del, "yes" to allow yes
削除の時は、フルで測定月日時 を指定する事。
核心部分
dat = {} # format {'mmdd.hh': 'hi,low,pls' ... } def load(): global dat with open(logfile, 'rb') as pk: dat = pickle.load(pk) print('Loaded {0} datas!!'.format(len(dat))) def main(): cmds = {'save': save, 'cat': cat, 'stat': stat, 'mm': mmc, 'rm': rm, } load() try: while True: al = raw_input((mm + '> ')).strip() if len(al) == 0: continue if al[0].isdigit(): logging(al) else: a = al.split() fn = a.pop(0) arg= '' if len(a) == 0 else ' '.join(a) if cmds.has_key(fn): run = cmds[fn] run(arg) else: print('??') except: save()
このスクリプトは成長途上にあるので、取り合えず核心部分のみをば。
datと言う辞書に、測定日をキーにして値が入っています。loadは、logfileに保持してたdatを呼び戻す 手続きです。この手続き中でdatをglobal宣言し、手続きの外側のdatにデータを保持させます。 (そんなに白眼をむいて怒らないでね。)
main()中では、一行入力して、冒頭が数字なら、ロギング関係、それ以外(の英字)は、命令とみなして います。命令は、最初if文を羅列してたんだけど、命令の追加毎に編集するのが面倒臭くなったので、 テーブルによるディスパッチ方式に変更しました。
これで新たに命令を追加しても、テーブルに追加するだけで事が足ります。
数字だったらデータをスタックに保存し、それ以外だったらコマンドとして、スタックからデータを取り出して 処理するようにすれば、Forthのインタープリターになっちまいますよ。たまには触ってみるかな。