From 4658e241a49ef9cc0e9bc44d64144483b55c9da7 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Tue, 16 May 2017 17:17:15 +0200 Subject: [PATCH] filtering working --- rowers/dataprep.py | 17 +++++++++++ rowers/forms.py | 12 ++++++++ rowers/interactiveplots.py | 11 +++++-- rowers/templates/boxplot.html | 49 +++++++++++++++++------------- rowers/views.py | 56 ++++++++++++++++++++++++++++++++--- 5 files changed, 118 insertions(+), 27 deletions(-) diff --git a/rowers/dataprep.py b/rowers/dataprep.py index cb226c5f..eeaa2b64 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -95,6 +95,23 @@ from scipy.signal import savgol_filter import datetime +def filter_df(datadf,fieldname,value,largerthan=True): + + try: + x = datadf[fieldname] + except KeyError: + return datadf + + if largerthan: + mask = datadf[fieldname] < value + else: + mask = datadf[fieldname] >= value + + datadf.loc[mask,fieldname] = np.nan + + + return datadf + def clean_df_stats(datadf,workstrokesonly=True,ignorehr=True, ignoreadvanced=False): # clean data remove zeros and negative values diff --git a/rowers/forms.py b/rowers/forms.py index 69b6870f..061ec014 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -300,6 +300,18 @@ parchoices = list(sorted(formaxlabels.items(), key = lambda x:x[1])) class BoxPlotChoiceForm(forms.Form): yparam = forms.ChoiceField(choices=parchoices,initial='spm', label='Metric') + spmmin = forms.FloatField(initial=15, + required=False,label = 'Min SPM') + spmmax = forms.FloatField(initial=55, + required=False,label = 'Max SPM') + workmin = forms.FloatField(initial=0, + required=False,label = 'Min Work per Stroke') + workmax = forms.FloatField(initial=1500, + required=False,label = 'Max Work per Stroke') + + includereststrokes = forms.BooleanField(initial=False, + required=False, + label='Include Rest Strokes') class ChartParamChoiceForm(forms.Form): plotchoices = ( diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index 920b4677..6315340b 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -88,12 +88,19 @@ from rowers.dataprep import nicepaceformat,niceformat from rowers.dataprep import timedeltaconv def interactive_boxchart(datadf,fieldname,extratitle=''): + + if datadf.empty: + return '','It looks like there are no data matching your filter' + TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,resize' + plot = BoxPlot(datadf, values=fieldname, label='date', legend=False, title=axlabels[fieldname]+' '+extratitle, outliers=False, tools=TOOLS, + toolbar_location="above", + toolbar_sticky=False, x_mapper_type='datetime') yrange1 = Range1d(start=yaxminima[fieldname],end=yaxmaxima[fieldname]) @@ -133,12 +140,12 @@ def interactive_boxchart(datadf,fieldname,extratitle=''): plot.xaxis.major_label_orientation = pi/4 - + script, div = components(plot) - return script,div + def interactive_forcecurve(theworkouts,workstrokesonly=False): TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' diff --git a/rowers/templates/boxplot.html b/rowers/templates/boxplot.html index 45b14144..bbb5ebd7 100644 --- a/rowers/templates/boxplot.html +++ b/rowers/templates/boxplot.html @@ -34,28 +34,35 @@ -
-

Box Chart

-
-
-
- {% csrf_token %} - - {{ chartform.as_table }} -
-
-

- -

-
-
-
- - - -
- {{ the_div|safe }} +

Box Chart

+
+
+ {{ the_div|safe }} +
+
+
+
+
+ {% csrf_token %} + + {{ chartform.as_table }} +
+
+

+ +

+
+
+
+
+

+ You can use the form above to change the metric or filter the data. + Set Min SPM and Max SPM to select only strokes in a certain range of + stroke rates. + Set Work per Stroke to a minimum value to remove "paddle" strokes or turns. +

+
diff --git a/rowers/views.py b/rowers/views.py index 82cb4450..ece0cf1e 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -3043,6 +3043,15 @@ def boxplot_view(request,userid=0, cd = form.cleaned_data workouts = cd['workouts'] plotfield = chartform.cleaned_data['yparam'] + includereststrokes = chartform.cleaned_data['includereststrokes'] + request.session['includereststrokes'] = includereststrokes + workstrokesonly = not includereststrokes + + spmmin = chartform.cleaned_data['spmmin'] + spmmax = chartform.cleaned_data['spmmax'] + workmin = chartform.cleaned_data['workmin'] + workmax = chartform.cleaned_data['workmax'] + ids = [int(w.id) for w in workouts] request.session['ids'] = ids @@ -3058,12 +3067,25 @@ def boxplot_view(request,userid=0, fieldlist,fielddict = dataprep.getstatsfields() - fieldlist = [plotfield,'workoutid'] + fieldlist = [plotfield,'workoutid','spm','driveenergy', + 'workoutstate'] # prepare data frame datadf = dataprep.read_cols_df_sql(ids,fieldlist) datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly) + + datadf = dataprep.filter_df(datadf,'spm',spmmin, + largerthan=True) + datadf = dataprep.filter_df(datadf,'spm',spmmax, + largerthan=False) + datadf = dataprep.filter_df(datadf,'driveenergy',workmin, + largerthan=True) + datadf = dataprep.filter_df(datadf,'driveneergy',workmax, + largerthan=False) + + datadf.dropna(axis=0,how='any',inplace=True) + datadf['workoutid'].replace(datemapping,inplace=True) datadf.rename(columns={"workoutid":"date"},inplace=True) datadf = datadf.sort_values(['date']) @@ -3093,6 +3115,13 @@ def boxplot_view(request,userid=0, chartform = BoxPlotChoiceForm(request.POST) if chartform.is_valid(): plotfield = chartform.cleaned_data['yparam'] + includereststrokes = chartform.cleaned_data['includereststrokes'] + spmmin = chartform.cleaned_data['spmmin'] + spmmax = chartform.cleaned_data['spmmax'] + workmin = chartform.cleaned_data['workmin'] + workmax = chartform.cleaned_data['workmax'] + request.session['includereststrokes'] = includereststrokes + workstrokesonly = not includereststrokes ids = request.session['ids'] request.session['ids'] = ids workouts = [Workout.objects.get(id=id) for id in ids] @@ -3106,12 +3135,31 @@ def boxplot_view(request,userid=0, } fieldlist,fielddict = dataprep.getstatsfields() - fieldlist = [plotfield,'workoutid'] + fieldlist = [plotfield,'workoutid','spm','driveenergy', + 'workoutstate'] # prepare data frame datadf = dataprep.read_cols_df_sql(ids,fieldlist) + + # dummy values for drive energy + mask = datadf['driveenergy'] == 0 + datadf.loc[mask,'driveenergy'] = 450 - datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly) + datadf = dataprep.clean_df_stats(datadf, + workstrokesonly=workstrokesonly) + + + datadf = dataprep.filter_df(datadf,'spm',spmmin, + largerthan=True) + datadf = dataprep.filter_df(datadf,'spm',spmmax, + largerthan=False) + datadf = dataprep.filter_df(datadf,'driveenergy',workmin, + largerthan=True) + datadf = dataprep.filter_df(datadf,'driveneergy',workmax, + largerthan=False) + + datadf.dropna(axis=0,how='any',inplace=True) + datadf['workoutid'].replace(datemapping,inplace=True) datadf.rename(columns={"workoutid":"date"},inplace=True) datadf = datadf.sort_values(['date']) @@ -3136,7 +3184,7 @@ def boxplot_view(request,userid=0, else: return HttpResponse("invalid form") else: - url = reverse(workouts_view) + url = reverse(user_boxplot_select) return HttpResponseRedirect(url) # List Workouts