diff --git a/.gitignore b/.gitignore index 332c344d..d1f4d845 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,6 @@ conftest.py # temporary test files /rowers/tests/testdata/temp /rowers/tests/testdata/testdata.csv.gz -rowers/tests/testdata/testdata.csv.gz /rowers/tests/testdata/testdata.tcx diff --git a/.ipynb_checkpoints/Untitled-checkpoint.ipynb b/.ipynb_checkpoints/Untitled-checkpoint.ipynb new file mode 100644 index 00000000..2fd64429 --- /dev/null +++ b/.ipynb_checkpoints/Untitled-checkpoint.ipynb @@ -0,0 +1,6 @@ +{ + "cells": [], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/requirements3.txt b/requirements3.txt new file mode 100644 index 00000000..65b08443 --- /dev/null +++ b/requirements3.txt @@ -0,0 +1,142 @@ +amqp==2.4.1 +arrow==0.13.1 +atomicwrites==1.3.0 +attrs==18.2.0 +backcall==0.1.0 +beautifulsoup4==4.7.1 +billiard==3.5.0.5 +bleach==3.1.0 +bokeh==1.0.4 +braintree==3.51.0 +celery==4.2.1 +certifi==2018.11.29 +chardet==3.0.4 +Click==7.0 +colorama==0.4.1 +cookies==2.2.1 +coreapi==2.3.3 +coreschema==0.0.4 +cycler==0.10.0 +dask==1.1.1 +decorator==4.3.2 +Django==1.9.5 +django-analytical==2.5.0 +django-async-messages==0.3.1 +django-braces==1.13.0 +django-classy-tags==0.8.0 +django-cookie-law==2.0.1 +django-cors-headers==2.4.0 +django-countries==5.3.3 +django-datetime-widget==0.9.3 +django-debug-toolbar==1.4 +django-extensions==2.1.6 +django-htmlmin==0.10.0 +django-leaflet==0.24.0 +django-mailbox==4.7.1 +django-oauth-toolkit==0.10.0 +django-oauth2-provider==0.2.6.1 +django-rest-framework==0.1.0 +django-rest-swagger==2.2.0 +django-rq==1.3.0 +django-rq-dashboard==0.3.3 +django-shell-plus==1.1.7 +django-social-share==1.3.2 +django-suit==0.2.26 +django-suit-rq==1.0.1 +django-tz-detect==0.2.9 +djangorestframework==3.5.3 +docopt==0.6.2 +docutils==0.14 +factory-boy==2.11.1 +Faker==1.0.2 +fitparse==1.0.1 +future==0.17.1 +geocoder==1.38.1 +holoviews==1.11.2 +html5lib==1.0.1 +htmlmin==0.1.12 +HTMLParser==0.0.2 +httplib2==0.12.1 +icalendar==4.0.3 +idna==2.8 +image==1.5.27 +importlib-resources==1.0.2 +ipython==7.3.0 +ipython-genutils==0.2.0 +iso8601==0.1.12 +isodate==0.6.0 +itypes==1.1.0 +jedi==0.13.3 +Jinja2==2.10 +kiwisolver==1.0.1 +kombu==4.3.0 +lxml==4.3.1 +Markdown==3.0.1 +MarkupSafe==1.1.1 +matplotlib==3.0.2 +MiniMockTest==0.5 +mock==2.0.0 +more-itertools==5.0.0 +mpld3==0.3 +nose==1.3.7 +nose-parameterized==0.6.0 +numpy==1.16.1 +oauth2==1.9.0.post1 +oauthlib==1.0.3 +openapi-codec==1.3.2 +packaging==19.0 +pandas==0.24.1 +param==1.8.2 +parso==0.3.4 +pathspec==0.5.9 +pbr==5.1.2 +pexpect==4.6.0 +pickleshare==0.7.5 +Pillow==5.4.1 +pluggy==0.9.0 +prompt-toolkit==2.0.9 +ptyprocess==0.6.0 +py==1.8.0 +Pygments==2.3.1 +pyparsing==2.3.1 +pytest==4.3.0 +pytest-django==3.4.7 +pytest-runner==4.4 +pytest-sugar==0.9.2 +python-dateutil==2.8.0 +python-twitter==3.5 +pytz==2018.9 +pyviz-comms==0.7.0 +PyYAML==3.13 +ratelim==0.1.6 +redis==3.2.0 +requests==2.21.0 +requests-oauthlib==1.2.0 +rowingdata==2.0.6 +rowingphysics==0.5.0 +rq==0.13.0 +scipy==1.2.1 +shell==1.0.1 +shortuuid==0.5.0 +simplejson==3.16.0 +six==1.12.0 +soupsieve==1.8 +SQLAlchemy==1.2.18 +sqlparse==0.2.4 +stravalib==0.10.2 +termcolor==1.1.0 +text-unidecode==1.2 +timezonefinder==3.4.2 +tornado==5.1.1 +tqdm==4.31.1 +traitlets==4.3.2 +units==0.7 +uritemplate==3.0.0 +urllib3==1.24.1 +VerbalExpressions==0.0.2 +vine==1.2.0 +wcwidth==0.1.7 +webencodings==0.5.1 +xmltodict==0.12.0 +yamjam==0.1.7 +yamllint==1.15.0 diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index 69827884..e5d3f049 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -20,11 +20,6 @@ from bokeh.palettes import Dark2_8 as palette import itertools from bokeh.plotting import figure, ColumnDataSource, Figure,curdoc from bokeh.models import CustomJS,Slider, TextInput,BoxAnnotation -try: - from bokeh.charts import Histogram,HeatMap,Area,BoxPlot,Bar - from bokeh.charts.attributes import CatAttr -except: - pass from bokeh.resources import CDN,INLINE from bokeh.embed import components @@ -59,6 +54,8 @@ import datetime import math import numpy as np import pandas as pd +import holoviews as hv +from holoviews import opts from pytz import timezone as tz,utc from django.utils.timezone import get_current_timezone from django.utils.timezone import activate @@ -84,17 +81,6 @@ from rowers.utils import lbstoN from rowers.datautils import p0 import rowers.datautils as datautils -watermarkurl = "/static/img/logo7.png" -watermarksource = ColumnDataSource(dict( - url = [watermarkurl],)) - -watermarkrange = Range1d(start=0,end=1) -watermarkalpha = 0.6 -watermarkx = 0.99 -watermarky = 0.01 -watermarkw = 184 -watermarkh = 35 -watermarkanchor = 'bottom_right' def errorbar(fig, x, y, source=ColumnDataSource(), xerr=False, yerr=False, color='black', @@ -203,6 +189,17 @@ def interactive_boxchart(datadf,fieldname,extratitle=''): # add watermark + watermarkurl = "/static/img/logo7.png" + watermarksource = ColumnDataSource(dict( + url = [watermarkurl],)) + + watermarkrange = Range1d(start=0,end=1) + watermarkalpha = 0.6 + watermarkx = 0.99 + watermarky = 0.01 + watermarkw = 184 + watermarkh = 35 + watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.extra_x_ranges = {"watermark": watermarkrange} @@ -246,13 +243,6 @@ def interactive_boxchart(datadf,fieldname,extratitle=''): return script,div -try: - import holoviews as hv - hv.extension('bokeh') - renderer = hv.renderer('bokeh') -except ImportError: - pass - def interactive_activitychart(workouts,startdate,enddate,stack='type'): dates = [] @@ -326,20 +316,43 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type'): df.sort_values('date_sorting',inplace=True) - - p = hv.Bars(df,values='duration', -# label = CatAttr(columns=['date'], sort=False), - xlabel='Date', - ylabel='Time', - title='Activity {d1} to {d2}'.format( + hv.extension('bokeh') + + table = hv.Table(df,[('date','Date'),('type','Workout Type')],[('duration','Duration')]) + + bars=table.to.bars(['date','type'],['duration']) + bars.opts( + opts.Bars(color=hv.Cycle('Category20'), show_legend=True, stacked=True, + tools=['hover'], width=600, xrotation=90)) + + + p = hv.render(bars) + + p.title.text = 'Activity {d1} to {d2}'.format( d1 = startdate.strftime("%Y-%m-%d"), d2 = enddate.strftime("%Y-%m-%d"), - ), - stack=stack, - plot_width=350, - plot_height=250, - toolbar_location = None, - ) + ) + p.plot_width=350 + p.plot_height=250 + p.toolbar_location = None + + +# p = hv.Bars(df,values='duration', +# label = CatAttr(columns=['date'], sort=False), +# xlabel='Date', +# ylabel='Time', +# title='Activity {d1} to {d2}'.format( +# d1 = startdate.strftime("%Y-%m-%d"), +# d2 = enddate.strftime("%Y-%m-%d"), +# ), +# stack=stack, +# plot_width=350, +# plot_height=250, +# toolbar_location = None, +# ) + + + # for legend in p.legend: @@ -359,13 +372,7 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type'): #p.yaxis.axis_label = 'Minutes' - try: - p = renderer.get_plot(p).state - script, div = components(p) - except: - script = '' - div = '' - + script,div = components(p) return script,div def interactive_forcecurve(theworkouts,workstrokesonly=False): @@ -459,6 +466,17 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False): toolbar_sticky=False) # add watermark + watermarkurl = "/static/img/logo7.png" + watermarksource = ColumnDataSource(dict( + url = [watermarkurl],)) + + watermarkrange = Range1d(start=0,end=1) + watermarkalpha = 0.6 + watermarkx = 0.99 + watermarky = 0.01 + watermarkw = 184 + watermarkh = 35 + watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.extra_x_ranges = {"watermark": watermarkrange} plot.sizing_mode = 'scale_width' @@ -769,6 +787,17 @@ def fitnessmetric_chart(fitnessmetrics,user,workoutmode='rower'): x_axis_type='datetime') # add watermark + watermarkurl = "/static/img/logo7.png" + watermarksource = ColumnDataSource(dict( + url = [watermarkurl],)) + + watermarkrange = Range1d(start=0,end=1) + watermarkalpha = 0.6 + watermarkx = 0.99 + watermarky = 0.01 + watermarkw = 184 + watermarkh = 35 + watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.extra_x_ranges = {"watermark": watermarkrange} @@ -855,6 +884,17 @@ def interactive_histoall(theworkouts): ) # add watermark + watermarkurl = "/static/img/logo7.png" + watermarksource = ColumnDataSource(dict( + url = [watermarkurl],)) + + watermarkrange = Range1d(start=0,end=1) + watermarkalpha = 0.6 + watermarkx = 0.99 + watermarky = 0.01 + watermarkw = 184 + watermarkh = 35 + watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.extra_x_ranges = {"watermark": watermarkrange} @@ -1604,6 +1644,17 @@ def interactive_otwcpchart(powerdf,promember=0,rowername=""): toolbar_sticky=False) # add watermark + watermarkurl = "/static/img/logo7.png" + watermarksource = ColumnDataSource(dict( + url = [watermarkurl],)) + + watermarkrange = Range1d(start=0,end=1) + watermarkalpha = 0.6 + watermarkx = 0.99 + watermarky = 0.01 + watermarkw = 184 + watermarkh = 35 + watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.sizing_mode = 'scale_width' @@ -1893,6 +1944,17 @@ def interactive_cpchart(rower,thedistances,thesecs,theavpower, toolbar_sticky=False) # add watermark + watermarkurl = "/static/img/logo7.png" + watermarksource = ColumnDataSource(dict( + url = [watermarkurl],)) + + watermarkrange = Range1d(start=0,end=1) + watermarkalpha = 0.6 + watermarkx = 0.99 + watermarky = 0.01 + watermarkw = 184 + watermarkh = 35 + watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.sizing_mode = 'scale_width' @@ -2200,6 +2262,17 @@ def interactive_chart(id=0,promember=0,intervaldata = {}): tools=TOOLS) # add watermark + watermarkurl = "/static/img/logo7.png" + watermarksource = ColumnDataSource(dict( + url = [watermarkurl],)) + + watermarkrange = Range1d(start=0,end=1) + watermarkalpha = 0.6 + watermarkx = 0.99 + watermarky = 0.01 + watermarkw = 184 + watermarkh = 35 + watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.extra_x_ranges = {"watermark": watermarkrange} @@ -2393,6 +2466,17 @@ def interactive_multiflex(datadf,xparam,yparam,groupby,extratitle='', toolbar_sticky=False,plot_width=920) # add watermark + watermarkurl = "/static/img/logo7.png" + watermarksource = ColumnDataSource(dict( + url = [watermarkurl],)) + + watermarkrange = Range1d(start=0,end=1) + watermarkalpha = 0.6 + watermarkx = 0.99 + watermarky = 0.01 + watermarkw = 184 + watermarkh = 35 + watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.extra_x_ranges = {"watermark": watermarkrange} @@ -2622,6 +2706,17 @@ def interactive_cum_flex_chart2(theworkouts,promember=0, toolbar_sticky=False) # add watermark + watermarkurl = "/static/img/logo7.png" + watermarksource = ColumnDataSource(dict( + url = [watermarkurl],)) + + watermarkrange = Range1d(start=0,end=1) + watermarkalpha = 0.6 + watermarkx = 0.99 + watermarky = 0.01 + watermarkw = 184 + watermarkh = 35 + watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.extra_x_ranges = {"watermark": watermarkrange} plot.sizing_mode = 'scale_width' @@ -2852,6 +2947,19 @@ def interactive_flex_chart2(id=0,promember=0, plottype='line', workstrokesonly=False): + watermarkurl = "/static/img/logo7.png" + watermarksource = ColumnDataSource(dict( + url = [watermarkurl],)) + + watermarkrange = Range1d(start=0,end=1) + watermarkalpha = 0.6 + watermarkx = 0.99 + watermarky = 0.01 + watermarkw = 184 + watermarkh = 35 + watermarkanchor = 'bottom_right' + + #rowdata,row = dataprep.getrowdata_db(id=id) columns = [xparam,yparam1,yparam2, 'ftime','distance','fpace', @@ -3041,6 +3149,17 @@ def interactive_flex_chart2(id=0,promember=0, # add watermark + watermarkurl = "/static/img/logo7.png" + watermarksource = ColumnDataSource(dict( + url = [watermarkurl],)) + + watermarkrange = Range1d(start=0,end=1) + watermarkalpha = 0.6 + watermarkx = 0.99 + watermarky = 0.01 + watermarkw = 184 + watermarkh = 35 + watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.extra_x_ranges = {"watermark": watermarkrange} plot.sizing_mode = 'scale_width' @@ -3652,6 +3771,17 @@ def interactive_bar_chart(id=0,promember=0): tools=TOOLS) # add watermark + watermarkurl = "/static/img/logo7.png" + watermarksource = ColumnDataSource(dict( + url = [watermarkurl],)) + + watermarkrange = Range1d(start=0,end=1) + watermarkalpha = 0.6 + watermarkx = 0.99 + watermarky = 0.01 + watermarkw = 184 + watermarkh = 35 + watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.extra_x_ranges = {"watermark": watermarkrange} plot.sizing_mode = 'scale_width' @@ -3821,6 +3951,17 @@ def interactive_multiple_compare_chart(ids,xparam,yparam,plottype='line', toolbar_sticky=False) # add watermark + watermarkurl = "/static/img/logo7.png" + watermarksource = ColumnDataSource(dict( + url = [watermarkurl],)) + + watermarkrange = Range1d(start=0,end=1) + watermarkalpha = 0.6 + watermarkx = 0.99 + watermarky = 0.01 + watermarkw = 184 + watermarkh = 35 + watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.extra_x_ranges = {"watermark": watermarkrange} plot.sizing_mode = 'scale_width' @@ -4073,6 +4214,17 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm', toolbar_sticky=False) # add watermark + watermarkurl = "/static/img/logo7.png" + watermarksource = ColumnDataSource(dict( + url = [watermarkurl],)) + + watermarkrange = Range1d(start=0,end=1) + watermarkalpha = 0.6 + watermarkx = 0.99 + watermarky = 0.01 + watermarkw = 184 + watermarkh = 35 + watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.extra_x_ranges = {"watermark": watermarkrange} plot.sizing_mode = 'scale_width' @@ -4204,6 +4356,17 @@ def interactive_otw_advanced_pace_chart(id=0,promember=0): toolbar_sticky=False) # add watermark + watermarkurl = "/static/img/logo7.png" + watermarksource = ColumnDataSource(dict( + url = [watermarkurl],)) + + watermarkrange = Range1d(start=0,end=1) + watermarkalpha = 0.6 + watermarkx = 0.99 + watermarky = 0.01 + watermarkw = 184 + watermarkh = 35 + watermarkanchor = 'bottom_right' plot.extra_y_ranges = {"watermark": watermarkrange} plot.extra_x_ranges = {"watermark": watermarkrange} plot.sizing_mode = 'scale_width' diff --git a/rowers/management/commands/processemail.py b/rowers/management/commands/processemail.py index 7bf213f7..ea187d00 100644 --- a/rowers/management/commands/processemail.py +++ b/rowers/management/commands/processemail.py @@ -57,7 +57,7 @@ def processattachment(rower, fileobj, title, uploadoptions,testing=False): except AttributeError: filename = fileobj[6:] if testing: - print 'Attribute Error', filename + print('Attribute Error', filename) # test if file exists and is not empty @@ -66,11 +66,11 @@ def processattachment(rower, fileobj, title, uploadoptions,testing=False): line = fop.readline() except (IOError, UnicodeEncodeError): if testing: - print 'IOError',filename,'media/'+filename + print('IOError',filename,'media/'+filename) return 0 if testing: - print 'Creating workout from email' + print('Creating workout from email') # set user if rower.user.is_staff and 'username' in uploadoptions: @@ -102,7 +102,7 @@ def processattachment(rower, fileobj, title, uploadoptions,testing=False): pass if testing: - print 'Workout id = {workoutid}'.format(workoutid=workoutid) + print('Workout id = {workoutid}'.format(workoutid=workoutid)) if workoutid[0]: link = settings.SITE_URL+reverse( @@ -242,17 +242,17 @@ class Command(BaseCommand): testing=testing ) except: - print "Bad ZIP file" - print attachment.document.name + print("Bad ZIP file") + print(attachment.document.name) else: # move attachment and make workout if testing: try: - print name + print(name) except UnicodeEncodeError: - print "Unicode Error" + print("Unicode Error") try: - print attachment.document + print(attachment.document) except UnicodeEncodeError: pass diff --git a/rowers/polarstuff.py b/rowers/polarstuff.py index 3057c59b..6e251328 100644 --- a/rowers/polarstuff.py +++ b/rowers/polarstuff.py @@ -73,8 +73,11 @@ def get_token(code): secret=POLAR_CLIENT_SECRET ) - headers = { 'Authorization': 'Basic %s' % base64.b64encode(auth_string) } - + try: + headers = { 'Authorization': 'Basic %s' % base64.b64encode(auth_string) } + except TypeError: + headers = { 'Authorization': 'Basic %s' % base64.b64encode(bytes(auth_string,'utf-8')) } + response = requests.post("https://polarremote.com/v2/oauth2/token", data=post_data, headers=headers) @@ -116,7 +119,10 @@ def get_polar_notifications(): secret=POLAR_CLIENT_SECRET ) - headers = { 'Authorization': 'Basic %s' % base64.b64encode(auth_string) } + try: + headers = { 'Authorization': 'Basic %s' % base64.b64encode(auth_string) } + except TypeError: + headers = { 'Authorization': 'Basic %s' % base64.b64encode(bytes(auth_string,'utf-8')) } response = requests.get(url, headers=headers) diff --git a/rowers/tasks.py b/rowers/tasks.py index 1b00357d..7b3ad6e9 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -1657,7 +1657,10 @@ def handle_makeplot(f1, f2, t, hrdata, plotnr, imagename, except IOError: row = rdata(f2 + '.gz', rower=rr) - haspower = row.df[' Power (watts)'].mean() > 50 + try: + haspower = row.df[' Power (watts)'].mean() > 50 + except TypeError: + haspower = True nr_rows = len(row.df) if (plotnr in [1, 2, 4, 5, 8, 11, 9, 12]) and (nr_rows > 1200): diff --git a/rowers/templates/flexchart3otw.html b/rowers/templates/flexchart3otw.html index 2eb32cf0..aa45a735 100644 --- a/rowers/templates/flexchart3otw.html +++ b/rowers/templates/flexchart3otw.html @@ -11,8 +11,8 @@ {{ js_res | safe }} {{ css_res| safe }} - - + + diff --git a/rowers/templates/list_workouts.html b/rowers/templates/list_workouts.html index b4066432..fff5afdb 100644 --- a/rowers/templates/list_workouts.html +++ b/rowers/templates/list_workouts.html @@ -59,7 +59,7 @@