Created
March 13, 2022 19:34
-
-
Save larsoner/53f1878cffd2ffe118ab6d8049eee2e9 to your computer and use it in GitHub Desktop.
Find best 20-minute segment since latest FTP test
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
import numpy as np | |
from datetime import datetime | |
from tqdm.auto import tqdm | |
from pytz import timezone | |
from peloton import PelotonWorkout | |
my_tz = timezone('US/Eastern') | |
print('Getting workout list...') | |
workouts = PelotonWorkout.list() | |
print('Finding latest FTP test...') | |
ftp = [workout for workout in workouts | |
if 'ftp' in workout.ride.title.lower().split() and | |
'warm' not in workout.ride.title.lower()] | |
assert len(ftp) >= 1, 'No FTP test found' | |
ftp = sorted(ftp, key=lambda x: x.start_time)[-1] # newest one | |
factor = 0.95 | |
ftp_watts = np.array(ftp.metrics.output.values).mean() | |
print(f'{ftp.ride.instructor.first_name}\'s {ftp.ride.title}: ' | |
f'{ftp.start_time.astimezone(my_tz)}\n' | |
f' {ftp_watts * factor:0.1f} watts (from {ftp_watts:0.1f})') | |
workouts = [ | |
workout for workout in tqdm(workouts, desc='Fetching metrics') | |
if 'ride' in workout.ride.title.lower().split() and # is a ride | |
'stretch' not in workout.ride.title.lower() and # not a stretch | |
workout.start_time > ftp.start_time and # strictly after latest FTP | |
hasattr(workout.metrics, 'output') and # has meaningful metrics | |
len(workout.metrics.output.values) | |
] | |
# figure out the best 20-minute for each ride | |
print(f'Finding best non-FTP ride (of {len(workouts)} eligible)...') | |
mean_20 = np.ones(20 * 60) # over 20 min | |
mean_20 /= len(mean_20) | |
cont_20s = [ | |
np.convolve(mean_20, workout.metrics.output.values, mode='same').max() | |
for workout in workouts] | |
idx = np.argmax(cont_20s) | |
workout = workouts[idx] | |
print(f'{workout.ride.instructor.first_name}\'s {workout.ride.title}: ' | |
f'{workout.start_time.astimezone(my_tz)}\n' | |
f' {cont_20s[idx] * factor:0.1f} watts ' | |
f'(from {cont_20s[idx]:0.1f})') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment