Private
Public Access
1
0

better representation of marker workouts

This commit is contained in:
Sander Roosendaal
2021-01-03 15:57:09 +01:00
parent 254f4eeedb
commit 545cfa0dec
6 changed files with 89 additions and 32 deletions

View File

@@ -739,8 +739,6 @@ class PerformanceManagerForm(forms.Form):
doform = forms.BooleanField(required=False,initial=False, doform = forms.BooleanField(required=False,initial=False,
label='Freshness') label='Freshness')
showtests = forms.BooleanField(required=False,initial=False,
label='Show my best workouts')
class FitnessFitForm(forms.Form): class FitnessFitForm(forms.Form):
startdate = forms.DateField( startdate = forms.DateField(

View File

@@ -114,6 +114,15 @@ def newtestpower(x):
return x['testpower'] return x['testpower']
def newtestpowerid(x):
try:
if np.isnan(x['testpower']):
return np.nan
except (AttributeError,TypeError):
return np.nan
return x['id']
def build_goldmedalstandards(workouts,kfitness): def build_goldmedalstandards(workouts,kfitness):
dates = [] dates = []
testpower = [] testpower = []
@@ -125,11 +134,14 @@ def build_goldmedalstandards(workouts,kfitness):
data = [] data = []
goldmedalstandards = [] goldmedalstandards = []
goldmedaldurations = [] goldmedaldurations = []
ids = []
workoutdt = [] workoutdt = []
ids = []
outids = []
for w in workouts: for w in workouts:
goldmedalstandard,goldmedalseconds = dataprep.workout_goldmedalstandard(w)
ids.append(w.id) ids.append(w.id)
goldmedalstandard,goldmedalseconds = dataprep.workout_goldmedalstandard(w)
if goldmedalseconds > 60: if goldmedalseconds > 60:
goldmedalstandards.append(goldmedalstandard) goldmedalstandards.append(goldmedalstandard)
goldmedaldurations.append(goldmedalseconds) goldmedaldurations.append(goldmedalseconds)
@@ -170,6 +182,7 @@ def build_goldmedalstandards(workouts,kfitness):
powerdf = df[df['workout'].isin(ids)] powerdf = df[df['workout'].isin(ids)]
indexmax = powerdf['goldmedalstandard'].idxmax() indexmax = powerdf['goldmedalstandard'].idxmax()
theid = powerdf.loc[indexmax,'workout']
powertest = powerdf['goldmedalstandard'].max() powertest = powerdf['goldmedalstandard'].max()
durationtest = powerdf.loc[indexmax,'goldmedalduration'] durationtest = powerdf.loc[indexmax,'goldmedalduration']
@@ -178,15 +191,17 @@ def build_goldmedalstandards(workouts,kfitness):
if powertest > 0: if powertest > 0:
testpower.append(powertest) testpower.append(powertest)
testduration.append(durationtest) testduration.append(durationtest)
outids.append(theid)
else: else:
testpower.append(np.nan) testpower.append(np.nan)
testduration.append(np.nan) testduration.append(np.nan)
outids.append(np.nan)
fatigues.append(np.nan) fatigues.append(np.nan)
fitnesses.append(np.nan) fitnesses.append(np.nan)
impulses.append(np.nan) impulses.append(np.nan)
return dates, testpower, testduration, fatigues, fitnesses,impulses return dates, testpower, testduration, fatigues, fitnesses,impulses,outids
def get_testpower(workouts,fitnesstestsecs,kfitness): def get_testpower(workouts,fitnesstestsecs,kfitness):
@@ -1760,6 +1775,7 @@ def getfatigues(
testduration.append(np.nan) testduration.append(np.nan)
return fatigues,fitnesses,dates,testpower,testduration,impulses return fatigues,fitnesses,dates,testpower,testduration,impulses
def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7, def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7,
@@ -1787,16 +1803,19 @@ def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7,
testduration = [] testduration = []
impulses = [] impulses = []
outids = []
if showtests: if showtests:
workouts = Workout.objects.filter(user=user.rower,date__gte=startdate, workouts = Workout.objects.filter(user=user.rower,date__gte=startdate,
date__lte=enddate, date__lte=enddate,
workouttype__in=mytypes.rowtypes, workouttype__in=mytypes.rowtypes,
duplicate=False) duplicate=False)
dates,testpower,testduration,fatigues,fitnesses,impulses = build_goldmedalstandards( dates,testpower,testduration,fatigues,fitnesses,impulses, outids = build_goldmedalstandards(
workouts,kfitness workouts,kfitness
) )
df = pd.DataFrame({ df = pd.DataFrame({
'id': outids,
'date':dates, 'date':dates,
'testpower':testpower, 'testpower':testpower,
'testduration':testduration, 'testduration':testduration,
@@ -1807,11 +1826,12 @@ def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7,
df.sort_values(['date'],inplace=True) df.sort_values(['date'],inplace=True)
df['testdup'] = df['testpower'].shift(1) df['testdup'] = df['testpower'].shift(1)
df['testpower'] = df.apply(lambda x: newtestpower(x),axis=1) df['testpower'] = df.apply(lambda x: newtestpower(x),axis=1)
df['id'] = df.apply(lambda x: newtestpowerid(x),axis=1)
try: #try:
df['testpower'].iloc[-1] = df['testdup'].iloc[-1] # df['testpower'].iloc[-1] = df['testdup'].iloc[-1]
except IndexError: #except IndexError:
pass # pass
dates = [d for d in df['date']] dates = [d for d in df['date']]
@@ -1820,6 +1840,7 @@ def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7,
fitnesses = df['fitness'].values.tolist() fitnesses = df['fitness'].values.tolist()
testduration = df['testduration'].values.tolist() testduration = df['testduration'].values.tolist()
impulses = df['impulse'].tolist() impulses = df['impulse'].tolist()
outids = df['id'].unique()
fatigues,fitnesses,dates,testpower,testduration,impulses = getfatigues(fatigues, fatigues,fitnesses,dates,testpower,testduration,impulses = getfatigues(fatigues,
fitnesses, fitnesses,
@@ -1859,6 +1880,7 @@ def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7,
df = df.groupby(['date']).max() df = df.groupby(['date']).max()
df['date'] = df.index.values df['date'] = df.index.values
#for row in df.iterrows(): #for row in df.iterrows():
# print(row) # print(row)
@@ -1928,9 +1950,9 @@ def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7,
yaxlabel = 'Fitness' yaxlabel = 'Fitness'
if showtests: #if showtests:
plot.circle('date','testpower',source=source,fill_color='green',size=10, # plot.circle('date','testpower',source=source,fill_color='green',size=10,
legend_label='Your best workouts') # legend_label='Your best workouts')
plot.xaxis.axis_label = None plot.xaxis.axis_label = None
plot.yaxis.axis_label = yaxlabel plot.yaxis.axis_label = yaxlabel
@@ -1938,13 +1960,13 @@ def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7,
y2rangemin = df.loc[:,['form']].min().min() y2rangemin = df.loc[:,['form']].min().min()
y2rangemax = df.loc[:,['form']].max().max() y2rangemax = df.loc[:,['form']].max().max()
if dofatigue and showtests: #if dofatigue and showtests:
y1rangemin = df.loc[:,['testpower','fitness','fatigue']].min().min() # y1rangemin = df.loc[:,['testpower','fitness','fatigue']].min().min()
y1rangemax = df.loc[:,['testpower','fitness','fatigue']].max().max()*1.02 # y1rangemax = df.loc[:,['testpower','fitness','fatigue']].max().max()*1.02
elif showtests: #elif showtests:
y1rangemin = df.loc[:,['testpower','fitness']].min().min() # y1rangemin = df.loc[:,['testpower','fitness']].min().min()
y1rangemax = df.loc[:,['testpower','fitness']].max().max()*1.02 # y1rangemax = df.loc[:,['testpower','fitness']].max().max()*1.02
elif dofatigue: if dofatigue:
y1rangemin = df.loc[:,['fitness','fatigue']].min().min() y1rangemin = df.loc[:,['fitness','fatigue']].min().min()
y1rangemax = df.loc[:,['fitness','fatigue']].max().max()*1.02 y1rangemax = df.loc[:,['fitness','fatigue']].max().max()*1.02
else: else:
@@ -2024,6 +2046,7 @@ def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7,
plot2.y_range = Range1d(0,df['impulse'].max()) plot2.y_range = Range1d(0,df['impulse'].max())
plot2.vbar(x = df['date'], top = df['impulse'],color='gray') plot2.vbar(x = df['date'], top = df['impulse'],color='gray')
plot2.vbar(x = df['date'], top = 0*df['testpower']+df['impulse'], color='red')
plot2.sizing_mode = 'scale_both' plot2.sizing_mode = 'scale_both'
plot2.yaxis.axis_label = 'Impulse' plot2.yaxis.axis_label = 'Impulse'
@@ -2045,10 +2068,10 @@ def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7,
nrworkouts = workouts.count(), nrworkouts = workouts.count(),
nrdata = len(df), nrdata = len(df),
e = e, e = e,
) ),0,0,0,[]
) )
return [script,div,endfitness,endfatigue,endform] return [script,div,endfitness,endfatigue,endform,outids]
def fitnessfit_chart(workouts,user,workoutmode='water',startdate=None, def fitnessfit_chart(workouts,user,workoutmode='water',startdate=None,

View File

@@ -891,7 +891,6 @@ class Rower(models.Model):
kfatigue = models.IntegerField(default=7,verbose_name='Fatigue Time Decay Constant (days)') kfatigue = models.IntegerField(default=7,verbose_name='Fatigue Time Decay Constant (days)')
showfit = models.BooleanField(default=False) showfit = models.BooleanField(default=False)
showfresh = models.BooleanField(default=False) showfresh = models.BooleanField(default=False)
showtests = models.BooleanField(default=False)
pw_ut2 = models.IntegerField(default=124,verbose_name="UT2 Power") pw_ut2 = models.IntegerField(default=124,verbose_name="UT2 Power")
pw_ut1 = models.IntegerField(default=171,verbose_name="UT1 Power") pw_ut1 = models.IntegerField(default=171,verbose_name="UT1 Power")

View File

@@ -113,9 +113,12 @@
make this chart shorter than a few months. make this chart shorter than a few months.
</p> </p>
<p> <p>
Optionally, the chart shows you workouts that represent your best performance for that period. The bottom chart shows the training impulse of each individual workout. A gray bar
We automatically detect hard workout segments and tests and compare them to world class denotes a regular workout. The red bars denote workouts that stand out in terms
("Gold Medal") standards for your gender, weight and age category. of your power/time performance for that period. This is only available for workouts
where Power (Watts) is measured. How well you performed is expressed as a
Gold Medal Score, where 100 means you are as good as the world class
athletes of your gender, weight and age category.
</p> </p>
<p> <p>
For this chart to reflect your fitness and freshness, it is important to have all workouts on For this chart to reflect your fitness and freshness, it is important to have all workouts on
@@ -148,6 +151,37 @@
</p> </p>
</div> </div>
</li> </li>
{% if bestworkouts %}
<h2>Marker Workouts</h2>
<li class="grid_4">
<table width="100%" class="listtable">
<thead>
<tr>
<th>Date</th>
<th>Workout</th>
<th>Gold Medal Score</th>
<th>Duration</th>
</tr>
</thead>
<tbody>
{% for w in bestworkouts %}
<tr>
<td>{{ w.date }}</td>
<td>
<a href="/rowers/workout/{{ w.id|encode }}/">{{ w.name }}
</td>
<td>
{{ w.goldmedalstandard|floatformat:"0" }} %
</td>
<td>
{{ w.goldmedalseconds|secondstotimestring }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</li>
{% endif %}
</ul> </ul>

View File

@@ -270,6 +270,7 @@ def strfdeltah(tdelta):
return res return res
@register.filter
def secondstotimestring(tdelta): def secondstotimestring(tdelta):
hours, rest = divmod(tdelta,3600) hours, rest = divmod(tdelta,3600)
minutes,seconds = divmod(rest,60) minutes,seconds = divmod(rest,60)

View File

@@ -1567,7 +1567,6 @@ def performancemanager_view(request,userid=0,mode='rower',
usegoldmedalstandard = False usegoldmedalstandard = False
doform = therower.showfresh doform = therower.showfresh
dofatigue = therower.showfit dofatigue = therower.showfit
showtests = therower.showtests
if request.method == 'POST': if request.method == 'POST':
form = PerformanceManagerForm(request.POST) form = PerformanceManagerForm(request.POST)
@@ -1577,28 +1576,30 @@ def performancemanager_view(request,userid=0,mode='rower',
metricchoice = form.cleaned_data['metricchoice'] metricchoice = form.cleaned_data['metricchoice']
dofatigue = form.cleaned_data['dofatigue'] dofatigue = form.cleaned_data['dofatigue']
doform = form.cleaned_data['doform'] doform = form.cleaned_data['doform']
showtests = form.cleaned_data['showtests']
therower.showfresh = doform therower.showfresh = doform
therower.showfatigue = dofatigue therower.showfatigue = dofatigue
therower.showtests = showtests
therower.save() therower.save()
else: else:
form = PerformanceManagerForm(initial={ form = PerformanceManagerForm(initial={
'doform':doform, 'doform':doform,
'dofatigue':dofatigue, 'dofatigue':dofatigue,
'showtests':showtests,
}) })
script, thediv, endfitness, endfatigue, endform = performance_chart( script, thediv, endfitness, endfatigue, endform, ids = performance_chart(
theuser,startdate=startdate,enddate=enddate, theuser,startdate=startdate,enddate=enddate,
kfitness = kfitness, kfitness = kfitness,
kfatigue = kfatigue, kfatigue = kfatigue,
metricchoice = metricchoice, metricchoice = metricchoice,
doform = doform, doform = doform,
dofatigue = dofatigue, dofatigue = dofatigue,
showtests = showtests, showtests = True,
) )
ids = pd.Series(ids).dropna().values
bestworkouts = Workout.objects.filter(id__in=ids).order_by('date')
breadcrumbs = [ breadcrumbs = [
{ {
'url':'/rowers/analysis', 'url':'/rowers/analysis',
@@ -1634,6 +1635,7 @@ def performancemanager_view(request,userid=0,mode='rower',
'endfitness':int(endfitness), 'endfitness':int(endfitness),
'endfatigue':int(endfatigue), 'endfatigue':int(endfatigue),
'endform':int(endform), 'endform':int(endform),
'bestworkouts':bestworkouts,
}) })