diff --git a/context_processors.py b/context_processors.py index 1d6a00d6..99b93001 100644 --- a/context_processors.py +++ b/context_processors.py @@ -18,3 +18,6 @@ def hello_world(request): return { 'helloworld': 'hi Sander' } + +def warning_message(request): + return {'WARNING_MESSAGE': settings.WARNING_MESSAGE} diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 741b3787..3e145f1f 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -916,6 +916,16 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', w.startdatetime = timezone.now() w.save() + + if privacy == 'visible': + ts = Team.objects.filter(rower=r) + for t in ts: + w.team.add(t) + + # put stroke data in database + res = dataprep(row.df, id=w.id, bands=True, + barchart=True, otwpower=True, empower=True, inboard=inboard) + isbreakthrough = False ishard = False if workouttype == 'water': @@ -981,14 +991,6 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', else: pass - if privacy == 'visible': - ts = Team.objects.filter(rower=r) - for t in ts: - w.team.add(t) - - # put stroke data in database - res = dataprep(row.df, id=w.id, bands=True, - barchart=True, otwpower=True, empower=True, inboard=inboard) return (w.id, message) @@ -1150,14 +1152,6 @@ def new_workout_from_file(r, f2, a = MessageAttachment(message=msg,document=f3) a.save() -# res = myqueue( -# queuelow, -# handle_zip_file, -# r.user.email, -# title, -# f2 -# ) - return -1, message, f2 # Some people try to upload Concept2 logbook summaries @@ -1547,8 +1541,27 @@ def getrowdata_db(id=0, doclean=False, convertnewtons=True): def getsmallrowdata_db(columns, ids=[], doclean=True, workstrokesonly=True): prepmultipledata(ids) - data = read_cols_df_sql(ids, columns) + data,extracols = read_cols_df_sql(ids, columns) + if extracols and len(ids)==1: + w = Workout.objects.get(id=ids[0]) + row = rdata(w.csvfilename) + f = row.df['TimeStamp (sec)'].diff().mean() + if f != 0 and not np.isnan(f): + windowsize = 2 * (int(10. / (f))) + 1 + else: + windowsize = 1 + for c in extracols: + try: + cdata = row.df[c] + cdata.fillna(inplace=True,method='bfill') + # This doesn't work because sometimes data are duplicated at save + cdata2 = savgol_filter(cdata.values,windowsize,3) + print len(cdata),len(cdata2),'mies' + data[c] = cdata2 + except KeyError: + data[c] = 0 + # convert newtons if doclean: @@ -1622,10 +1635,15 @@ def read_cols_df_sql(ids, columns, convertnewtons=True): # axx = [ax[0] for ax in axes] axx = [f.name for f in StrokeData._meta.get_fields()] + extracols = [] + + for c in columns: if not c in axx: columns.remove(c) + extracols.append(c) + columns = list(columns) + ['distance', 'spm', 'workoutid'] columns = [x for x in columns if x != 'None'] columns = list(set(columns)) @@ -1673,7 +1691,7 @@ def read_cols_df_sql(ids, columns, convertnewtons=True): 'averageforce'] * lbstoN engine.dispose() - return df + return df,extracols # Read stroke data from the DB for a Workout ID. Returns a pandas dataframe @@ -1973,6 +1991,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, ) ) + if bands: # HR bands data['hr_ut2'] = rowdatadf.ix[:, 'hr_ut2'] @@ -2133,6 +2152,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, # write data if id given if id != 0: data['workoutid'] = id + engine = create_engine(database_url, echo=False) with engine.connect() as conn, conn.begin(): data.to_sql('strokedata', engine, if_exists='append', index=False) diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index de097e7a..7ab2256b 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -2175,13 +2175,19 @@ def interactive_flex_chart2(id=0,promember=0, except KeyError: y1mean = 0 - + rowdata['xname'] = axlabels[xparam] - rowdata['yname1'] = axlabels[yparam1] + try: + rowdata['yname1'] = axlabels[yparam1] + except KeyError: + rowdata['yname1'] = yparam1 if yparam2 != 'None': - rowdata['yname2'] = axlabels[yparam2] + try: + rowdata['yname2'] = axlabels[yparam2] + except KeyError: + rowdata['yname2'] = yparam2 else: - rowdata['yname2'] = axlabels[yparam1] + rowdata['yname2'] = rowdata['yname1'] # prepare data @@ -2281,7 +2287,12 @@ def interactive_flex_chart2(id=0,promember=0, plot.title.text_font_size=value("1.0em") plot.xaxis.axis_label = axlabels[xparam] - plot.yaxis.axis_label = axlabels[yparam1] + try: + yaxlabel = axlabels[yparam1] + except KeyError: + yaxlabel = yparam1 + + plot.yaxis.axis_label = yaxlabel @@ -2289,7 +2300,13 @@ def interactive_flex_chart2(id=0,promember=0, plot.y_range = yrange1 if (xparam != 'time') and (xparam != 'distance') and (xparam != 'cumdist'): - xrange1 = Range1d(start=yaxminima[xparam],end=yaxmaxima[xparam]) + try: + xrange1 = Range1d(start=yaxminima[xparam], + end=yaxmaxima[xparam]) + except KeyError: + xrange1 = Range1d(start=rowdata[xparam].min(), + end=rowdata[xparam].max()) + plot.x_range = xrange1 if xparam == 'time': @@ -2313,22 +2330,32 @@ def interactive_flex_chart2(id=0,promember=0, if yparam2 != 'None': - yrange2 = Range1d(start=yaxminima[yparam2],end=yaxmaxima[yparam2]) + try: + yrange2 = Range1d(start=yaxminima[yparam2], + end=yaxmaxima[yparam2]) + except KeyError: + yrange2 = Range1d(start=rowdata[yparam2].min(), + end=rowdata[yparam2].max()) + plot.extra_y_ranges["yax2"] = yrange2 #= {"yax2": yrange2} + try: + axlegend = axlabels[yparam2] + except KeyError: + axlegend = str(yparam2)+' ' if plottype=='line': plot.line('x1','y2',color="red",y_range_name="yax2", - legend=axlabels[yparam2], + legend=axlegend, source=source2) elif plottype=='scatter': - plot.scatter('x1','y2',source=source2,legend=axlabels[yparam2] - ,fill_alpha=0.4, + plot.scatter('x1','y2',source=source2,legend=axlegend, + fill_alpha=0.4, line_color=None,color="red",y_range_name="yax2") plot.add_layout(LinearAxis(y_range_name="yax2", - axis_label=axlabels[yparam2]),'right') + axis_label=axlegend),'right') y2means = Span(location=y2mean,dimension='width',line_color='red', line_dash=[6,6],line_width=2,y_range_name="yax2") @@ -2336,7 +2363,7 @@ def interactive_flex_chart2(id=0,promember=0, plot.add_layout(y2means) y2label = Label(x=100,y=70,x_units='screen',y_units='screen', - text=axlabels[yparam2]+": {y2mean:6.2f}".format(y2mean=y2mean), + text=axlegend+": {y2mean:6.2f}".format(y2mean=y2mean), background_fill_alpha=.7, background_fill_color='white', text_color='red', diff --git a/rowers/templates/flexchart3otw.html b/rowers/templates/flexchart3otw.html index c7f2517a..29934302 100644 --- a/rowers/templates/flexchart3otw.html +++ b/rowers/templates/flexchart3otw.html @@ -94,7 +94,15 @@ {% endif %} {% endfor %} {% endif %} - + {% if promember %} + {% for key, value in extrametrics.items %} + {{ value }} + {% endfor %} + {% else %} + {% for key, value in extrametrics.items %} + {{ value }} (Pro) + {% endfor %} + {% endif %} @@ -119,6 +127,15 @@ {% endif %} {% endfor %} {% endif %} + {% if promember %} + {% for key, value in extrametrics.items %} + {{ value }} + {% endfor %} + {% else %} + {% for key, value in extrametrics.items %} + {{ value }} (Pro) + {% endfor %} + {% endif %} diff --git a/rowers/urls.py b/rowers/urls.py index 0ecd420a..244a6b0d 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -363,12 +363,12 @@ urlpatterns = [ url(r'^register/thankyou/$', TemplateView.as_view(template_name='registerthankyou.html'), name='registerthankyou'), url(r'^workout/(?P\d+)/workflow$',views.workout_workflow_view, name='workout_workflow_view'), - url(r'^workout/(?P\d+)/flexchart/(?P\w+.*)/(?P\w+.*)/(?P\w+.*)/(?P\w+)/$',views.workout_flexchart3_view), - url(r'^workout/(?P\d+)/flexchart/(?P\w+.*)/(?P\w+.*)/(?P\w+.*)/(?P\w+.*)$',views.workout_flexchart3_view), - url(r'^workout/(?P\d+)/flexchart/(?P\w+.*)/(?P\w+.*)/(?P\w+.*)$',views.workout_flexchart3_view), + url(r'^workout/(?P\d+)/flexchart/(?P\w+.*)/(?P[\w\ ]+.*)/(?P[\w\ ]+.*)/(?P\w+)/$',views.workout_flexchart3_view), + url(r'^workout/(?P\d+)/flexchart/(?P\w+.*)/(?P[\w\ ]+.*)/(?P[\w\ ]+.*)/(?P\w+.*)$',views.workout_flexchart3_view), + url(r'^workout/(?P\d+)/flexchart/(?P\w+.*)/(?P[\w\ ]+.*)/(?P[\w\ ]+.*)$',views.workout_flexchart3_view), url(r'^workout/(?P\d+)/flexchart$',views.workout_flexchart3_view), - url(r'^workout/compare/(?P\d+)/(?P\d+)/(?P\w+.*)/(?P\w+.*)/(?P\w+.*)$',views.workout_comparison_view2), - url(r'^workout/compare/(?P\d+)/(?P\d+)/(?P\w+.*)/(?P\w+.*)/$',views.workout_comparison_view2), + url(r'^workout/compare/(?P\d+)/(?P\d+)/(?P\w+.*)/(?P[\w\ ]+.*)/(?P[\w\ ]+.*)$',views.workout_comparison_view2), + url(r'^workout/compare/(?P\d+)/(?P\d+)/(?P\w+.*)/(?P[\w\ ]+.*)/$',views.workout_comparison_view2), url(r'^test\_callback',views.rower_process_testcallback), url(r'^workout/(?P\d+)/test\_strokedata$',views.strokedataform), ] diff --git a/rowers/views.py b/rowers/views.py index 470ed0bd..d86d4dbe 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -6455,7 +6455,10 @@ def instroke_view(request,id=0): return HttpResponseRedirect(url) rowdata = rrdata(csvfile=row.csvfilename) - instrokemetrics = rowdata.get_instroke_columns() + try: + instrokemetrics = rowdata.get_instroke_columns() + except AttributeError: + instrokemetrics = [] return render(request, @@ -7491,7 +7494,12 @@ def workout_flexchart3_view(request,*args,**kwargs): if yparam2 == name: yparam2 = 'spm' messages.info(request,'To use '+d['verbose_name']+', you have to be Pro member') - + + # bring back slashes + yparam1 = yparam1.replace('_slsh_','/') + yparam2 = yparam2.replace('_slsh_','/') + xparam = xparam.replace('_slsh_','/') + # create interactive plot try: script,div,js_resources,css_resources,workstrokesonly = interactive_flex_chart2(id,xparam=xparam,yparam1=yparam1, @@ -7517,55 +7525,61 @@ def workout_flexchart3_view(request,*args,**kwargs): if d['mode'] == 'erg': axchoicespro.pop(name) - return render(request, - 'flexchart3otw.html', - {'the_script':script, - 'the_div':div, - 'js_res': js_resources, - 'css_res':css_resources, - 'id':int(id), - 'teams':get_my_teams(request.user), - 'xparam':xparam, - 'yparam1':yparam1, - 'yparam2':yparam2, - 'plottype':plottype, - 'favoritechartnotes':favoritechartnotes, - 'mayedit':mayedit, - 'promember':promember, - 'axchoicesbasic':axchoicesbasic, - 'axchoicespro':axchoicespro, - 'noylist':noylist, - 'workstrokesonly': not workstrokesonly, - 'favoritenr':favoritenr, - 'maxfav':maxfav, - }) else: for name,d in rowingmetrics: if d['mode'] == 'water': axchoicespro.pop(name) - - return render(request, - 'flexchart3otw.html', - {'the_script':script, - 'the_div':div, - 'js_res': js_resources, - 'css_res':css_resources, - 'teams':get_my_teams(request.user), - 'id':int(id), - 'xparam':xparam, - 'yparam1':yparam1, - 'yparam2':yparam2, - 'plottype':plottype, - 'axchoicesbasic':axchoicesbasic, - 'axchoicespro':axchoicespro, - 'favoritechartnotes':favoritechartnotes, - 'noylist':noylist, - 'mayedit':mayedit, - 'promember':promember, - 'workstrokesonly': not workstrokesonly, - 'favoritenr':favoritenr, - 'maxfav':maxfav, - }) + + + rowdata = rdata(row.csvfilename) + additionalmetrics = rowdata.get_additional_metrics() + + + extrametrics = {m.replace('/','_slsh_'):m for m in additionalmetrics} + + try: + extrametrics.pop('originalvelo') + except KeyError: + pass + + try: + extrametrics.pop('cumdist') + except KeyError: + pass + + try: + extrametrics.pop(' Cadence (strokes_slsh_min)') + except KeyError: + pass + + try: + extrametrics.pop(' WorkPerStroke (joules)') + except KeyError: + pass + + return render(request, + 'flexchart3otw.html', + {'the_script':script, + 'the_div':div, + 'js_res': js_resources, + 'css_res':css_resources, + 'teams':get_my_teams(request.user), + 'id':int(id), + 'xparam':xparam, + 'yparam1':yparam1, + 'yparam2':yparam2, + 'plottype':plottype, + 'axchoicesbasic':axchoicesbasic, + 'axchoicespro':axchoicespro, + 'extrametrics':extrametrics, + 'favoritechartnotes':favoritechartnotes, + 'noylist':noylist, + 'mayedit':mayedit, + 'promember':promember, + 'workstrokesonly': not workstrokesonly, + 'favoritenr':favoritenr, + 'maxfav':maxfav, + }) # The interactive plot with the colored Heart rate zones diff --git a/rowsandall_app/settings.py b/rowsandall_app/settings.py index f4cd50c5..c76969ca 100644 --- a/rowsandall_app/settings.py +++ b/rowsandall_app/settings.py @@ -117,6 +117,7 @@ TEMPLATES = [ 'django.contrib.messages.context_processors.messages', 'django.template.context_processors.i18n', 'context_processors.google_analytics', + 'context_processors.warning_message', ], # 'loaders': [ # 'django.template.loaders.app_directories.Loader', @@ -383,3 +384,9 @@ TWEET_ACCESS_TOKEN_SECRET = CFG['tweet_access_token_secret'] TWEET_CONSUMER_KEY = CFG['tweet_consumer_key'] TWEET_CONSUMER_SECRET = CFG['tweet_consumer_secret'] +# Environment + +try: + WARNING_MESSAGE = CFG['warning_message'] +except KeyError: + WARNING_MESSAGE = '' diff --git a/templates/basebase.html b/templates/basebase.html index ec85bb4f..deca65f2 100644 --- a/templates/basebase.html +++ b/templates/basebase.html @@ -202,6 +202,11 @@ + {% if WARNING_MESSAGE != '' %} + + {{ WARNING_MESSAGE }} + + {% endif %} {% if messages %} {% for message in messages %} {% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
+ {{ WARNING_MESSAGE }} +