update
This commit is contained in:
parent
5379004d1c
commit
e53878f665
4 changed files with 223 additions and 25 deletions
104
lactate-eval.py
Normal file
104
lactate-eval.py
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
import numpy as np
|
||||
from scipy import optimize
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
x0 = np.array(
|
||||
[
|
||||
102,
|
||||
128,
|
||||
143,
|
||||
161,
|
||||
176,
|
||||
191,
|
||||
207,
|
||||
222,
|
||||
237,
|
||||
255,
|
||||
270,
|
||||
]
|
||||
)
|
||||
y0 = np.array(
|
||||
[
|
||||
1.5,
|
||||
1.3,
|
||||
1.1,
|
||||
1.3,
|
||||
1.5,
|
||||
1.6,
|
||||
2.3,
|
||||
2.9,
|
||||
4.2,
|
||||
5.9,
|
||||
7.7,
|
||||
]
|
||||
)
|
||||
x1 = np.array(
|
||||
[
|
||||
100,
|
||||
120,
|
||||
140,
|
||||
160,
|
||||
180,
|
||||
200,
|
||||
220,
|
||||
240,
|
||||
260,
|
||||
]
|
||||
)
|
||||
y1 = np.array(
|
||||
[
|
||||
1.4,
|
||||
1,
|
||||
1.4,
|
||||
1.5,
|
||||
1.7,
|
||||
2.9,
|
||||
2.8,
|
||||
3,
|
||||
6.2,
|
||||
]
|
||||
)
|
||||
|
||||
def get_poly_fit(x, y, remove_first_n=1, remove_last_n=1, n_points=100):
|
||||
coeffs = np.polyfit(x, y, 3)
|
||||
poly = np.poly1d(coeffs)
|
||||
x_start = x[remove_first_n]
|
||||
x_end = x[-1-remove_last_n]
|
||||
x_poly = np.linspace(x_start, x_end, n_points)
|
||||
y_poly = poly(x_poly)
|
||||
return x_poly, y_poly
|
||||
|
||||
def get_log_log_threshold(x, y):
|
||||
x_log = np.log(x)
|
||||
y_log = np.log(y)
|
||||
p, e = optimize.curve_fit(piecewise_linear, x_log, y_log, p0=[np.mean(x_log), np.mean(y_log), 0.5, 4.0])
|
||||
return np.exp(p[0])
|
||||
|
||||
|
||||
def piecewise_linear(x, x0, y0, k1, k2):
|
||||
return np.piecewise(
|
||||
x, [x < x0], [lambda x: k1 * x + y0 - k1 * x0, lambda x: k2 * x + y0 - k2 * x0]
|
||||
)
|
||||
|
||||
def main():
|
||||
first_x, first_y = get_poly_fit(x0, y0)
|
||||
second_x, second_y = get_poly_fit(x1, y1)
|
||||
first_lt1 = get_log_log_threshold(first_x, first_y)
|
||||
second_lt1 = get_log_log_threshold(second_x, second_y)
|
||||
plt.plot(first_x, first_y, color='C0')
|
||||
plt.scatter(x0, y0, color='C0')
|
||||
plt.plot(second_x, second_y, color='C1')
|
||||
plt.scatter(x1, y1, color='C1')
|
||||
plt.axvline(first_lt1, color='C0', linestyle='dashed')
|
||||
plt.axvline(second_lt1, color='C1', linestyle='dashed')
|
||||
plt.grid(True, which='major')
|
||||
major_ticks = np.arange(0, 8, 1)
|
||||
minor_ticks = np.arange(0, 8, 0.1)
|
||||
plt.yticks(major_ticks)
|
||||
plt.yticks(minor_ticks, minor=True)
|
||||
plt.show()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
||||
|
|
@ -1,31 +1,86 @@
|
|||
import numpy as np
|
||||
from scipy import optimize
|
||||
|
||||
metrics = GC.activityMetrics(compare=True)
|
||||
n_activities = len(metrics)
|
||||
|
||||
GC.setChart(title='Lactate-Ramp',
|
||||
type=GC.CHART_LINE,
|
||||
animate=False,
|
||||
legpos=GC_ALIGN_TOP,
|
||||
stack=False)
|
||||
|
||||
def piecewise_linear(x, x0, y0, k1, k2):
|
||||
def fun0(x):
|
||||
k1 * x + y0 - k1 * x0
|
||||
|
||||
def fun1(x):
|
||||
k2 * x + y0 - k2 * x0
|
||||
|
||||
return np.piecewise(x, [x < x0], [fun0, fun1])
|
||||
|
||||
|
||||
GC.setChart(
|
||||
title="Lactate-Ramp",
|
||||
type=GC.CHART_LINE,
|
||||
animate=False,
|
||||
legpos=GC_ALIGN_TOP,
|
||||
stack=False,
|
||||
)
|
||||
|
||||
for i, metric in enumerate(metrics):
|
||||
date = metric[0]['date']
|
||||
date = metric[0]["date"]
|
||||
color = metric[1]
|
||||
print(color)
|
||||
x = list(GC.xdataSeries('Lactate-Ramp', 'Power', compareindex=i))
|
||||
y = list(GC.xdataSeries('Lactate-Ramp', 'Lactate', compareindex=i))
|
||||
x = list(GC.xdataSeries("Lactate-Ramp", "Power", compareindex=i))
|
||||
y = list(GC.xdataSeries("Lactate-Ramp", "Lactate", compareindex=i))
|
||||
if not (x and y):
|
||||
continue
|
||||
GC.addCurve(name=str(date),
|
||||
x=x,
|
||||
y=y,
|
||||
xaxis='Power',
|
||||
yaxis='Lactate',
|
||||
color=color,
|
||||
line=GC_LINE_SOLID,
|
||||
symbol=GC_SYMBOL_CIRCLE,
|
||||
size=3,
|
||||
opacity=100,
|
||||
opengl=False)
|
||||
GC.addCurve(
|
||||
name=str(date),
|
||||
x=x,
|
||||
y=y,
|
||||
xaxis="Power",
|
||||
yaxis="Lactate",
|
||||
color=color,
|
||||
line=GC_LINE_SOLID,
|
||||
symbol=GC_SYMBOL_CIRCLE,
|
||||
size=3,
|
||||
opacity=100,
|
||||
opengl=False,
|
||||
)
|
||||
coeffs = np.polyfit(x, y, 3)
|
||||
poly = np.poly1d(coeffs)
|
||||
x_poly = np.linspace(x[0], x[-1], 51)
|
||||
y_poly = poly(x_poly)
|
||||
GC.addCurve(
|
||||
name="Fit",
|
||||
x=x_poly,
|
||||
y=y_poly,
|
||||
xaxis="Power",
|
||||
yaxis="Lactate",
|
||||
color=color,
|
||||
line=GC_LINE_DASH,
|
||||
symbol=GC_SYMBOL_NONE,
|
||||
size=3,
|
||||
opacity=100,
|
||||
opengl=False,
|
||||
)
|
||||
x_poly = np.linspace(x[0], x[-2], 51)
|
||||
x_poly = np.array(x)
|
||||
y_poly = poly(x_poly)
|
||||
p, e = optimize.curve_fit(piecewise_linear, np.log(x_poly), np.log(y_poly), p0=[np.mean(x_poly), np.mean(y_poly), 0, 0])
|
||||
# p, e = optimize.curve_fit(piecewise_linear, x_poly, y_poly)
|
||||
print(p)
|
||||
GC.addCurve(
|
||||
name="log-log",
|
||||
x=x_poly,
|
||||
y=piecewise_linear(x_poly, *p),
|
||||
xaxis="Power",
|
||||
yaxis="Lactate",
|
||||
line=GC_LINE_DASH,
|
||||
symbol=GC_SYMBOL_NONE,
|
||||
size=1,
|
||||
opacity=100,
|
||||
opengl=False,
|
||||
)
|
||||
print(piecewise_linear(x_poly, *p))
|
||||
|
||||
GC.setAxis('Power', min=90, max=350, type=GC.AXIS_CONTINUOUS)
|
||||
GC.setAxis('Lactate', min=0.0, max=10.0, type=GC.AXIS_CONTINUOUS)
|
||||
|
||||
GC.setAxis("Power", min=90, max=350, type=GC.AXIS_CONTINUOUS)
|
||||
GC.setAxis("Lactate", min=0.0, max=10.0, type=GC.AXIS_CONTINUOUS)
|
||||
|
|
|
|||
|
|
@ -1,2 +1,5 @@
|
|||
plotly
|
||||
pandas
|
||||
scipy
|
||||
matplotlib
|
||||
pwlf
|
||||
|
|
|
|||
|
|
@ -4,18 +4,25 @@ import numpy as np
|
|||
WEIGHT_RANGE = [75, 85]
|
||||
|
||||
|
||||
def to_date(date):
|
||||
return (date - pd.to_datetime("1900-01-01").date()).days
|
||||
|
||||
|
||||
def get_weight_measures():
|
||||
# query non-zero
|
||||
data = pd.DataFrame(GC.seasonMeasures(group="Body")).query("WEIGHTKG != 0.0")[
|
||||
["date", "WEIGHTKG"]
|
||||
]
|
||||
data.reset_index(inplace=True)
|
||||
print(data)
|
||||
weight = data["WEIGHTKG"].to_numpy().flatten()
|
||||
weight_shifted = data["WEIGHTKG"].shift(periods=1)
|
||||
weight_shifted.loc[0] = 0.0
|
||||
weight_shifted = weight_shifted.to_numpy().flatten()
|
||||
weight_shifted = data["WEIGHTKG"].shift(periods=1).to_numpy().flatten()
|
||||
weight_shifted[0] = 0.0
|
||||
change = weight - weight_shifted
|
||||
indices = np.argwhere(change != 0.0).flatten()
|
||||
weight = weight[indices]
|
||||
print(data["date"])
|
||||
print(indices)
|
||||
date = (
|
||||
data["date"].loc[indices] - pd.to_datetime("1900-01-01").date()
|
||||
).dt.days.to_numpy()
|
||||
|
|
@ -25,7 +32,26 @@ def get_weight_measures():
|
|||
)
|
||||
|
||||
|
||||
def trendline(weight_data, start, end):
|
||||
weight = weight_data["WEIGHTKG"]
|
||||
date = weight_data["date"]
|
||||
y = weight.to_numpy()
|
||||
x = date.to_numpy()
|
||||
coeffs = np.polyfit(x[1:], y[1:], 1)
|
||||
poly = np.poly1d(coeffs)
|
||||
trend = poly([start, end])
|
||||
trend_x = np.array([start, end])
|
||||
return pd.DataFrame(
|
||||
np.hstack([trend_x.reshape([-1, 1]), trend.reshape([-1, 1])]),
|
||||
columns=["date", "trend"],
|
||||
), (trend[0], (trend[-1] - trend[0]) / (trend_x[-1] - trend_x[0]))
|
||||
|
||||
|
||||
season = GC.season()
|
||||
t_min = to_date(season["start"][0])
|
||||
t_max = to_date(season["end"][0])
|
||||
weight_data = get_weight_measures()
|
||||
trend_data, trend_coeffs = trendline(weight_data, t_min, t_max)
|
||||
GC.setChart(
|
||||
type=GC.CHART_LINE,
|
||||
orientation=GC_VERTICAL,
|
||||
|
|
@ -44,7 +70,16 @@ settings = {
|
|||
"opengl": False,
|
||||
}
|
||||
GC.addCurve(name="Weight", x=weight_data["date"], y=weight_data["WEIGHTKG"], **settings)
|
||||
GC.setAxis("Date", type=GC.AXIS_DATE)
|
||||
settings["symbol"] = GC_SYMBOL_NONE
|
||||
settings["line"] = GC_LINE_SOLID
|
||||
settings["color"] = "yellow"
|
||||
GC.addCurve(
|
||||
name=f"Trend: {trend_coeffs[0]:.2f} {trend_coeffs[1]*7:+.2f}/week",
|
||||
x=trend_data["date"],
|
||||
y=trend_data["trend"],
|
||||
**settings,
|
||||
)
|
||||
GC.setAxis("Date", type=GC.AXIS_DATE, min=t_min, max=t_max)
|
||||
GC.setAxis(
|
||||
"Weight",
|
||||
type=GC.AXIS_CONTINUOUS,
|
||||
|
|
@ -52,3 +87,4 @@ GC.setAxis(
|
|||
max=WEIGHT_RANGE[1],
|
||||
color="red",
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue