Private
Public Access
1
0

initial solution to #70

This commit is contained in:
Sander Roosendaal
2019-07-24 15:23:53 +02:00
parent da6934ec0c
commit 6b9f41fca6
4 changed files with 23 additions and 8 deletions

View File

@@ -2208,6 +2208,9 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True,
else: else:
drivenergy = drivelength * averageforce drivenergy = drivelength * averageforce
powerhr = power/hr
powerhr = powerhr.fillna(value=0)
if driveenergy.mean() == 0 and driveenergy.std() == 0: if driveenergy.mean() == 0 and driveenergy.std() == 0:
driveenergy = 0*driveenergy+100 driveenergy = 0*driveenergy+100
@@ -2237,6 +2240,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True,
drivespeed=drivespeed, drivespeed=drivespeed,
rhythm=rhythm, rhythm=rhythm,
distanceperstroke=distanceperstroke, distanceperstroke=distanceperstroke,
powerhr=powerhr,
) )
) )

View File

@@ -85,6 +85,15 @@ rowingmetrics = (
'default': 0, 'default': 0,
'mode':'both', 'mode':'both',
'type':'pro'}), 'type':'pro'}),
('powerhr',{
'numtype':'float',
'null':True,
'verbose_name': 'Power Heart Rate Efficiency (J/beat)',
'ax_min':0,
'ax_max':5,
'mode':'both',
'type':'pro'}),
('spm',{ ('spm',{
'numtype':'float', 'numtype':'float',

View File

@@ -1,4 +1,4 @@
# Generated by Django 2.1.7 on 2019-04-24 20:56 # Generated by Django 2.1.7 on 2019-07-24 12:56
import datetime import datetime
from django.conf import settings from django.conf import settings
@@ -122,9 +122,9 @@ class Migration(migrations.Migration):
name='FavoriteChart', name='FavoriteChart',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('yparam1', models.CharField(choices=[('averageforce', 'Average Drive Force (N)'), ('forceratio', 'Average/Peak Force Ratio'), ('velo', 'Boat Speed (m/s)'), ('catch', 'Catch Angle (degrees)'), ('cumdist', 'Cumulative Distance (m)'), ('distance', 'Distance (m)'), ('distanceperstroke', 'Distance per Stroke (m)'), ('totalangle', 'Drive Length (deg)'), ('drivelength', 'Drive Length (m)'), ('drivespeed', 'Drive Speed (m/s)'), ('effectiveangle', 'Effective Drive Length (deg)'), ('finish', 'Finish Angle (degrees)'), ('hr', 'Heart Rate (bpm)'), ('efficiency', 'OTW Efficiency (%)'), ('pace', 'Pace (/500m)'), ('peakforce', 'Peak Drive Force (N)'), ('peakforceangle', 'Peak Force Angle'), ('power', 'Power (W)'), ('slip', 'Slip (degrees)'), ('spm', 'Stroke Rate (spm)'), ('rhythm', 'Stroke Rhythm'), ('time', 'Time'), ('wash', 'Wash (degrees)'), ('driveenergy', 'Work Per Stroke (J)')], max_length=50, verbose_name='Y1')), ('yparam1', models.CharField(choices=[('averageforce', 'Average Drive Force (N)'), ('forceratio', 'Average/Peak Force Ratio'), ('velo', 'Boat Speed (m/s)'), ('catch', 'Catch Angle (degrees)'), ('cumdist', 'Cumulative Distance (m)'), ('distance', 'Distance (m)'), ('distanceperstroke', 'Distance per Stroke (m)'), ('totalangle', 'Drive Length (deg)'), ('drivelength', 'Drive Length (m)'), ('drivespeed', 'Drive Speed (m/s)'), ('effectiveangle', 'Effective Drive Length (deg)'), ('finish', 'Finish Angle (degrees)'), ('hr', 'Heart Rate (bpm)'), ('efficiency', 'OTW Efficiency (%)'), ('pace', 'Pace (/500m)'), ('peakforce', 'Peak Drive Force (N)'), ('peakforceangle', 'Peak Force Angle'), ('power', 'Power (W)'), ('powerhr', 'Power Heart Rate Efficiency (J/beat)'), ('slip', 'Slip (degrees)'), ('spm', 'Stroke Rate (spm)'), ('rhythm', 'Stroke Rhythm'), ('time', 'Time'), ('wash', 'Wash (degrees)'), ('driveenergy', 'Work Per Stroke (J)')], max_length=50, verbose_name='Y1')),
('yparam2', models.CharField(blank=True, choices=[('None', '<None>'), ('averageforce', 'Average Drive Force (N)'), ('forceratio', 'Average/Peak Force Ratio'), ('velo', 'Boat Speed (m/s)'), ('catch', 'Catch Angle (degrees)'), ('cumdist', 'Cumulative Distance (m)'), ('distance', 'Distance (m)'), ('distanceperstroke', 'Distance per Stroke (m)'), ('totalangle', 'Drive Length (deg)'), ('drivelength', 'Drive Length (m)'), ('drivespeed', 'Drive Speed (m/s)'), ('effectiveangle', 'Effective Drive Length (deg)'), ('finish', 'Finish Angle (degrees)'), ('hr', 'Heart Rate (bpm)'), ('efficiency', 'OTW Efficiency (%)'), ('pace', 'Pace (/500m)'), ('peakforce', 'Peak Drive Force (N)'), ('peakforceangle', 'Peak Force Angle'), ('power', 'Power (W)'), ('slip', 'Slip (degrees)'), ('spm', 'Stroke Rate (spm)'), ('rhythm', 'Stroke Rhythm'), ('time', 'Time'), ('wash', 'Wash (degrees)'), ('driveenergy', 'Work Per Stroke (J)')], default='None', max_length=50, verbose_name='Y2')), ('yparam2', models.CharField(blank=True, choices=[('None', '<None>'), ('averageforce', 'Average Drive Force (N)'), ('forceratio', 'Average/Peak Force Ratio'), ('velo', 'Boat Speed (m/s)'), ('catch', 'Catch Angle (degrees)'), ('cumdist', 'Cumulative Distance (m)'), ('distance', 'Distance (m)'), ('distanceperstroke', 'Distance per Stroke (m)'), ('totalangle', 'Drive Length (deg)'), ('drivelength', 'Drive Length (m)'), ('drivespeed', 'Drive Speed (m/s)'), ('effectiveangle', 'Effective Drive Length (deg)'), ('finish', 'Finish Angle (degrees)'), ('hr', 'Heart Rate (bpm)'), ('efficiency', 'OTW Efficiency (%)'), ('pace', 'Pace (/500m)'), ('peakforce', 'Peak Drive Force (N)'), ('peakforceangle', 'Peak Force Angle'), ('power', 'Power (W)'), ('powerhr', 'Power Heart Rate Efficiency (J/beat)'), ('slip', 'Slip (degrees)'), ('spm', 'Stroke Rate (spm)'), ('rhythm', 'Stroke Rhythm'), ('time', 'Time'), ('wash', 'Wash (degrees)'), ('driveenergy', 'Work Per Stroke (J)')], default='None', max_length=50, verbose_name='Y2')),
('xparam', models.CharField(choices=[('None', '<None>'), ('averageforce', 'Average Drive Force (N)'), ('forceratio', 'Average/Peak Force Ratio'), ('velo', 'Boat Speed (m/s)'), ('catch', 'Catch Angle (degrees)'), ('cumdist', 'Cumulative Distance (m)'), ('distance', 'Distance (m)'), ('distanceperstroke', 'Distance per Stroke (m)'), ('totalangle', 'Drive Length (deg)'), ('drivelength', 'Drive Length (m)'), ('drivespeed', 'Drive Speed (m/s)'), ('effectiveangle', 'Effective Drive Length (deg)'), ('finish', 'Finish Angle (degrees)'), ('hr', 'Heart Rate (bpm)'), ('efficiency', 'OTW Efficiency (%)'), ('pace', 'Pace (/500m)'), ('peakforce', 'Peak Drive Force (N)'), ('peakforceangle', 'Peak Force Angle'), ('power', 'Power (W)'), ('slip', 'Slip (degrees)'), ('spm', 'Stroke Rate (spm)'), ('rhythm', 'Stroke Rhythm'), ('time', 'Time'), ('wash', 'Wash (degrees)'), ('driveenergy', 'Work Per Stroke (J)')], max_length=50, verbose_name='X')), ('xparam', models.CharField(choices=[('None', '<None>'), ('averageforce', 'Average Drive Force (N)'), ('forceratio', 'Average/Peak Force Ratio'), ('velo', 'Boat Speed (m/s)'), ('catch', 'Catch Angle (degrees)'), ('cumdist', 'Cumulative Distance (m)'), ('distance', 'Distance (m)'), ('distanceperstroke', 'Distance per Stroke (m)'), ('totalangle', 'Drive Length (deg)'), ('drivelength', 'Drive Length (m)'), ('drivespeed', 'Drive Speed (m/s)'), ('effectiveangle', 'Effective Drive Length (deg)'), ('finish', 'Finish Angle (degrees)'), ('hr', 'Heart Rate (bpm)'), ('efficiency', 'OTW Efficiency (%)'), ('pace', 'Pace (/500m)'), ('peakforce', 'Peak Drive Force (N)'), ('peakforceangle', 'Peak Force Angle'), ('power', 'Power (W)'), ('powerhr', 'Power Heart Rate Efficiency (J/beat)'), ('slip', 'Slip (degrees)'), ('spm', 'Stroke Rate (spm)'), ('rhythm', 'Stroke Rhythm'), ('time', 'Time'), ('wash', 'Wash (degrees)'), ('driveenergy', 'Work Per Stroke (J)')], max_length=50, verbose_name='X')),
('plottype', models.CharField(choices=[('line', 'Line Chart'), ('scatter', 'Scatter Chart')], default='line', max_length=50, verbose_name='Chart Type')), ('plottype', models.CharField(choices=[('line', 'Line Chart'), ('scatter', 'Scatter Chart')], default='line', max_length=50, verbose_name='Chart Type')),
('workouttype', models.CharField(choices=[('ote', 'Erg/SkiErg'), ('otw', 'On The Water'), ('all', 'All'), ('strava', 'strava'), ('concept2', 'concept2'), ('sporttracks', 'sporttracks'), ('runkeeper', 'runkeeper'), ('mapmyfitness', 'mapmyfitness'), ('csv', 'painsled'), ('tcx', 'tcx'), ('rp', 'rowperfect'), ('mystery', 'mystery'), ('rowperfect3', 'rowperfect3'), ('ergdata', 'ergdata'), ('boatcoach', 'boatcoach'), ('boatcoachotw', 'boatcoachotw'), ('painsleddesktop', 'painsleddesktop'), ('speedcoach', 'speedcoach'), ('speedcoach2', 'speedcoach2'), ('ergstick', 'ergstick'), ('fit', 'fit'), ('unknown', 'unknown')], default='both', max_length=50, verbose_name='Workout Type')), ('workouttype', models.CharField(choices=[('ote', 'Erg/SkiErg'), ('otw', 'On The Water'), ('all', 'All'), ('strava', 'strava'), ('concept2', 'concept2'), ('sporttracks', 'sporttracks'), ('runkeeper', 'runkeeper'), ('mapmyfitness', 'mapmyfitness'), ('csv', 'painsled'), ('tcx', 'tcx'), ('rp', 'rowperfect'), ('mystery', 'mystery'), ('rowperfect3', 'rowperfect3'), ('ergdata', 'ergdata'), ('boatcoach', 'boatcoach'), ('boatcoachotw', 'boatcoachotw'), ('painsleddesktop', 'painsleddesktop'), ('speedcoach', 'speedcoach'), ('speedcoach2', 'speedcoach2'), ('ergstick', 'ergstick'), ('fit', 'fit'), ('unknown', 'unknown')], default='both', max_length=50, verbose_name='Workout Type')),
('reststrokes', models.BooleanField(default=True, verbose_name='Incl. Rest')), ('reststrokes', models.BooleanField(default=True, verbose_name='Incl. Rest')),
@@ -192,7 +192,7 @@ class Migration(migrations.Migration):
name='PaidPlan', name='PaidPlan',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('shortname', models.CharField(choices=[('basic', 'basic'), ('pro', 'pro'), ('plan', 'plan'), ('coach', 'coach')], max_length=50)), ('shortname', models.CharField(choices=[('basic', 'basic'), ('pro', 'pro'), ('plan', 'plan'), ('coach', 'coach'), ('freecoach', 'freecoach')], max_length=50)),
('name', models.CharField(max_length=200)), ('name', models.CharField(max_length=200)),
('external_id', models.CharField(blank=True, default=None, max_length=200, null=True)), ('external_id', models.CharField(blank=True, default=None, max_length=200, null=True)),
('price', models.FloatField(blank=True, default=None, null=True)), ('price', models.FloatField(blank=True, default=None, null=True)),
@@ -268,7 +268,7 @@ class Migration(migrations.Migration):
('postal_code', models.CharField(blank=True, default='', max_length=200, null=True)), ('postal_code', models.CharField(blank=True, default='', max_length=200, null=True)),
('customer_id', models.CharField(blank=True, default=None, max_length=200, null=True)), ('customer_id', models.CharField(blank=True, default=None, max_length=200, null=True)),
('subscription_id', models.CharField(blank=True, default=None, max_length=200, null=True)), ('subscription_id', models.CharField(blank=True, default=None, max_length=200, null=True)),
('rowerplan', models.CharField(choices=[('basic', 'basic'), ('pro', 'pro'), ('plan', 'plan'), ('coach', 'coach')], default='basic', max_length=30)), ('rowerplan', models.CharField(choices=[('basic', 'basic'), ('pro', 'pro'), ('plan', 'plan'), ('coach', 'coach'), ('freecoach', 'freecoach')], default='basic', max_length=30)),
('paymenttype', models.CharField(choices=[('single', 'single'), ('recurring', 'recurring')], default='single', max_length=30, verbose_name='Payment Type')), ('paymenttype', models.CharField(choices=[('single', 'single'), ('recurring', 'recurring')], default='single', max_length=30, verbose_name='Payment Type')),
('paymentprocessor', models.CharField(blank=True, choices=[('paypal', 'PayPal'), ('braintree', 'BrainTree')], default='braintree', max_length=50, null=True)), ('paymentprocessor', models.CharField(blank=True, choices=[('paypal', 'PayPal'), ('braintree', 'BrainTree')], default='braintree', max_length=50, null=True)),
('planexpires', models.DateField(default=rowers.models.current_day)), ('planexpires', models.DateField(default=rowers.models.current_day)),
@@ -390,6 +390,7 @@ class Migration(migrations.Migration):
('hr', models.IntegerField(null=True, verbose_name='Heart Rate (bpm)')), ('hr', models.IntegerField(null=True, verbose_name='Heart Rate (bpm)')),
('pace', models.FloatField(null=True, verbose_name='Pace (/500m)')), ('pace', models.FloatField(null=True, verbose_name='Pace (/500m)')),
('velo', models.FloatField(default=0, null=True, verbose_name='Boat Speed (m/s)')), ('velo', models.FloatField(default=0, null=True, verbose_name='Boat Speed (m/s)')),
('powerhr', models.FloatField(null=True, verbose_name='Power Heart Rate Efficiency (J/beat)')),
('spm', models.FloatField(null=True, verbose_name='Stroke Rate (spm)')), ('spm', models.FloatField(null=True, verbose_name='Stroke Rate (spm)')),
('driveenergy', models.FloatField(null=True, verbose_name='Work Per Stroke (J)')), ('driveenergy', models.FloatField(null=True, verbose_name='Work Per Stroke (J)')),
('power', models.FloatField(null=True, verbose_name='Power (W)')), ('power', models.FloatField(null=True, verbose_name='Power (W)')),
@@ -568,7 +569,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(blank=True, max_length=150, null=True)), ('name', models.CharField(blank=True, max_length=150, null=True)),
('date', models.DateField()), ('date', models.DateField()),
('workouttype', models.CharField(choices=[('water', 'Standard Racing Shell'), ('rower', 'Indoor Rower'), ('skierg', 'Ski Erg'), ('bike', 'Bike Erg'), ('dynamic', 'Dynamic Indoor Rower'), ('slides', 'Indoor Rower on Slides'), ('paddle', 'Paddle Adapter'), ('snow', 'On-snow'), ('coastal', 'Coastal'), ('c-boat', 'Dutch C boat'), ('churchboat', 'Finnish Church boat'), ('Ride', 'Ride'), ('Run', 'Run'), ('NordicSki', 'NordicSki'), ('Swim', 'Swim'), ('Hike', 'Hike'), ('Walk', 'Walk'), ('Canoeing', 'Canoeing'), ('Crossfit', 'Crossfit'), ('StandUpPaddling', 'StandUpPaddling'), ('IceSkate', 'IceSkate'), ('WeightTraining', 'WeightTraining'), ('InlineSkate', 'InlineSkate'), ('Kayaking', 'Kayaking'), ('Workout', 'Workout'), ('other', 'Other')], max_length=50, verbose_name='Exercise/Boat Class')), ('workouttype', models.CharField(choices=[('water', 'Standard Racing Shell'), ('rower', 'Indoor Rower'), ('skierg', 'Ski Erg'), ('bikeerg', 'Bike Erg'), ('dynamic', 'Dynamic Indoor Rower'), ('slides', 'Indoor Rower on Slides'), ('paddle', 'Paddle Adapter'), ('snow', 'On-snow'), ('coastal', 'Coastal'), ('c-boat', 'Dutch C boat'), ('churchboat', 'Finnish Church boat'), ('Ride', 'Ride'), ('Bike', 'Bike'), ('Run', 'Run'), ('NordicSki', 'NordicSki'), ('Swim', 'Swim'), ('Hike', 'Hike'), ('Walk', 'Walk'), ('Canoeing', 'Canoeing'), ('Crossfit', 'Crossfit'), ('StandUpPaddling', 'StandUpPaddling'), ('IceSkate', 'IceSkate'), ('WeightTraining', 'WeightTraining'), ('InlineSkate', 'InlineSkate'), ('Kayaking', 'Kayaking'), ('Workout', 'Workout'), ('Yoga', 'Yoga'), ('other', 'Other')], max_length=50, verbose_name='Exercise/Boat Class')),
('workoutsource', models.CharField(default='unknown', max_length=100)), ('workoutsource', models.CharField(default='unknown', max_length=100)),
('boattype', models.CharField(choices=[('1x', '1x (single)'), ('2x', '2x (double)'), ('2x+', '2x+ (coxed double)'), ('2-', '2- (pair)'), ('2+', '2+ (coxed pair)'), ('3x+', '3x+ (coxed triple)'), ('3x-', '3x- (triple)'), ('4x', '4x (quad)'), ('4x+', '4x+ (coxed quad)'), ('4-', '4- (four)'), ('4+', '4+ (coxed four)'), ('8+', '8+ (eight)'), ('8x+', '8x+ (octuple scull)')], default='1x', max_length=50, verbose_name='Boat Type')), ('boattype', models.CharField(choices=[('1x', '1x (single)'), ('2x', '2x (double)'), ('2x+', '2x+ (coxed double)'), ('2-', '2- (pair)'), ('2+', '2+ (coxed pair)'), ('3x+', '3x+ (coxed triple)'), ('3x-', '3x- (triple)'), ('4x', '4x (quad)'), ('4x+', '4x+ (coxed quad)'), ('4-', '4- (four)'), ('4+', '4+ (coxed four)'), ('8+', '8+ (eight)'), ('8x+', '8x+ (octuple scull)')], default='1x', max_length=50, verbose_name='Boat Type')),
('adaptiveclass', models.CharField(choices=[('None', 'None'), ('PR1', 'PR1 (Arms and Shoulders)'), ('PR2', 'PR2 (Trunk and Arms)'), ('PR3', 'PR3 (Leg Trunk and Arms)'), ('FES', 'FES (Functional Electrical Stimulation)')], default='None', max_length=50, verbose_name='Adaptive Classification')), ('adaptiveclass', models.CharField(choices=[('None', 'None'), ('PR1', 'PR1 (Arms and Shoulders)'), ('PR2', 'PR2 (Trunk and Arms)'), ('PR3', 'PR3 (Leg Trunk and Arms)'), ('FES', 'FES (Functional Electrical Stimulation)')], default='None', max_length=50, verbose_name='Adaptive Classification')),

View File

@@ -2908,8 +2908,9 @@ class Meta:
index_together = ['workoutid'] index_together = ['workoutid']
app_label = 'rowers' app_label = 'rowers'
attrs = {'__module__': '', 'Meta': Meta} attrs = {'__module__': 'rowers.models', 'Meta': Meta}
attrs.update(strokedatafields) attrs.update(strokedatafields)
# Model of StrokeData table # Model of StrokeData table
# the definition here is used only to enable easy Django migration # the definition here is used only to enable easy Django migration