diff --git a/rowers/dataprep.py b/rowers/dataprep.py index b3834f16..a68f05c6 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -96,7 +96,7 @@ queuelow = django_rq.get_queue('low') queuehigh = django_rq.get_queue('default') from rowsandall_app.settings import SITE_URL -from rowers.mytypes import otwtypes,otetypes +from rowers.mytypes import otwtypes,otetypes,rowtypes from rowers import mytypes from rowers.database import * @@ -1016,6 +1016,53 @@ def fetchcperg(rower,theworkouts): return cpdf +def fetchcp_new(rower,workouts): + + data = [] + for workout in workouts: + cpfile = 'media/cpdata_{id}.parquet.gz'.format(id=workout.id) + try: + df = pd.read_parquet(cpfile) + data.append(df) + except OSError: + # CP data file doesn't exist yet. has to be created + strokesdf = getsmallrowdata_db(['power','workoutid','time'],ids = [workout.id]) + if not strokesdf.empty: + totaltime = strokesdf['time'].max() + try: + powermean = strokesdf['power'].mean() + except KeyError: + powermean = 0 + + if powermean != 0: + thesecs = totaltime + maxt = 1.05 * thesecs + + if maxt > 0: + logarr = datautils.getlogarr(maxt) + dfgrouped = strokesdf.groupby(['workoutid']) + delta, cpvalues, avgpower = datautils.getcp(dfgrouped, logarr) + filename = 'media/cpdata_{id}.parquet.gz'.format(id=workout.id) + df = pd.DataFrame({ + 'delta':delta, + 'cp':cpvalues, + 'id':workout.id, + }) + df.to_parquet(filename,engine='fastparquet',compression='GZIP') + data.append(df) + + + if len(data) == 0: + return pd.Series(),pd.Series(),0 + if len(data)>1: + df = pd.concat(data,axis=0) + + df = df.groupby(['delta']).max() + + + df = df.sort_values(['delta']).reset_index() + + return df['delta'],df['cp'],0 def fetchcp(rower,theworkouts,table='cpdata'): # get all power data from database (plus workoutid) @@ -1434,7 +1481,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', isbreakthrough = False ishard = False - if workouttype == 'water': + if workouttype in rowtypes: df = getsmallrowdata_db(['power', 'workoutid', 'time'], ids=[w.id]) try: powermean = df['power'].mean() @@ -1448,15 +1495,26 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', logarr = datautils.getlogarr(maxt) dfgrouped = df.groupby(['workoutid']) delta, cpvalues, avgpower = datautils.getcp(dfgrouped, logarr) + filename = 'media/cpdata_{id}.parquet.gz'.format(id=w.id) + cpdf = pd.DataFrame({ + 'delta':delta, + 'cp':cpvalues, + 'id':w.id, + }) + cpdf.to_parquet(filename,engine='fastparquet',compression='GZIP') - res, btvalues, res2 = utils.isbreakthrough( - delta, cpvalues, r.p0, r.p1, r.p2, r.p3, r.cpratio) + if workouttype in otwtypes: + res, btvalues, res2 = utils.isbreakthrough( + delta, cpvalues, r.p0, r.p1, r.p2, r.p3, r.cpratio) + elif workouttype in otetypes: + res, btvalues, res2 = utils.isbreakthrough( + delta, cpvalues, r.ep0, r.ep1, r.ep2, r.ep3, r.ecpratio) else: res = 0 res2 = 0 if res: isbreakthrough = True - res = datautils.updatecp(delta, cpvalues, r) + res = datautils.updatecp(delta, cpvalues, r,workouttype=workouttype) if res2 and not isbreakthrough: ishard = True diff --git a/rowers/datautils.py b/rowers/datautils.py index 10f5cd13..554ea19e 100644 --- a/rowers/datautils.py +++ b/rowers/datautils.py @@ -8,12 +8,24 @@ import numpy as np from scipy.interpolate import griddata from scipy import optimize +from rowers.mytypes import otwtypes,otetypes,rowtypes + #p0 = [500,350,10,8000] p0 = [190,200,33,16000] -def updatecp(delta,cpvalues,r): - cp2 = r.p0/(1+delta/r.p2) - cp2 += r.p1/(1+delta/r.p3) +def updatecp(delta,cpvalues,r,workouttype='water'): + if workouttype in otwtypes: + p0 = r.p0 + p1 = r.p1 + p2 = r.p2 + p3 = r.p3 + else: + p0 = r.ep0 + p1 = r.ep1 + p2 = r.ep2 + p3 = r.ep3 + cp2 = p0/(1+delta/p2) + cp2 += p1/(1+delta/p3) delta = delta.append(delta) cp = cpvalues.append(cp2) @@ -31,11 +43,18 @@ def updatecp(delta,cpvalues,r): res = cpfit(powerdf) p1 = res[0] - r.p0 = p1[0] - r.p1 = p1[1] - r.p2 = p1[2] - r.p3 = p1[3] - r.cpratio = res[3] + if workouttype in otwtypes: + r.p0 = p1[0] + r.p1 = p1[1] + r.p2 = p1[2] + r.p3 = p1[3] + r.cpratio = res[3] + else: + r.ep0 = p1[0] + r.ep1 = p1[1] + r.ep2 = p1[2] + r.ep3 = p1[3] + r.ecpratio = res[3] r.save() @@ -89,7 +108,10 @@ def cpfit(powerdf): def getlogarr(maxt): maxlog10 = np.log10(maxt-5) - logarr = np.arange(50)*maxlog10/50. + #print(maxlog10,round(maxlog10)) + aantal = 10*round(maxlog10) + logarr = np.arange(aantal+1)/10. + res = [] for la in logarr: try: diff --git a/rowers/forms.py b/rowers/forms.py index 02ded6af..3bfbe8ce 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -1036,7 +1036,7 @@ analysischoices = ( ('flexall','Cumulative Flex Chart'), ('stats','Statistics'), ('compare','Compare'), - ('cp','CP Chart') + ('cp','CP chart'), ) diff --git a/rowers/models.py b/rowers/models.py index c302b3ad..9e5bc625 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -2985,6 +2985,13 @@ def auto_delete_file_on_delete(sender, instance, **kwargs): except FileNotFoundError: pass + # remove parquet file + try: + dirname = 'media/cpdata_{id}.parquet.gz'.format(id=instance.id) + os.remove(dirname) + except FileNotFoundError: + pass + @receiver(models.signals.post_delete,sender=Workout) def update_duplicates_on_delete(sender, instance, **kwargs): if instance.id: diff --git a/rowers/templates/user_analysis_select.html b/rowers/templates/user_analysis_select.html index 3b71d66b..37974888 100644 --- a/rowers/templates/user_analysis_select.html +++ b/rowers/templates/user_analysis_select.html @@ -2,7 +2,7 @@ {% load staticfiles %} {% load rowerfilters %} -{% block title %}Workouts{% endblock %} +{% block title %}Analysis{% endblock %} {% block main %}
@@ -285,9 +316,9 @@
- + {% if workouts %} - + Toggle All
{{ form.as_table }} diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py index 8e780e81..43b2563b 100644 --- a/rowers/views/analysisviews.py +++ b/rowers/views/analysisviews.py @@ -500,6 +500,60 @@ def histodata(workouts, options): return(script,div) +def cpdata(workouts, options): + userid = options['userid'] + + + u = User.objects.get(id=userid) + r = u.rower + + + ids = [w.id for w in workouts] + delta, cpvalue, avgpower = dataprep.fetchcp_new(r,workouts) + powerdf = pd.DataFrame({ + 'Delta':delta, + 'CP':cpvalue, + }) + + + if powerdf.empty: + return('','

No valid data found

') + + powerdf = powerdf[powerdf['CP']>0] + powerdf.dropna(axis=0,inplace=True) + powerdf.sort_values(['Delta','CP'],ascending=[1,0],inplace=True) + powerdf.drop_duplicates(subset='Delta',keep='first',inplace=True) + + rowername = r.user.first_name+" "+r.user.last_name + + if len(powerdf) !=0 : + res = interactive_otwcpchart(powerdf,promember=True,rowername=rowername) + script = res[0] + div = res[1] + p1 = res[2] + ratio = res[3] + r.p0 = p1[0] + r.p1 = p1[1] + r.p2 = p1[2] + r.p3 = p1[3] + r.cpratio = ratio + r.save() + paulslope = 1 + paulintercept = 1 + message = res[4] + else: + script = '' + div = '

No ranking pieces found.

' + paulslope = 1 + paulintercept = 1 + p1 = [1,1,1,1] + message = "" + + scripta = script.split('\n')[2:-1] + script = ''.join(scripta) + + return (script,div) + def statsdata(workouts, options): includereststrokes = options['includereststrokes'] spmmin = options['spmmin'] @@ -726,7 +780,7 @@ def analysis_view_data(request,userid=0): elif function == 'compare': script,div = comparisondata(workouts,options) elif function == 'cp': - script, div = cpdata(workouts,options) + script, div = cpdata(workouts, options) else: script = '' div = 'Unknown analysis functions'