From d95ac01172e86e803ade4ec478a82c3b37682d82 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Tue, 19 Sep 2017 16:39:58 +0200 Subject: [PATCH 1/2] added distance per stroke metric --- rowers/dataprep.py | 5 +++++ rowers/metrics.py | 3 ++- rowers/models.py | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 91ca3d6a..6922c4cf 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -1567,6 +1567,9 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True, drivenergy = drivelength*averageforce distance = rowdatadf.ix[:,'cum_dist'] + velo = 500./p + + distanceperstroke = 60.*velo/spm data = DataFrame( @@ -1588,6 +1591,7 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True, distance=distance, drivespeed=drivespeed, rhythm=rhythm, + distanceperstroke=distanceperstroke, ) ) @@ -1667,6 +1671,7 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True, velo = 500./p + ergpw = 2.8*velo**3 efficiency = 100.*ergpw/power diff --git a/rowers/metrics.py b/rowers/metrics.py index c65cbcc0..e41e7b57 100644 --- a/rowers/metrics.py +++ b/rowers/metrics.py @@ -23,7 +23,8 @@ axes = ( ('effectiveangle', 'Effective Drive Length (deg)',40,140,'pro'), ('rhythm', 'Stroke Rhythm (%)',20,55,'pro'), ('efficiency', 'OTW efficiency (%)',0,110,'pro'), - ('None', 'None',0,1,'basic'), + ('distanceperstroke','Distance per Stroke (m)',0,15,'pro'), + ('None', 'None',0,1,'basic'), ) axlabels = {ax[0]:ax[1] for ax in axes} diff --git a/rowers/models.py b/rowers/models.py index b7b8d8fd..bc6b2052 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -560,6 +560,7 @@ class StrokeData(models.Model): totalangle = models.FloatField(default=0.0,null=True,verbose_name='Total Stroke Length (deg)') effectiveangle = models.FloatField(default=0.0,null=True,verbose_name='Effective Stroke Length (deg)') efficiency = models.FloatField(default=-1,null=True,verbose_name='OTW Efficiency') + distanceperstroke = models.FloatField(default=-1,null=True,verbose_name='Distance per Stroke') # A wrapper around the png files class GraphImage(models.Model): From e68995580285d703dd99a4a9de68f0bfba9456e7 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Wed, 20 Sep 2017 11:18:42 +0200 Subject: [PATCH 2/2] added calcdps routine --- rowers/dataprep.py | 86 ++++++++++++++------ rowers/dataprepnodjango.py | 156 ++++++++++++++++++++++++++++--------- rowers/tasks.py | 28 ++++++- rowers/urls.py | 1 + rowers/views.py | 17 +++- 5 files changed, 225 insertions(+), 63 deletions(-) diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 6922c4cf..e4b29c24 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -95,6 +95,7 @@ columndict = { 'wash':'wash', 'slip':'slip', 'workoutstate':' WorkoutState', + 'cumdist':'cum_dist', } from scipy.signal import savgol_filter @@ -1506,7 +1507,6 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True, 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)'] @@ -1605,6 +1605,11 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True, data['hr_max'] = rowdatadf.ix[:,'hr_max'] data['hr_bottom'] = 0.0*data['hr'] + try: + tel = rowdatadf.ix[:,' ElapsedTime (sec)'] + except KeyError: + rowdatadf[' ElapsedTime (sec)'] = rowdatadf['TimeStamp (sec)'] + if barchart: # time increments for bar chart time_increments = rowdatadf.ix[:,' ElapsedTime (sec)'].diff() @@ -1656,18 +1661,50 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True, except KeyError: slip = 0*power - totalangle = finish-catch - effectiveangle = finish-wash-catch-slip + try: + totalangle = finish-catch + effectiveangle = finish-wash-catch-slip + except ValueError: + totalangle = 0*power + effectiveangle = 0*power + if windowsize > 3 and windowsize 3 and windowsize\d+)/$',views.team_view), url(r'^team/(?P\d+)/memberstats$',views.team_members_stats_view), diff --git a/rowers/views.py b/rowers/views.py index a640c5fa..f154a300 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -93,7 +93,7 @@ from rowers.rows import handle_uploaded_file from rowers.tasks import handle_makeplot,handle_otwsetpower,handle_sendemailtcx,handle_sendemailcsv from rowers.tasks import ( handle_sendemail_unrecognized,handle_sendemailnewcomment, - handle_sendemailnewresponse + handle_sendemailnewresponse, handle_updatedps ) from scipy.signal import savgol_filter @@ -9266,6 +9266,21 @@ def team_leaveconfirm_view(request,id=0): 'teams':get_my_teams(request.user), }) +@login_required() +def rower_calcdps_view(request): + r = getrower(request.user) + + ws = [(w.id,w.csvfilename) for w in Workout.objects.filter(user=r)] + if settings.DEBUG: + res = handle_updatedps.delay(r.user.email,ws,debug=True) + else: + queue.enqueue(handle_updatedps,r.user.email,ws,debug=False) + + messages.info(request,"Your workouts are being updated in the background. You will receive email when this is done.") + + url = reverse(workouts_view) + return HttpResponseRedirect(url) + @login_required() def team_leave_view(request,id=0): r = getrower(request.user)