diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 1891625b..e51e6631 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -26,7 +26,7 @@ from rowingdata import ( MysteryParser, BoatCoachOTWParser, painsledDesktopParser, speedcoachParser, ErgStickParser, SpeedCoach2Parser, FITParser, fitsummarydata, - make_cumvalues, + make_cumvalues,cumcpdata, summarydata, get_file_type, ) @@ -41,7 +41,7 @@ import itertools import math from tasks import ( handle_sendemail_unrecognized, handle_sendemail_breakthrough, - handle_sendemail_hard, handle_updatecp + handle_sendemail_hard, handle_updatecp,handle_updateergcp ) from django.conf import settings @@ -426,20 +426,22 @@ def paceformatsecs(values): return out -def getcpdata_sql(rower_id): +def getcpdata_sql(rower_id,table='cpdata'): engine = create_engine(database_url, echo=False) - query = sa.text('SELECT delta,cp from cpdata WHERE user={rower_id};'.format( - rower_id=rower_id + query = sa.text('SELECT * from {table} WHERE user={rower_id};'.format( + rower_id=rower_id, + table=table, )) connection = engine.raw_connection() df = pd.read_sql_query(query, engine) return df -def deletecpdata_sql(rower_id): +def deletecpdata_sql(rower_id,table='cpdata'): engine = create_engine(database_url, echo=False) - query = sa.text('DELETE from cpdata WHERE user={rower_id};'.format( - rower_id=rower_id + query = sa.text('DELETE from {table} WHERE user={rower_id};'.format( + rower_id=rower_id, + table=table, )) with engine.connect() as conn, conn.begin(): try: @@ -451,7 +453,7 @@ def deletecpdata_sql(rower_id): -def updatecpdata_sql(rower_id,delta,cp): +def updatecpdata_sql(rower_id,delta,cp,table='cpdata',distance=[]): deletecpdata_sql(rower_id) df = pd.DataFrame( { @@ -461,9 +463,12 @@ def updatecpdata_sql(rower_id,delta,cp): } ) + if not distance.empty: + df['distance'] = distance + engine = create_engine(database_url, echo=False) with engine.connect() as conn, conn.begin(): - df.to_sql('cpdata', engine, if_exists='append', index=False) + df.to_sql(table, engine, if_exists='append', index=False) conn.close() engine.dispose() @@ -484,7 +489,19 @@ def runcpupdate(rower): else: res = queue.enqueue(handle_updatecp,rower.id,theids) - +def fetchcperg(rower,theworkouts): + theids = [int(w.id) for w in theworkouts] + thefilenames = [w.csvfilename for w in theworkouts] + cpdf = getcpdata_sql(rower.id,table='ergcpdata') + + if settings.DEBUG: + res = handle_updateergcp.delay(rower.id,thefilenames,debug=True) + else: + res = queue.enqueue(handle_updateergcp,rower.id,thefilenames) + + return cpdf + + def fetchcp(rower,theworkouts): # get all power data from database (plus workoutid) theids = [int(w.id) for w in theworkouts] diff --git a/rowers/dataprepnodjango.py b/rowers/dataprepnodjango.py index 67ded4e6..767ace9f 100644 --- a/rowers/dataprepnodjango.py +++ b/rowers/dataprepnodjango.py @@ -548,14 +548,30 @@ def read_df_sql(id,debug=False): engine.dispose() return df -def deletecpdata_sql(rower_id,debug=False): +def getcpdata_sql(rower_id,table='cpdata',debug=False): if debug: engine = create_engine(database_url_debug, echo=False) else: engine = create_engine(database_url, echo=False) - query = sa.text('DELETE from cpdata WHERE user={rower_id};'.format( - rower_id=rower_id + query = sa.text('SELECT * from {table} WHERE user={rower_id};'.format( + rower_id=rower_id, + table=table, + )) + connection = engine.raw_connection() + df = pd.read_sql_query(query, engine) + + return df + +def deletecpdata_sql(rower_id,table='cpdata',debug=False): + if debug: + engine = create_engine(database_url_debug, echo=False) + else: + engine = create_engine(database_url, echo=False) + + query = sa.text('DELETE from {table} WHERE user={rower_id};'.format( + rower_id=rower_id, + table=table, )) with engine.connect() as conn, conn.begin(): try: @@ -567,8 +583,8 @@ def deletecpdata_sql(rower_id,debug=False): -def updatecpdata_sql(rower_id,delta,cp,debug=False): - deletecpdata_sql(rower_id,debug=debug) +def updatecpdata_sql(rower_id,delta,cp,table='cpdata',distance=pd.Series([]),debug=False): + deletecpdata_sql(rower_id,table=table,debug=debug) df = pd.DataFrame( { 'delta':delta, @@ -577,17 +593,22 @@ def updatecpdata_sql(rower_id,delta,cp,debug=False): } ) + if not distance.empty: + df['distance'] = distance + if debug: engine = create_engine(database_url_debug, echo=False) else: engine = create_engine(database_url, echo=False) with engine.connect() as conn, conn.begin(): - df.to_sql('cpdata', engine, if_exists='append', index=False) + df.to_sql(table, engine, if_exists='append', index=False) conn.close() engine.dispose() + + def smalldataprep(therows,xparam,yparam1,yparam2): diff --git a/rowers/forms.py b/rowers/forms.py index 6980dafe..4923a517 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -188,7 +188,7 @@ class UploadOptionsForm(forms.Form): landingpage = forms.ChoiceField(choices=nextpages, initial='workout_edit_view', - label='Landing Page') + label='After Upload, go to') class Meta: fields = ['make_plot','plottype','upload_toc2','makeprivate'] diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index dff5c227..982d1918 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -41,6 +41,7 @@ import pandas as pd from pytz import timezone as tz,utc from django.utils.timezone import get_current_timezone from django.utils.timezone import activate +from django.utils import timezone activate(settings.TIME_ZONE) thetimezone = get_current_timezone() @@ -1065,10 +1066,9 @@ def interactive_otwcpchart(powerdf,promember=0): return [script,div,p1,ratio,message] -def interactive_cpchart(thedistances,thesecs,theavpower, +def interactive_cpchart(rower,thedistances,thesecs,theavpower, theworkouts,promember=0): - message = 0 # plot tools if (promember==1): @@ -1086,7 +1086,7 @@ def interactive_cpchart(thedistances,thesecs,theavpower, p = pd.Series(500./velo) p2 = p.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - + source = ColumnDataSource( data = dict( dist = thedistances, @@ -1108,6 +1108,7 @@ def interactive_cpchart(thedistances,thesecs,theavpower, paulslope = 5.0/np.log10(2.0) paulintercept = p[0]-paulslope*np.log10(thedistances[0]) + fitx = pd.Series(np.arange(100)*2*max(np.log10(thedistances))/100.) fitp = paulslope*fitx+paulintercept @@ -1198,16 +1199,13 @@ def interactive_cpchart(thedistances,thesecs,theavpower, plot.xaxis.axis_label = "Duration (seconds)" plot.yaxis.axis_label = "Power (W)" - therows = [] - for workout in theworkouts: - f1 = workout.csvfilename - rowdata = rdata(f1) - if rowdata != 0: - therows.append(rowdata) - cpdata = cumcpdata(therows) + cpdata = dataprep.fetchcperg(rower, theworkouts) - velo = cpdata['Distance']/cpdata['Delta'] + if cpdata.empty: + return ['','',paulslope,paulintercept,p1,message] + + velo = cpdata['distance']/cpdata['delta'] p = 500./velo @@ -1215,12 +1213,12 @@ def interactive_cpchart(thedistances,thesecs,theavpower, source2 = ColumnDataSource( data = dict( - duration = cpdata['Delta'], - power = cpdata['CP'], + duration = cpdata['delta'], + power = cpdata['cp'], tim = niceformat( - cpdata['Delta'].fillna(method='ffill').apply(lambda x: timedeltaconv(x)) + cpdata['delta'].fillna(method='ffill').apply(lambda x: timedeltaconv(x)) ), - dist = cpdata['Distance'], + dist = cpdata['distance'], pace = nicepaceformat(p2), ) ) @@ -1252,6 +1250,7 @@ def interactive_cpchart(thedistances,thesecs,theavpower, script, div = components(plot) + return [script,div,paulslope,paulintercept,p1,message] def interactive_windchart(id=0,promember=0): diff --git a/rowers/models.py b/rowers/models.py index 2c84d272..1b233404 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -653,6 +653,18 @@ class cpdata(models.Model): index_together = ['user'] app_label = 'rowers' +# Storing data for the OTW CP chart +class ergcpdata(models.Model): + delta = models.IntegerField(default=0) + cp = models.FloatField(default=0) + distance = models.FloatField(default=0) + user = models.IntegerField(default=0) + + class Meta: + db_table = 'ergcpdata' + index_together = ['user'] + app_label = 'rowers' + # A wrapper around the png files class GraphImage(models.Model): filename = models.CharField(default='',max_length=150,blank=True,null=True) diff --git a/rowers/tasks.py b/rowers/tasks.py index 9ffe5da8..372dc1cb 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -400,7 +400,24 @@ def handle_otwsetpower(f1, boattype, weightvalue, return 1 -# This function generates all the static (PNG image) plots + +@app.task +def handle_updateergcp(rower_id,workoutfilenames,debug=False): + therows = [] + for f1 in workoutfilenames: + rowdata = rdata(f1) + if rowdata != 0: + therows.append(rowdata) + + cpdata = rowingdata.cumcpdata(therows) + cpdata.columns = cpdata.columns.str.lower() + + updatecpdata_sql(rower_id,cpdata['delta'],cpdata['cp'], + table='ergcpdata',distance=cpdata['distance'], + debug=debug) + + return 1 + @app.task def handle_updatecp(rower_id,workoutids,debug=False): diff --git a/rowers/views.py b/rowers/views.py index 346c35ab..cbeacc7d 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -2787,8 +2787,10 @@ def rankings_view(request,theuser=0, # create interactive plot if len(thedistances) !=0 : - res = interactive_cpchart(thedistances,thesecs,theavpower, - theworkouts,promember=promember) + res = interactive_cpchart( + r,thedistances,thesecs,theavpower, + theworkouts,promember=promember + ) script = res[0] div = res[1] paulslope = res[2] diff --git a/static/img/coxmate1a.gif b/static/img/coxmate1a.gif deleted file mode 100644 index 51e68fd6..00000000 Binary files a/static/img/coxmate1a.gif and /dev/null differ