-
-
Save kmcallister/19c9898fea0d76156fa2f1925ace2164 to your computer and use it in GitHub Desktop.
Weight tracking scripts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
#set -e | |
./ewma.py < log > smoothed | |
echo | |
./progress.py "$@" < smoothed | |
echo | |
gnuplot < weight-graph.gpl | |
#./maintain.py < log | |
#echo | |
./rate.py < smoothed > rate | |
gnuplot < rate-graph.gpl | |
cp log backup/$(tail -n 1 log | awk '{print $1}') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import sys | |
import argparse | |
import time | |
import datetime | |
argparser = argparse.ArgumentParser() | |
argparser.add_argument('--verbose', '-v', action='store_true') | |
argparser.add_argument('--alpha', '-a', type=float, default=0.1) | |
args = argparser.parse_args() | |
if args.alpha < 0.0 or args.alpha > 1.0: | |
raise ValueError, "you suck" | |
ewma = 0.0 | |
def update(weight): | |
global ewma | |
ewma = args.alpha*weight + (1.0 - args.alpha)*ewma | |
last_ordinal = None | |
last_weight = None | |
for ln in sys.stdin: | |
date, weight = ln.split() | |
date = datetime.datetime.strptime(date, '%Y-%m-%d') | |
weight = float(weight) | |
ordinal = date.toordinal() | |
if args.verbose: | |
print (date.toordinal(), weight) | |
if last_ordinal is None: | |
last_ordinal = ordinal | |
last_weight = weight | |
ewma = weight | |
else: | |
last_ordinal += 1 | |
while last_ordinal < ordinal: | |
if args.verbose: | |
print 'Missing day, using', last_weight | |
update(last_weight) | |
last_ordinal += 1 | |
if args.verbose: | |
print 'Update with', weight | |
update(weight) | |
last_weight = weight | |
print date.strftime('%Y-%m-%d'), ewma |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import datetime | |
import sys | |
import math | |
import argparse | |
import numpy | |
from scipy import stats | |
goal = 234 | |
window = 30 | |
points = [] | |
confidence = 0.05 | |
for ln in sys.stdin: | |
date, weight = ln.split() | |
date = datetime.datetime.strptime(date, '%Y-%m-%d') | |
weight = float(weight) | |
points.append((date, weight)) | |
points = points[-window:] | |
weights = [p[1] for p in points] | |
minw, maxw, avgw = (min(weights), max(weights), numpy.average(weights)) | |
t_stat, p_value = stats.ttest_1samp(weights, goal) | |
print 'Target: %6.2f lbs' % (goal,) | |
print 'Range: %6.2f lbs' % (maxw-minw,) | |
print 'Std deviation: %6.2f lbs' % (numpy.std(weights),) | |
print 'Min/avg/max: %6.2f / %6.2f / %6.2f' % (minw, avgw, maxw) | |
print 'Deltas: %6.2f / %6.2f / %6.2f' % (minw-goal, avgw-goal, maxw-goal) | |
print 'Verdict: ', 'Maintaining!' if p_value > confidence else 'Not maintaining', '(p = %.2f)' % (p_value,) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import datetime | |
import sys | |
import math | |
import argparse | |
from scipy import stats | |
argparser = argparse.ArgumentParser() | |
argparser.add_argument('--reddit', '-r', action='store_true') | |
args = argparser.parse_args() | |
parse_date = lambda s: datetime.datetime.strptime(s, "%Y-%m-%d") | |
goal = 225 | |
goal_date = parse_date("2019-06-01") | |
window = 30 | |
height = 1.91 # meters | |
kg_per_lb = 0.453592 | |
points = [] | |
def parse(ln): | |
date, weight = ln.split() | |
date = datetime.datetime.strptime(date, '%Y-%m-%d') | |
weight = float(weight) | |
return (date, weight) | |
lines = list(sys.stdin) | |
start_date, start = parse(lines[0]) | |
points = map(parse, lines) | |
num_points = len(points) | |
num_decrease = sum(1 for p, q in zip(points, points[1:]) if p[1] > q[1]) | |
points = points[-window:] | |
first = points[0] | |
last = points[-1] | |
reg_x = [p[0].toordinal() for p in points] | |
reg_y = [p[1] for p in points] | |
slope, intercept, r_value, p_value, stderr = stats.linregress(reg_x, reg_y) | |
#rate = (first[1] - last[1]) / (last[0] - first[0]).days | |
rate = -slope | |
if rate <= 0.0: | |
print "Sorry, you're getting fatter at %.2f lb/wk (r^2 = %.2f)" % (-7.0*rate, r_value**2.0) | |
sys.exit(1) | |
def output_stat(label, value): | |
if args.reddit: | |
print '**' + label + '**|' + value.lstrip() | |
else: | |
print (label + ':').ljust(17) + value | |
done = start - last[1] | |
days_done = (last[0] - start_date).days | |
remainder = last[1] - goal | |
remaining_time = datetime.timedelta(days = remainder / rate) | |
finish_date = last[0] + remaining_time | |
margin = (goal_date - finish_date).days + 1 | |
required_rate = remainder / (goal_date - last[0]).days | |
excess_rate = rate - required_rate | |
def project(date): | |
projection = last[1] - (rate * (parse_date(date) - last[0]).days) | |
print 'Weight on %s: %6.2f lbs = %6.2f lbs lost' % (date, projection, start - projection) | |
if args.reddit: | |
print 'Stat|Value' | |
print ':-|:-' | |
output_stat('Current weight', '%6.2f lbs' % (last[1],)) | |
#output_stat('BMI', '%6.2f' % ((kg_per_lb * last[1]) / (height ** 2.0),)) | |
output_stat('Lost so far', '%6.2f lbs = %5.2f%% of starting weight' % (done, 100.0 * done / start)) | |
output_stat('Remaining', '%6.2f lbs = %5.2f%% of current weight' % (remainder, 100.0 * remainder / last[1])) | |
output_stat('Progress', '%6.2f %%' % (done / (start - goal) * 100.0,)) | |
output_stat('Required rate', '%6.2f lbs / wk' % (7.0 * required_rate,)) | |
output_stat('Actual rate', '%6.2f lbs / wk = %.2f%% per week (r^2 = %4.2f)' % (7.0*rate, 100*7.0*rate / last[1], r_value**2.0)) | |
#output_stat('Excess rate', '%6.2f lbs / wk' % (7.0*excess_rate,)) | |
output_stat('Deficit', ' %4d kcal / day' % (rate*3500,)) | |
#output_stat('Excess deficit', ' %4d kcal/day' % (excess_rate*3500,)) | |
output_stat('All-time rate', '%6.2f lbs / wk' % (7.0 * done / days_done,)) | |
output_stat('Average drops', '%6.2f %% of the time (%d out of %d points)' % (100.0 * num_decrease / float(num_points), num_decrease, num_points)) | |
print 'Goal will be reached on %s' % (finish_date.strftime('%Y-%m-%d'),), | |
if margin > 0: | |
print '(%d days early)' % (margin,) | |
else: | |
print '(%d days late)' % (-margin,) | |
if args.reddit: | |
print days_done, 'days done, only', remaining_time.days, 'left to go! Keep it up, you\'re doing great!' | |
project('2019-06-01') | |
with open('regression_line', 'w') as f: | |
line_out = lambda pt: f.write(pt[0].strftime('%Y-%m-%d') + ' ' + str(intercept + slope*pt[0].toordinal()) + '\n') | |
line_out(points[0]) | |
line_out(points[-1]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
set title "Weight loss rate" | |
set ylabel "Pounds per week" | |
#set y2label "r^2" | |
set term png size 1400,900 | |
set output "rate-graph.png" | |
set timefmt "%Y-%m-%d" | |
set xdata time | |
set format x "%b\n%d" | |
#set xrange ["2018-02-18":] | |
plot "rate" using 1:2 with lines lw 3 title "Rate", \ | |
#"rate" using 1:3 with lines lw 1 title "r^2" axes x1y2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import datetime | |
import sys | |
import math | |
import argparse | |
from scipy import stats | |
window = 14 | |
points = [] | |
for ln in sys.stdin: | |
date, weight = ln.split() | |
date = datetime.datetime.strptime(date, '%Y-%m-%d') | |
weight = float(weight) | |
points.append((date, weight)) | |
points = points[-window:] | |
if len(points) < window: | |
continue | |
reg_x = [p[0].toordinal() for p in points] | |
reg_y = [p[1] for p in points] | |
slope, intercept, r_value, p_value, stderr = stats.linregress(reg_x, reg_y) | |
print date.strftime("%Y-%m-%d"), -7.0*slope, r_value**2.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
set title "Weight loss progress" | |
set ylabel "Weight (lbs)" | |
set term png size 1400,900 | |
set output "weight-graph.png" | |
set timefmt "%Y-%m-%d" | |
set xdata time | |
set format x "%b\n%d" | |
#set xrange ["2018-08-01":] | |
#set yrange [240:290] | |
plot "log" using 1:2 with linespoints pointtype 6 title "Daily weight", \ | |
"smoothed" using 1:2 with lines lw 3 title "Moving average", \ | |
"regression_line" using 1:2 title "Trend line" with lines lw 2 lt rgb "#c01f1f", \ | |
# "raw_line" using 1:2 title "Raw trend line" with lines lw 2 lt rgb "blue" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment