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,
label='Freshness')
showtests = forms.BooleanField(required=False,initial=False,
label='Show my best workouts')
class FitnessFitForm(forms.Form):
startdate = forms.DateField(

View File

@@ -114,6 +114,15 @@ def newtestpower(x):
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):
dates = []
testpower = []
@@ -125,11 +134,14 @@ def build_goldmedalstandards(workouts,kfitness):
data = []
goldmedalstandards = []
goldmedaldurations = []
ids = []
workoutdt = []
ids = []
outids = []
for w in workouts:
goldmedalstandard,goldmedalseconds = dataprep.workout_goldmedalstandard(w)
ids.append(w.id)
goldmedalstandard,goldmedalseconds = dataprep.workout_goldmedalstandard(w)
if goldmedalseconds > 60:
goldmedalstandards.append(goldmedalstandard)
goldmedaldurations.append(goldmedalseconds)
@@ -170,6 +182,7 @@ def build_goldmedalstandards(workouts,kfitness):
powerdf = df[df['workout'].isin(ids)]
indexmax = powerdf['goldmedalstandard'].idxmax()
theid = powerdf.loc[indexmax,'workout']
powertest = powerdf['goldmedalstandard'].max()
durationtest = powerdf.loc[indexmax,'goldmedalduration']
@@ -178,15 +191,17 @@ def build_goldmedalstandards(workouts,kfitness):
if powertest > 0:
testpower.append(powertest)
testduration.append(durationtest)
outids.append(theid)
else:
testpower.append(np.nan)
testduration.append(np.nan)
outids.append(np.nan)
fatigues.append(np.nan)
fitnesses.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):
@@ -1760,6 +1775,7 @@ def getfatigues(
testduration.append(np.nan)
return fatigues,fitnesses,dates,testpower,testduration,impulses
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 = []
impulses = []
outids = []
if showtests:
workouts = Workout.objects.filter(user=user.rower,date__gte=startdate,
date__lte=enddate,
workouttype__in=mytypes.rowtypes,
duplicate=False)
dates,testpower,testduration,fatigues,fitnesses,impulses = build_goldmedalstandards(
dates,testpower,testduration,fatigues,fitnesses,impulses, outids = build_goldmedalstandards(
workouts,kfitness
)
df = pd.DataFrame({
'id': outids,
'date':dates,
'testpower':testpower,
'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['testdup'] = df['testpower'].shift(1)
df['testpower'] = df.apply(lambda x: newtestpower(x),axis=1)
df['id'] = df.apply(lambda x: newtestpowerid(x),axis=1)
try:
df['testpower'].iloc[-1] = df['testdup'].iloc[-1]
except IndexError:
pass
#try:
# df['testpower'].iloc[-1] = df['testdup'].iloc[-1]
#except IndexError:
# pass
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()
testduration = df['testduration'].values.tolist()
impulses = df['impulse'].tolist()
outids = df['id'].unique()
fatigues,fitnesses,dates,testpower,testduration,impulses = getfatigues(fatigues,
fitnesses,
@@ -1859,6 +1880,7 @@ def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7,
df = df.groupby(['date']).max()
df['date'] = df.index.values
#for row in df.iterrows():
# print(row)
@@ -1928,9 +1950,9 @@ def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7,
yaxlabel = 'Fitness'
if showtests:
plot.circle('date','testpower',source=source,fill_color='green',size=10,
legend_label='Your best workouts')
#if showtests:
# plot.circle('date','testpower',source=source,fill_color='green',size=10,
# legend_label='Your best workouts')
plot.xaxis.axis_label = None
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()
y2rangemax = df.loc[:,['form']].max().max()
if dofatigue and showtests:
y1rangemin = df.loc[:,['testpower','fitness','fatigue']].min().min()
y1rangemax = df.loc[:,['testpower','fitness','fatigue']].max().max()*1.02
elif showtests:
y1rangemin = df.loc[:,['testpower','fitness']].min().min()
y1rangemax = df.loc[:,['testpower','fitness']].max().max()*1.02
elif dofatigue:
#if dofatigue and showtests:
# y1rangemin = df.loc[:,['testpower','fitness','fatigue']].min().min()
# y1rangemax = df.loc[:,['testpower','fitness','fatigue']].max().max()*1.02
#elif showtests:
# y1rangemin = df.loc[:,['testpower','fitness']].min().min()
# y1rangemax = df.loc[:,['testpower','fitness']].max().max()*1.02
if dofatigue:
y1rangemin = df.loc[:,['fitness','fatigue']].min().min()
y1rangemax = df.loc[:,['fitness','fatigue']].max().max()*1.02
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.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.yaxis.axis_label = 'Impulse'
@@ -2045,10 +2068,10 @@ def performance_chart(user,startdate=None,enddate=None,kfitness=42,kfatigue=7,
nrworkouts = workouts.count(),
nrdata = len(df),
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,

View File

@@ -891,7 +891,6 @@ class Rower(models.Model):
kfatigue = models.IntegerField(default=7,verbose_name='Fatigue Time Decay Constant (days)')
showfit = 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_ut1 = models.IntegerField(default=171,verbose_name="UT1 Power")

View File

@@ -113,9 +113,12 @@
make this chart shorter than a few months.
</p>
<p>
Optionally, the chart shows you workouts that represent your best performance for that period.
We automatically detect hard workout segments and tests and compare them to world class
("Gold Medal") standards for your gender, weight and age category.
The bottom chart shows the training impulse of each individual workout. A gray bar
denotes a regular workout. The red bars denote workouts that stand out in terms
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>
For this chart to reflect your fitness and freshness, it is important to have all workouts on
@@ -148,6 +151,37 @@
</p>
</div>
</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>

View File

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

View File

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