diff --git a/rowers/forms.py b/rowers/forms.py index ff61a245..30c6836b 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -25,6 +25,12 @@ import datetime from django.forms import formset_factory from rowers.utils import landingpages from rowers.metrics import axes +from rowers.metrics import axlabels + +formaxlabels = axlabels.copy() +formaxlabels.pop('None') +parchoices = list(sorted(formaxlabels.items(), key = lambda x:x[1])) + class FlexibleDecimalField(forms.DecimalField): @@ -710,6 +716,12 @@ class DataFrameColumnsForm(forms.Form): cols = forms.MultipleChoiceField(choices=colchoices, label='Table Columns') +class HistoForm(forms.Form): + includereststrokes = forms.BooleanField(initial=False,label='Include Rest Strokes',required=False) + histoparam = forms.ChoiceField(choices=parchoices,initial='power', + label='Metric') + + # form to select modality and boat type for trend flex class TrendFlexModalForm(forms.Form): modality = forms.ChoiceField(choices=workouttypes, @@ -797,12 +809,6 @@ class PlannedSessionMultipleCloneForm(forms.Form): label='Planned Sessions' ) -from rowers.metrics import axlabels - -formaxlabels = axlabels.copy() -formaxlabels.pop('None') -parchoices = list(sorted(formaxlabels.items(), key = lambda x:x[1])) - class BoxPlotChoiceForm(forms.Form): yparam = forms.ChoiceField(choices=parchoices,initial='spm', diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index e1207fb6..141bc9f0 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -1214,12 +1214,13 @@ def fitnessmetric_chart(fitnessmetrics,user,workoutmode='rower',startdate=None, return [script,div] -def interactive_histoall(theworkouts): +def interactive_histoall(theworkouts,histoparam,includereststrokes): TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair' ids = [int(w.id) for w in theworkouts] - rowdata = dataprep.getsmallrowdata_db(['power'],ids=ids,doclean=True) + workstrokesonly = not includereststrokes + rowdata = dataprep.getsmallrowdata_db([histoparam],ids=ids,doclean=True,workstrokesonly=workstrokesonly) rowdata.dropna(axis=0,how='any',inplace=True) @@ -1227,16 +1228,16 @@ def interactive_histoall(theworkouts): return "","No Valid Data Available","","" try: - histopwr = rowdata['power'].values + histopwr = rowdata[histoparam].values except KeyError: - return "","No power data","","" + return "","No data","","" if len(histopwr) == 0: return "","No valid data available","","" # throw out nans histopwr = histopwr[~np.isinf(histopwr)] - histopwr = histopwr[histopwr > 25] - histopwr = histopwr[histopwr < 1000] + histopwr = histopwr[histopwr > yaxminima[histoparam]] + histopwr = histopwr[histopwr < yaxmaxima[histoparam]] plot = Figure(tools=TOOLS,plot_width=900, toolbar_sticky=False, @@ -1289,7 +1290,7 @@ def interactive_histoall(theworkouts): # plot.quad(top='hist_norm',bottom=0,left=edges[:-1],right=edges[1:]) plot.quad(top='hist_norm',bottom=0,left='left',right='right',source=source) - plot.xaxis.axis_label = "Power (W)" + plot.xaxis.axis_label = axlabels[histoparam] plot.yaxis.axis_label = "% of strokes" plot.y_range = Range1d(0,1.05*max(hist_norm)) @@ -1297,7 +1298,7 @@ def interactive_histoall(theworkouts): hover = plot.select(dict(type=HoverTool)) hover.tooltips = OrderedDict([ - ('Power(W)','@left{int}'), + (axlabels[histoparam],'@left{int}'), ('% of strokes','@hist_norm'), ('Cumulative %','@histsum{int}'), ]) @@ -1311,12 +1312,36 @@ def interactive_histoall(theworkouts): axis_label="Cumulative % of strokes"),'right') plot.sizing_mode = 'scale_width' + + annolabel = Label(x=50,y=450,x_units='screen',y_units='screen', + text='', + background_fill_alpha=0.7, + background_fill_color='white', + text_color='black', + ) + + plot.add_layout(annolabel) + + callback = CustomJS(args = dict( + annolabel=annolabel, + ), code=""" + var annotation = annotation.value + annolabel.text = annotation + """) + + annotation = TextInput(title="Type your plot notes here", value="", + callback=callback) + callback.args["annotation"] = annotation + + layout = layoutcolumn([annotation,plot]) + try: - script, div = components(plot) + script, div = components(layout) except ValueError: script = '' div = '' - + + return [script,div] def course_map(course): @@ -3889,7 +3914,7 @@ def interactive_flex_chart2(id=0,promember=0, """) annotation = TextInput(title="Type your plot notes here", value="", - callback=callback) + callback=callback) callback.args["annotation"] = annotation slider_spm_min = Slider(start=15.0, end=55,value=15.0, step=.1, diff --git a/rowers/templates/analysis.html b/rowers/templates/analysis.html index d598c144..aca799ec 100644 --- a/rowers/templates/analysis.html +++ b/rowers/templates/analysis.html @@ -40,14 +40,14 @@

  • -

    Power Histogram

    +

    Histogram

    Power Histogram

    - Plot a power histogram of all your strokes over a date range. + Plot a histogram chart of one metric for all your strokes over a date range.

  • diff --git a/rowers/templates/histo.html b/rowers/templates/histo.html index b7b2d7d2..4e200c2d 100644 --- a/rowers/templates/histo.html +++ b/rowers/templates/histo.html @@ -75,6 +75,8 @@ +

    Histogram View

    +
    • @@ -100,6 +102,11 @@ {{ form.as_table }}
    • +
    • + + {{ histoform.as_table }} +
      +
    • {% csrf_token %} diff --git a/rowers/templates/menu_analytics.html b/rowers/templates/menu_analytics.html index 24b99117..bb9078ba 100644 --- a/rowers/templates/menu_analytics.html +++ b/rowers/templates/menu_analytics.html @@ -62,9 +62,9 @@  Statistics
    • -
    • +
    • -  Power Histogram +  Histogram
    diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py index a5f815e2..d367301e 100644 --- a/rowers/views/analysisviews.py +++ b/rowers/views/analysisviews.py @@ -20,11 +20,17 @@ def histo(request,theuser=0, 'workouttypes':[i[0] for i in mytypes.workouttypes], 'waterboattype':mytypes.waterboattype, 'rankingonly': False, + 'histoparam':'power' }): r = getrequestrower(request,userid=theuser) theuser = r.user - + + if 'histoparam' in request.session: + histoparam = request.session['histoparam'] + else: + histoparam = 'power' + if 'waterboattype' in request.session: waterboattype = request.session['waterboattype'] else: @@ -81,6 +87,7 @@ def histo(request,theuser=0, if request.method == 'POST': form = DateRangeForm(request.POST) modalityform = TrendFlexModalForm(request.POST) + histoform = HistoForm(request.POST) if form.is_valid(): startdate = form.cleaned_data['startdate'] enddate = form.cleaned_data['enddate'] @@ -110,6 +117,11 @@ def histo(request,theuser=0, 'startdate': startdate, 'enddate': enddate, }) + if histoform.is_valid(): + includereststrokes = histoform.cleaned_data['includereststrokes'] + histoparam = histoform.cleaned_data['histoparam'] + request.session['histoparam'] = histoparam + request.session['includereststrokes'] = includereststrokes else: form = DateRangeForm(initial={ 'startdate': startdate, @@ -125,6 +137,10 @@ def histo(request,theuser=0, 'rankingonly':rankingonly, } ) + histoform = HistoForm(initial={ + 'includereststrokes':False, + 'histoparam':histoparam + }) negtypes = [] for b in mytypes.boattypes: @@ -149,6 +165,7 @@ def histo(request,theuser=0, 'enddatestring':enddatestring, 'rankingonly':rankingonly, 'includereststrokes':includereststrokes, + 'histoparam':histoparam, } request.session['options'] = options @@ -163,9 +180,21 @@ def histo(request,theuser=0, request.session['options'] = options + breadcrumbs = [ + { + 'url':'/rowers/analysis', + 'name':'Analysis' + }, + { + 'url':reverse('histo'), + 'name': 'Histogram' + } + ] + return render(request, 'histo.html', {'interactiveplot':script, 'the_div':div, + 'breadcrumbs':breadcrumbs, 'id':theuser, 'active':'nav-analysis', 'theuser':theuser, @@ -174,6 +203,7 @@ def histo(request,theuser=0, 'enddate':enddate, 'form':form, 'optionsform':modalityform, + 'histoform':histoform, 'teams':get_my_teams(request.user), }) @@ -295,6 +325,7 @@ def histo_data( 'enddatestring':timezone.now().strftime("%Y-%m-%d"), 'startdatestring':(timezone.now()-datetime.timedelta(days=30)).strftime("%Y-%m-%d"), 'deltadays':-1, + 'histoparam':'power', }): def_options = options @@ -311,6 +342,7 @@ def histo_data( theuser = keyvalue_get_default('theuser',options,def_options) startdatestring = keyvalue_get_default('startdatestring',options,def_options) enddatestring = keyvalue_get_default('enddatestring',options,def_options) + histoparam = keyvalue_get_default('histoparam',options,def_options) if modality == 'all': modalities = [m[0] for m in mytypes.workouttypes] @@ -358,7 +390,7 @@ def histo_data( rankingpiece__in=rankingpiece) if allworkouts: - res = interactive_histoall(allworkouts) + res = interactive_histoall(allworkouts,histoparam,includereststrokes) script = res[0] div = res[1] else: diff --git a/rowers/views/statements.py b/rowers/views/statements.py index 2179bebb..b9eb4985 100644 --- a/rowers/views/statements.py +++ b/rowers/views/statements.py @@ -48,7 +48,7 @@ from django.http import ( ) from django.contrib.auth import authenticate, login, logout from rowers.forms import ( - ForceCurveOptionsForm, + ForceCurveOptionsForm,HistoForm, LoginForm,DocumentsForm,UploadOptionsForm,ImageForm,CourseForm, TeamUploadOptionsForm,WorkFlowLeftPanelForm,WorkFlowMiddlePanelForm, WorkFlowLeftPanelElement,WorkFlowMiddlePanelElement,