adding trimp or rscore, time constants, test duration to form
This commit is contained in:
@@ -703,6 +703,50 @@ class FitnessMetricForm(forms.Form):
|
|||||||
class Meta:
|
class Meta:
|
||||||
fields = ['startdate','enddate','mode']
|
fields = ['startdate','enddate','mode']
|
||||||
|
|
||||||
|
class FitnessFitForm(forms.Form):
|
||||||
|
startdate = forms.DateField(
|
||||||
|
initial=timezone.now()-datetime.timedelta(days=365),
|
||||||
|
# widget=SelectDateWidget(years=range(1990,2050)),
|
||||||
|
widget=AdminDateWidget(),
|
||||||
|
label='Start Date')
|
||||||
|
enddate = forms.DateField(
|
||||||
|
initial=timezone.now(),
|
||||||
|
widget=AdminDateWidget(),
|
||||||
|
label='End Date')
|
||||||
|
|
||||||
|
modechoices = (
|
||||||
|
('rower','indoor rower'),
|
||||||
|
('water','on the water')
|
||||||
|
)
|
||||||
|
|
||||||
|
metricchoices = (
|
||||||
|
('trimp','TRIMP'),
|
||||||
|
('rscore','rScore')
|
||||||
|
)
|
||||||
|
|
||||||
|
fitnesstest = forms.IntegerField(required=True,initial=20,
|
||||||
|
label='Test Duration (minutes)')
|
||||||
|
|
||||||
|
kfitness = forms.IntegerField(initial=42,required=True,
|
||||||
|
label='Fitness Time Constant (days)')
|
||||||
|
|
||||||
|
kfatigue = forms.IntegerField(initial=7,required=True,
|
||||||
|
label='Fatigue Time Constant (days)')
|
||||||
|
|
||||||
|
metricchoice = forms.ChoiceField(required=True,
|
||||||
|
choices=metricchoices,
|
||||||
|
initial='rscore',
|
||||||
|
label='Workload Metric')
|
||||||
|
|
||||||
|
mode = forms.ChoiceField(required=True,
|
||||||
|
choices=modechoices,
|
||||||
|
initial='rower',
|
||||||
|
label='Workout Mode'
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
fields = ['startdate','enddate','mode','fitnesstest','kfitness','kfatigue','metricchoice']
|
||||||
|
|
||||||
class SessionDateShiftForm(forms.Form):
|
class SessionDateShiftForm(forms.Form):
|
||||||
shiftstartdate = forms.DateField(
|
shiftstartdate = forms.DateField(
|
||||||
initial=timezone.now(),
|
initial=timezone.now(),
|
||||||
|
|||||||
@@ -1528,22 +1528,24 @@ def interactive_forcecurve(theworkouts,workstrokesonly=True,plottype='scatter'):
|
|||||||
return [script,div,js_resources,css_resources]
|
return [script,div,js_resources,css_resources]
|
||||||
|
|
||||||
def fitnessfit_chart(workouts,user,workoutmode='water',startdate=None,
|
def fitnessfit_chart(workouts,user,workoutmode='water',startdate=None,
|
||||||
enddate=None,nrdays=42):
|
enddate=None,kfitness=42,kfatigue=7,fitnesstest=20):
|
||||||
|
|
||||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
||||||
|
|
||||||
dates = []
|
dates = []
|
||||||
fourminpower = []
|
testpower = []
|
||||||
hourpower = []
|
|
||||||
|
|
||||||
workouts = workouts.order_by('date')
|
workouts = workouts.order_by('date')
|
||||||
data = []
|
data = []
|
||||||
|
|
||||||
|
fitnesstestsecs = fitnesstest*60
|
||||||
|
|
||||||
for w in workouts:
|
for w in workouts:
|
||||||
cpfile = 'media/cpdata_{id}.parquet.gz'.format(id=w.id)
|
cpfile = 'media/cpdata_{id}.parquet.gz'.format(id=w.id)
|
||||||
try:
|
try:
|
||||||
df = pd.read_parquet(cpfile)
|
df = pd.read_parquet(cpfile)
|
||||||
df['workout'] = w.id
|
df['workout'] = w.id
|
||||||
|
df['workoutdate'] = w.date.strftime('%d-%m-%Y')
|
||||||
data.append(df)
|
data.append(df)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
@@ -1557,7 +1559,7 @@ def fitnessfit_chart(workouts,user,workoutmode='water',startdate=None,
|
|||||||
errfunc = lambda pars,x,y: fitfunc(pars,x)-y
|
errfunc = lambda pars,x,y: fitfunc(pars,x)-y
|
||||||
|
|
||||||
for w in workouts:
|
for w in workouts:
|
||||||
ids = [w.id for w in workouts.filter(date__gte=w.date-datetime.timedelta(days=nrdays),
|
ids = [w.id for w in workouts.filter(date__gte=w.date-datetime.timedelta(days=kfitness),
|
||||||
date__lte=w.date)]
|
date__lte=w.date)]
|
||||||
|
|
||||||
powerdf = df[df['workout'].isin(ids)]
|
powerdf = df[df['workout'].isin(ids)]
|
||||||
@@ -1577,46 +1579,39 @@ def fitnessfit_chart(workouts,user,workoutmode='water',startdate=None,
|
|||||||
thesecs = powerdf['delta'].values
|
thesecs = powerdf['delta'].values
|
||||||
theavpower = powerdf['cp'].values
|
theavpower = powerdf['cp'].values
|
||||||
|
|
||||||
if thesecs.min() < 240 and thesecs.max() > 240:
|
if thesecs.min() < fitnesstestsecs and thesecs.max() > fitnesstestsecs:
|
||||||
ww = griddata(thesecs,theavpower,np.arange(239,241,1),method='linear',rescale=True)
|
ww = griddata(thesecs,theavpower,np.array([fitnesstestsecs]),method='linear',rescale=True)
|
||||||
powerfourmin = ww[1]
|
powertest = ww[0]
|
||||||
else:
|
else:
|
||||||
powerfourmin = np.nan
|
powertest = np.nan
|
||||||
|
|
||||||
|
|
||||||
if thesecs.min() < 3600 and thesecs.max() > 3600:
|
|
||||||
ww = griddata(thesecs,theavpower,np.arange(3599,3601,1),method='linear',rescale=True)
|
|
||||||
powerhour = ww[1]
|
|
||||||
else:
|
|
||||||
powerhour = np.nan
|
|
||||||
|
|
||||||
dates.append(datetime.datetime.combine(w.date,datetime.datetime.min.time()))
|
dates.append(datetime.datetime.combine(w.date,datetime.datetime.min.time()))
|
||||||
fourminpower.append(powerfourmin)
|
testpower.append(powertest)
|
||||||
hourpower.append(powerhour)
|
|
||||||
|
|
||||||
df = pd.DataFrame({
|
df = pd.DataFrame({
|
||||||
'date':dates,
|
'date':dates,
|
||||||
'fourminpower':fourminpower,
|
'testpower':testpower,
|
||||||
'hourpower':hourpower,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
df.sort_values(['date'],inplace=True)
|
df.sort_values(['date'],inplace=True)
|
||||||
|
|
||||||
df['hourdup'] = df['hourpower'].shift(1)
|
|
||||||
df['fourmindup'] = df['fourminpower'].shift(1)
|
|
||||||
df['hourpower'] = df.apply(lambda x: np.nan if abs(x['hourpower'] - x['hourdup']) < 4 \
|
|
||||||
else x['hourpower'],axis=1)
|
|
||||||
|
|
||||||
df['fourminpower'] = df.apply(lambda x: np.nan if abs(x['fourminpower'] - x['fourmindup']) < 4 \
|
df['testdup'] = df['testpower'].shift(1)
|
||||||
else x['fourminpower'],axis=1)
|
df['testpower'] = df.apply(lambda x: np.nan if abs(x['testpower'] - x['testdup']) < 4 \
|
||||||
|
else x['testpower'],axis=1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
source = ColumnDataSource(
|
source = ColumnDataSource(
|
||||||
data = dict(
|
data = dict(
|
||||||
fourminpower = df['fourminpower'],
|
testpower = df['testpower'],
|
||||||
hourpower = df['hourpower'],
|
|
||||||
date = df['date'],
|
date = df['date'],
|
||||||
fdate = df['date'].map(lambda x: x.strftime('%d-%m-%Y'))
|
fdate = df['date'].map(lambda x: x.strftime('%d-%m-%Y'))
|
||||||
)
|
)
|
||||||
@@ -1656,10 +1651,8 @@ def fitnessfit_chart(workouts,user,workoutmode='water',startdate=None,
|
|||||||
y_range_name = "watermark",
|
y_range_name = "watermark",
|
||||||
)
|
)
|
||||||
|
|
||||||
plot.circle('date','fourminpower',source=source,fill_color='green',size=10,legend_label='4 min power')
|
plot.circle('date','testpower',source=source,fill_color='green',size=10,
|
||||||
plot.circle('date','hourpower',source=source,fill_color='blue',size=10,legend_label='60 min power')
|
legend_label='{fitnesstest} min power'.format(fitnesstest=fitnesstest))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
plot.xaxis.axis_label = 'Date'
|
plot.xaxis.axis_label = 'Date'
|
||||||
plot.yaxis.axis_label = 'Power (W)'
|
plot.yaxis.axis_label = 'Power (W)'
|
||||||
@@ -1673,7 +1666,7 @@ def fitnessfit_chart(workouts,user,workoutmode='water',startdate=None,
|
|||||||
plot.xaxis.major_label_orientation = pi/4
|
plot.xaxis.major_label_orientation = pi/4
|
||||||
plot.sizing_mode = 'stretch_both'
|
plot.sizing_mode = 'stretch_both'
|
||||||
|
|
||||||
plot.y_range = Range1d(0,1.5*max(fourminpower))
|
plot.y_range = Range1d(0,1.5*max(testpower))
|
||||||
startdate = datetime.datetime.combine(startdate,datetime.datetime.min.time())
|
startdate = datetime.datetime.combine(startdate,datetime.datetime.min.time())
|
||||||
enddate = datetime.datetime.combine(enddate,datetime.datetime.min.time())
|
enddate = datetime.datetime.combine(enddate,datetime.datetime.min.time())
|
||||||
|
|
||||||
@@ -1685,8 +1678,7 @@ def fitnessfit_chart(workouts,user,workoutmode='water',startdate=None,
|
|||||||
hover = plot.select(dict(type=HoverTool))
|
hover = plot.select(dict(type=HoverTool))
|
||||||
|
|
||||||
hover.tooltips = OrderedDict([
|
hover.tooltips = OrderedDict([
|
||||||
('Power 4 minutes','@fourminpower'),
|
('Power {fitnesstest} minutes'.format(fitnesstest=fitnesstest),'@testpower'),
|
||||||
('Power 1 hour','@hourpower'),
|
|
||||||
('Date','@fdate')
|
('Date','@fdate')
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|||||||
@@ -72,11 +72,22 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% if rower.user %}
|
{% if rower.user %}
|
||||||
<h1>Power Progress for {{ rower.user.first_name }} </h1>
|
<h1>Fitness Progress for {{ rower.user.first_name }} </h1>
|
||||||
{% else %}
|
{% else %}
|
||||||
<h1>Power Progress for {{ user.first_name }} </h1>
|
<h1>Fitness Progress for {{ user.first_name }} </h1>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This is an experimental page. Using the form below you can set
|
||||||
|
a date range to compare a prediction of your form (from TRIMP or rScore values
|
||||||
|
representing your workload). The Fitness Time Constant is the
|
||||||
|
time constant describing your fitness decline when you stop training. The
|
||||||
|
Fatigue Time Constant (shorter than fitness time constant) is the time
|
||||||
|
constant describing fatigue decline after a session. You have to select
|
||||||
|
a test duration that represents your fitness goal and is a duration for which
|
||||||
|
you regularly do maximal or submaximal efforts during your regular rowing workouts.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
|
|||||||
@@ -1551,17 +1551,22 @@ def fitness_from_cp_view(request,userid=0,mode='rower',
|
|||||||
|
|
||||||
therower = getrequestrower(request,userid=userid)
|
therower = getrequestrower(request,userid=userid)
|
||||||
theuser = therower.user
|
theuser = therower.user
|
||||||
|
|
||||||
|
|
||||||
|
kfitness = 42
|
||||||
|
kfatigue = 7
|
||||||
|
fitnesstest = 20
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
form = FitnessMetricForm(request.POST)
|
form = FitnessFitForm(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
startdate = form.cleaned_data['startdate']
|
startdate = form.cleaned_data['startdate']
|
||||||
enddate = form.cleaned_data['enddate']
|
enddate = form.cleaned_data['enddate']
|
||||||
mode = form.cleaned_data['mode']
|
mode = form.cleaned_data['mode']
|
||||||
|
kfitness = form.cleaned_data['kfitness']
|
||||||
|
kfatigue = form.cleaned_data['kfatigue']
|
||||||
|
fitnesstest = form.cleaned_data['fitnesstest']
|
||||||
else:
|
else:
|
||||||
form = FitnessMetricForm()
|
form = FitnessFitForm()
|
||||||
|
|
||||||
workouts = Workout.objects.filter(user=therower,date__gte=startdate,
|
workouts = Workout.objects.filter(user=therower,date__gte=startdate,
|
||||||
date__lte=enddate,
|
date__lte=enddate,
|
||||||
@@ -1576,6 +1581,9 @@ def fitness_from_cp_view(request,userid=0,mode='rower',
|
|||||||
workouts,theuser,
|
workouts,theuser,
|
||||||
workoutmode=mode,startdate=startdate,
|
workoutmode=mode,startdate=startdate,
|
||||||
enddate=enddate,
|
enddate=enddate,
|
||||||
|
kfitness=kfitness,
|
||||||
|
kfatigue=kfatigue,
|
||||||
|
fitnesstest=fitnesstest,
|
||||||
)
|
)
|
||||||
|
|
||||||
breadcrumbs = [
|
breadcrumbs = [
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ from rowers.forms import (
|
|||||||
disqualifiers,SearchForm,BillingForm,PlanSelectForm,
|
disqualifiers,SearchForm,BillingForm,PlanSelectForm,
|
||||||
VideoAnalysisCreateForm,WorkoutSingleSelectForm,
|
VideoAnalysisCreateForm,WorkoutSingleSelectForm,
|
||||||
VideoAnalysisMetricsForm,SurveyForm,HistorySelectForm,
|
VideoAnalysisMetricsForm,SurveyForm,HistorySelectForm,
|
||||||
StravaChartForm,
|
StravaChartForm,FitnessFitForm
|
||||||
)
|
)
|
||||||
|
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
|
|||||||
Reference in New Issue
Block a user