Private
Public Access
1
0

Merge branch 'release/dataprep'

This commit is contained in:
sanderroosendaal
2016-11-03 15:09:43 +01:00
12 changed files with 2772 additions and 3517 deletions
File diff suppressed because it is too large Load Diff
+1082 -1082
View File
File diff suppressed because it is too large Load Diff
+189
View File
@@ -0,0 +1,189 @@
from rowers.models import Workout, User, Rower
from rowingdata import rowingdata as rrdata
from rowingdata import rower as rrower
from rowingdata import main as rmain
from pandas import DataFrame,Series
import pandas as pd
import numpy as np
from scipy.signal import savgol_filter
import datetime
def niceformat(values):
out = []
for v in values:
formattedv = strfdelta(v)
out.append(formattedv)
return out
def strfdelta(tdelta):
try:
minutes,seconds = divmod(tdelta.seconds,60)
tenths = int(tdelta.microseconds/1e5)
except AttributeError:
minutes,seconds = divmod(tdelta.view(np.int64),60e9)
seconds,rest = divmod(seconds,1e9)
tenths = int(rest/1e8)
res = "{minutes:0>2}:{seconds:0>2}.{tenths:0>1}".format(
minutes=minutes,
seconds=seconds,
tenths=tenths,
)
return res
def nicepaceformat(values):
out = []
for v in values:
formattedv = strfdelta(v)
out.append(formattedv)
return out
def timedeltaconv(x):
dt = datetime.timedelta(seconds=x)
return dt
def rdata(file,rower=rrower()):
try:
res = rrdata(file,rower=rower)
except IOError:
res = 0
return res
def getrowdata(id=0):
# check if valid ID exists (workout exists)
row = Workout.objects.get(id=id)
f1 = row.csvfilename
# get user
r = row.user
u = r.user
rr = rrower(hrmax=r.max,hrut2=r.ut2,
hrut1=r.ut1,hrat=r.at,
hrtr=r.tr,hran=r.an)
rowdata = rdata(f1,rower=rr)
return rowdata,row
def dataprep(rowdatadf,bands=False,barchart=False,otwpower=False):
rowdatadf.set_index([range(len(rowdatadf))],inplace=True)
t = rowdatadf.ix[:,'TimeStamp (sec)']
t = pd.Series(t-rowdatadf.ix[0,'TimeStamp (sec)'])
row_index = rowdatadf.ix[:,' Stroke500mPace (sec/500m)'] > 3000
rowdatadf.loc[row_index,' Stroke500mPace (sec/500m)'] = 3000.
p = rowdatadf.ix[:,' Stroke500mPace (sec/500m)']
hr = rowdatadf.ix[:,' HRCur (bpm)']
spm = rowdatadf.ix[:,' Cadence (stokes/min)']
cumdist = rowdatadf.ix[:,'cum_dist']
power = rowdatadf.ix[:,' Power (watts)']
averageforce = rowdatadf.ix[:,' AverageDriveForce (lbs)']
drivelength = rowdatadf.ix[:,' DriveLength (meters)']
peakforce = rowdatadf.ix[:,' PeakDriveForce (lbs)']
f = rowdatadf['TimeStamp (sec)'].diff().mean()
windowsize = 2*(int(10./(f)))+1
if windowsize <= 3:
windowsize = 5
if windowsize > 3:
spm = savgol_filter(spm,windowsize,3)
hr = savgol_filter(hr,windowsize,3)
drivelength = savgol_filter(drivelength,windowsize,3)
t2 = t.fillna(method='ffill').apply(lambda x: timedeltaconv(x))
p2 = p.fillna(method='ffill').apply(lambda x: timedeltaconv(x))
drivespeed = drivelength/rowdatadf[' DriveTime (ms)']*1.0e3
driveenergy = drivelength*averageforce*4.44822
distance = rowdatadf.ix[:,'cum_dist']
data = DataFrame(
dict(
time = t2,
timesecs = t,
hr = hr,
pace = p2,
pseconds=p,
spm = spm,
cumdist = cumdist,
ftime = niceformat(t2),
fpace = nicepaceformat(p2),
driveenergy=driveenergy,
power=power,
averageforce=averageforce,
drivelength=drivelength,
peakforce=peakforce,
distance=distance,
drivespeed=drivespeed,
)
)
if bands:
# HR bands
data['hr_ut2'] = rowdatadf.ix[:,'hr_ut2']
data['hr_ut1'] = rowdatadf.ix[:,'hr_ut1']
data['hr_at'] = rowdatadf.ix[:,'hr_at']
data['hr_tr'] = rowdatadf.ix[:,'hr_tr']
data['hr_an'] = rowdatadf.ix[:,'hr_an']
data['hr_max'] = rowdatadf.ix[:,'hr_max']
data['hr_bottom'] = 0.0*data['hr']
if barchart:
# time increments for bar chart
time_increments = rowdatadf.ix[:,' ElapsedTime (sec)'].diff()
time_increments[0] = time_increments[1]
time_increments = 0.5*time_increments+0.5*np.abs(time_increments)
x_right = (t2+time_increments.apply(lambda x:timedeltaconv(x)))
data['x_right'] = x_right
if otwpower:
try:
nowindpace = rowdatadf.ix[:,'nowindpace']
except KeyError:
nowindpace = p
try:
equivergpower = rowdatadf.ix[:,'equivergpower']
except KeyError:
equivergpower = 0*p+50.
nowindpace = nowindpace.apply(lambda x: timedeltaconv(x))
ergvelo = (equivergpower/2.8)**(1./3.)
ergpace = 500./ergvelo
ergpace[ergpace == np.inf] = 240.
ergpace = ergpace.apply(lambda x: timedeltaconv(x))
data['ergpace'] = ergpace
data['nowindpace'] = nowindpace
data['equivergpower'] = equivergpower
data['fergpace'] = nicepaceformat(ergpace)
data['fnowindpace'] = nicepaceformat(nowindpace)
return data
+217 -1084
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -107,6 +107,7 @@ You will be taken to the secure PayPal payment site.
<ul>
<li>2016-11-01 Sliders to select subsets of data on some plots</li>
<li>2016-11-01 Emailing workouts to workouts@rowsandall.com </li>
<li>2016-11-01 Interval Editor </li>
<li>2016-09-30 Stroke Analysis Plot - with date range filtering</li>
<li>2016-09-29 Improved Flex plot, Power Histogram and Ranking Pieces - with date range filtering</li>
<li>2016-09-20 Added the Power histogram</li>
+2
View File
@@ -53,7 +53,9 @@
</div>
{% endif %}
<div id="theplot" class="grid_12 alpha flexplot">
{{ the_div|safe }}
</div>
</div>
+3 -1
View File
@@ -61,11 +61,13 @@
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/otwsetpower">OTW Power</a>
</div>
{% endif %}
</div>
<div id="theplot" class="grid_12 alpha flexplot">
<div>
{{ the_div|safe }}
</div>
<div class="grid_12">
<p>
<h3>Notes</h3>
<ul>
+2 -2
View File
@@ -170,7 +170,7 @@
<td> {{ value }} W </td>
{% endif %}
{% if key == "duration" %}
<td> {{ value |paceprint }} </td>
<td> {{ value |deltatimeprint }} </td>
{% endif %}
{% endfor %}
</tr>
@@ -209,7 +209,7 @@
<td> {{ value }} W </td>
{% endif %}
{% if key == "duration" %}
<td> {{ value |paceprint }} </td>
<td> {{ value |deltatimeprint }} </td>
{% endif %}
{% endfor %}
</tr>
+21 -1
View File
@@ -6,7 +6,20 @@ register = template.Library()
def strfdelta(tdelta):
minutes,seconds = divmod(tdelta.seconds,60)
tenths = int(tdelta.microseconds/1e5)
res = "{minutes:0>2}:{seconds:0>2}.{tenths:0>1}".format(
res = "{minutes:0>1}:{seconds:0>2}.{tenths:0>1}".format(
minutes=minutes,
seconds=seconds,
tenths=tenths,
)
return res
def strfdeltah(tdelta):
hours, rest = divmod(tdelta.seconds,3600)
minutes,seconds = divmod(rest,60)
tenths = int(tdelta.microseconds/1e5)
res = "{hours:0>2}:{minutes:0>2}:{seconds:0>2}.{tenths:0>1}".format(
hours=hours,
minutes=minutes,
seconds=seconds,
tenths=tenths,
@@ -28,6 +41,13 @@ def paceprint(d):
else:
return strfdelta(d)
@register.filter
def deltatimeprint(d):
if (d == None):
return d
else:
return strfdeltah(d)
@register.filter
def lookup(dict, key):
+8 -12
View File
@@ -229,22 +229,22 @@ class DataTest(TestCase):
res = iplots.interactive_chart(w.id,promember=1)
res = iplots.interactive_bar_chart(w.id)
res = iplots.interactive_bar_chart(w.id,promember=1)
res = iplots.interactive_flex_chart(w.id,promember=0,xparam='time',
res = iplots.interactive_flex_chart2(w.id,promember=0,xparam='time',
yparam1='pace',yparam2='hr')
res = iplots.interactive_flex_chart(w.id,promember=0,xparam='distance',
res = iplots.interactive_flex_chart2(w.id,promember=0,xparam='distance',
yparam1='pace',yparam2='hr')
res = iplots.interactive_flex_chart(w.id,promember=0,xparam='time',
res = iplots.interactive_flex_chart2(w.id,promember=0,xparam='time',
yparam1='pace',yparam2='spm')
res = iplots.interactive_flex_chart(w.id,promember=0,xparam='distance',
res = iplots.interactive_flex_chart2(w.id,promember=0,xparam='distance',
yparam1='pace',yparam2='spm')
res = iplots.interactive_flex_chart(w.id,promember=1,xparam='time',
res = iplots.interactive_flex_chart2(w.id,promember=1,xparam='time',
yparam1='pace',yparam2='hr')
res = iplots.interactive_flex_chart(w.id,promember=1,xparam='distance',
res = iplots.interactive_flex_chart2(w.id,promember=1,xparam='distance',
yparam1='pace',yparam2='hr')
res = iplots.interactive_flex_chart(w.id,promember=1,xparam='time',
res = iplots.interactive_flex_chart2(w.id,promember=1,xparam='time',
yparam1='pace',yparam2='spm')
res = iplots.interactive_flex_chart(w.id,promember=1,xparam='distance',
res = iplots.interactive_flex_chart2(w.id,promember=1,xparam='distance',
yparam1='pace',yparam2='spm')
@@ -793,10 +793,6 @@ class subroutinetests(TestCase):
duration="0:55:00",distance=8000,
csvfilename=filename)
def test_seconds(self):
seconds = [30.3,75.8,3900.3,104670.2]
res = iplots.get_datetimes(seconds)
def c2stuff(self):
data = c2stuff.createc2workoutdata(self.w)
+1 -5
View File
@@ -127,12 +127,8 @@ urlpatterns = [
url(r'^register/thankyou/$', TemplateView.as_view(template_name='registerthankyou.html'), name='registerthankyou'),
url(r'^workout/(?P<id>\d+)/flexchart/(?P<xparam>\w+.*)/(?P<yparam1>\w+.*)/(?P<yparam2>\w+.*)/(?P<plottype>\w+)/$',views.workout_flexchart3_view),
url(r'^workout/(?P<id>\d+)/flexchart/(?P<xparam>\w+.*)/(?P<yparam1>\w+.*)/(?P<yparam2>\w+.*)/(?P<plottype>\w+.*)$',views.workout_flexchart3_view),
url(r'^workout/(?P<id>\d+)/flexchart/(?P<xparam>\w+.*)/(?P<yparam1>\w+.*)/(?P<yparam2>\w+.*)$',views.workout_flexchart2_view),
url(r'^workout/(?P<id>\d+)/flexchart/(?P<xparam>\w+.*)/(?P<yparam1>\w+.*)/(?P<yparam2>\w+.*)$',views.workout_flexchart3_view),
url(r'^workout/(?P<id>\d+)/flexchart$',views.workout_flexchart3_view),
url(r'^workout/(?P<id>\d+)/flexchart2/(?P<xparam>\w+.*)/(?P<yparam1>\w+.*)/(?P<yparam2>\w+.*)/(?P<plottype>\w+)/$',views.workout_flexchart2_view),
url(r'^workout/(?P<id>\d+)/flexchart2/(?P<xparam>\w+.*)/(?P<yparam1>\w+.*)/(?P<yparam2>\w+.*)/(?P<plottype>\w+.*)$',views.workout_flexchart2_view),
url(r'^workout/(?P<id>\d+)/flexchart2/(?P<xparam>\w+.*)/(?P<yparam1>\w+.*)/(?P<yparam2>\w+.*)$',views.workout_flexchart3_view),
url(r'^workout/(?P<id>\d+)/flexchart2$',views.workout_flexchart2_view),
url(r'^workout/compare/(?P<id1>\d+)/(?P<id2>\d+)/(?P<xparam>\w+.*)/(?P<yparam>\w+.*)/(?P<plottype>\w+.*)$',views.workout_comparison_view2),
url(r'^workout/compare/(?P<id1>\d+)/(?P<id2>\d+)/(?P<xparam>\w+.*)/(?P<yparam>\w+.*)/$',views.workout_comparison_view2),
]
+11 -95
View File
@@ -66,6 +66,7 @@ import mailprocessing
from io import BytesIO
from scipy.special import lambertw
from dataprep import timedeltaconv
LOCALTIMEZONE = tz('Etc/UTC')
USER_LANGUAGE = 'en-US'
@@ -1204,8 +1205,8 @@ def cum_flex(request,theuser=0,
xparam='spm',
yparam1='power',
yparam2='None',
startdate=timezone.now()-datetime.timedelta(days=30),
enddate=timezone.now(),
startdate=timezone.now()-datetime.timedelta(days=10),
enddate=timezone.now()+datetime.timedelta(days=1),
deltadays=-1,
startdatestring="",
enddatestring=""):
@@ -1617,8 +1618,8 @@ def rankings_view(request,theuser=0,
t = rankingdistance/velo
pwr = 2.8*(velo**3)
a = {'distance':rankingdistance,
'duration':get_datetimes([t])[0],
'pace':get_datetimes([p])[0],
'duration':timedeltaconv(t),
'pace':timedeltaconv(p),
'power':int(pwr)}
predictions.append(a)
@@ -1650,8 +1651,8 @@ def rankings_view(request,theuser=0,
p3 = 500./velo3
a = {'distance':rankingdistance,
'duration':get_datetimes([t3])[0],
'pace':get_datetimes([p3])[0],
'duration':timedeltaconv(t3),
'pace':timedeltaconv(p3),
'power':int(pwr3)}
cpredictions.append(a)
@@ -1677,8 +1678,8 @@ def rankings_view(request,theuser=0,
p = 500./velo
pwr = 2.8*(velo**3)
a = {'distance':int(d),
'duration':get_datetimes([t])[0],
'pace':get_datetimes([p])[0],
'duration':timedeltaconv(t),
'pace':timedeltaconv(p),
'power':int(pwr)}
predictions.append(a)
@@ -1697,8 +1698,8 @@ def rankings_view(request,theuser=0,
d = t*velo
p = 500./velo
a = {'distance':int(d),
'duration':get_datetimes([t])[0],
'pace':get_datetimes([p])[0],
'duration':timedeltaconv(t),
'pace':timedeltaconv(p),
'power':int(pwr)}
cpredictions.append(a)
@@ -2344,91 +2345,6 @@ def workout_comparison_view2(request,id1=0,id2=0,xparam='distance',
'promember':promember,
})
def workout_flexchart_view(request,id=0,xparam='distance',yparam1='pace',
yparam2='hr',
promember=0):
if request.method == 'POST':
workstrokesonly = request.POST['workstrokesonly']
else:
workstrokesonly = False
row = Workout.objects.get(id=id)
promember=0
mayedit=0
if not request.user.is_anonymous():
r = Rower.objects.get(user=request.user)
result = request.user.is_authenticated() and r.rowerplan=='pro'
if result:
promember=1
if request.user == row.user.user:
mayedit=1
# create interactive plot
res = interactive_flex_chart(id,xparam=xparam,yparam1=yparam1,
yparam2=yparam2,
promember=promember)
script = res[0]
div = res[1]
return render(request,
'flexchart.html',
{'interactiveplot':script,
'the_div':div,
'id':id,
'xparam':xparam,
'yparam1':yparam1,
'yparam2':yparam2,
'mayedit':mayedit,
})
def workout_flexchart2_view(request,id=0,xparam='distance',yparam1='pace',
yparam2='hr',plottype='line',
promember=0):
if request.method == 'POST':
workstrokesonly = request.POST['workstrokesonly']
if workstrokesonly == 'True':
workstrokesonly = True
else:
workstrokesonly = False
else:
workstrokesonly = False
row = Workout.objects.get(id=id)
promember=0
mayedit=0
if not request.user.is_anonymous():
r = Rower.objects.get(user=request.user)
result = request.user.is_authenticated() and r.rowerplan=='pro'
if result:
promember=1
if request.user == row.user.user:
mayedit=1
# create interactive plot
res = interactive_flex_chart(id,xparam=xparam,yparam1=yparam1,
yparam2=yparam2,
promember=promember,plottype=plottype,
workstrokesonly=workstrokesonly)
script = res[0]
div = res[1]
return render(request,
'flexchart2.html',
{'interactiveplot':script,
'the_div':div,
'id':id,
'xparam':xparam,
'yparam1':yparam1,
'yparam2':yparam2,
'plottype':plottype,
'mayedit':mayedit,
'promember':promember,
'workstrokesonly': not workstrokesonly,
})
def workout_flexchart3_view(request,id=0,xparam='distance',yparam1='pace',