fix #459
This commit is contained in:
@@ -25,6 +25,12 @@ import datetime
|
|||||||
from django.forms import formset_factory
|
from django.forms import formset_factory
|
||||||
from rowers.utils import landingpages
|
from rowers.utils import landingpages
|
||||||
from rowers.metrics import axes
|
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):
|
class FlexibleDecimalField(forms.DecimalField):
|
||||||
|
|
||||||
@@ -710,6 +716,12 @@ class DataFrameColumnsForm(forms.Form):
|
|||||||
cols = forms.MultipleChoiceField(choices=colchoices,
|
cols = forms.MultipleChoiceField(choices=colchoices,
|
||||||
label='Table Columns')
|
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
|
# form to select modality and boat type for trend flex
|
||||||
class TrendFlexModalForm(forms.Form):
|
class TrendFlexModalForm(forms.Form):
|
||||||
modality = forms.ChoiceField(choices=workouttypes,
|
modality = forms.ChoiceField(choices=workouttypes,
|
||||||
@@ -797,12 +809,6 @@ class PlannedSessionMultipleCloneForm(forms.Form):
|
|||||||
label='Planned Sessions'
|
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):
|
class BoxPlotChoiceForm(forms.Form):
|
||||||
yparam = forms.ChoiceField(choices=parchoices,initial='spm',
|
yparam = forms.ChoiceField(choices=parchoices,initial='spm',
|
||||||
|
|||||||
@@ -1214,12 +1214,13 @@ def fitnessmetric_chart(fitnessmetrics,user,workoutmode='rower',startdate=None,
|
|||||||
|
|
||||||
return [script,div]
|
return [script,div]
|
||||||
|
|
||||||
def interactive_histoall(theworkouts):
|
def interactive_histoall(theworkouts,histoparam,includereststrokes):
|
||||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
||||||
|
|
||||||
ids = [int(w.id) for w in theworkouts]
|
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)
|
rowdata.dropna(axis=0,how='any',inplace=True)
|
||||||
|
|
||||||
@@ -1227,16 +1228,16 @@ def interactive_histoall(theworkouts):
|
|||||||
return "","No Valid Data Available","",""
|
return "","No Valid Data Available","",""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
histopwr = rowdata['power'].values
|
histopwr = rowdata[histoparam].values
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return "","No power data","",""
|
return "","No data","",""
|
||||||
if len(histopwr) == 0:
|
if len(histopwr) == 0:
|
||||||
return "","No valid data available","",""
|
return "","No valid data available","",""
|
||||||
|
|
||||||
# throw out nans
|
# throw out nans
|
||||||
histopwr = histopwr[~np.isinf(histopwr)]
|
histopwr = histopwr[~np.isinf(histopwr)]
|
||||||
histopwr = histopwr[histopwr > 25]
|
histopwr = histopwr[histopwr > yaxminima[histoparam]]
|
||||||
histopwr = histopwr[histopwr < 1000]
|
histopwr = histopwr[histopwr < yaxmaxima[histoparam]]
|
||||||
|
|
||||||
plot = Figure(tools=TOOLS,plot_width=900,
|
plot = Figure(tools=TOOLS,plot_width=900,
|
||||||
toolbar_sticky=False,
|
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=edges[:-1],right=edges[1:])
|
||||||
plot.quad(top='hist_norm',bottom=0,left='left',right='right',source=source)
|
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.yaxis.axis_label = "% of strokes"
|
||||||
plot.y_range = Range1d(0,1.05*max(hist_norm))
|
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 = plot.select(dict(type=HoverTool))
|
||||||
|
|
||||||
hover.tooltips = OrderedDict([
|
hover.tooltips = OrderedDict([
|
||||||
('Power(W)','@left{int}'),
|
(axlabels[histoparam],'@left{int}'),
|
||||||
('% of strokes','@hist_norm'),
|
('% of strokes','@hist_norm'),
|
||||||
('Cumulative %','@histsum{int}'),
|
('Cumulative %','@histsum{int}'),
|
||||||
])
|
])
|
||||||
@@ -1311,12 +1312,36 @@ def interactive_histoall(theworkouts):
|
|||||||
axis_label="Cumulative % of strokes"),'right')
|
axis_label="Cumulative % of strokes"),'right')
|
||||||
|
|
||||||
plot.sizing_mode = 'scale_width'
|
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:
|
try:
|
||||||
script, div = components(plot)
|
script, div = components(layout)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
script = ''
|
script = ''
|
||||||
div = ''
|
div = ''
|
||||||
|
|
||||||
|
|
||||||
return [script,div]
|
return [script,div]
|
||||||
|
|
||||||
def course_map(course):
|
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="",
|
annotation = TextInput(title="Type your plot notes here", value="",
|
||||||
callback=callback)
|
callback=callback)
|
||||||
callback.args["annotation"] = annotation
|
callback.args["annotation"] = annotation
|
||||||
|
|
||||||
slider_spm_min = Slider(start=15.0, end=55,value=15.0, step=.1,
|
slider_spm_min = Slider(start=15.0, end=55,value=15.0, step=.1,
|
||||||
|
|||||||
@@ -40,14 +40,14 @@
|
|||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<li class="rounder">
|
<li class="rounder">
|
||||||
<h2>Power Histogram</h2>
|
<h2>Histogram</h2>
|
||||||
<a href="/rowers/histo/">
|
<a href="/rowers/histo/">
|
||||||
<div class="vignet">
|
<div class="vignet">
|
||||||
<img src="/static/img/histogram.png" alt="Power Histogram">
|
<img src="/static/img/histogram.png" alt="Power Histogram">
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<p>
|
<p>
|
||||||
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.
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<li class="rounder">
|
<li class="rounder">
|
||||||
|
|||||||
@@ -75,6 +75,8 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h1>Histogram View</h1>
|
||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
|
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
@@ -100,6 +102,11 @@
|
|||||||
{{ form.as_table }}
|
{{ form.as_table }}
|
||||||
</table>
|
</table>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<table>
|
||||||
|
{{ histoform.as_table }}
|
||||||
|
</table>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input class="button green small" value="Submit" type="Submit">
|
<input class="button green small" value="Submit" type="Submit">
|
||||||
|
|||||||
@@ -62,9 +62,9 @@
|
|||||||
<i class="fal fa-table fa-fw"></i> Statistics
|
<i class="fal fa-table fa-fw"></i> Statistics
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li id="stats-histopower">
|
<li id="stats-histo">
|
||||||
<a href="/rowers/histo/">
|
<a href="/rowers/histo/">
|
||||||
<i class="fas fa-chart-bar"></i> Power Histogram
|
<i class="fas fa-chart-bar"></i> Histogram
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -20,11 +20,17 @@ def histo(request,theuser=0,
|
|||||||
'workouttypes':[i[0] for i in mytypes.workouttypes],
|
'workouttypes':[i[0] for i in mytypes.workouttypes],
|
||||||
'waterboattype':mytypes.waterboattype,
|
'waterboattype':mytypes.waterboattype,
|
||||||
'rankingonly': False,
|
'rankingonly': False,
|
||||||
|
'histoparam':'power'
|
||||||
}):
|
}):
|
||||||
|
|
||||||
r = getrequestrower(request,userid=theuser)
|
r = getrequestrower(request,userid=theuser)
|
||||||
theuser = r.user
|
theuser = r.user
|
||||||
|
|
||||||
|
if 'histoparam' in request.session:
|
||||||
|
histoparam = request.session['histoparam']
|
||||||
|
else:
|
||||||
|
histoparam = 'power'
|
||||||
|
|
||||||
if 'waterboattype' in request.session:
|
if 'waterboattype' in request.session:
|
||||||
waterboattype = request.session['waterboattype']
|
waterboattype = request.session['waterboattype']
|
||||||
else:
|
else:
|
||||||
@@ -81,6 +87,7 @@ def histo(request,theuser=0,
|
|||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
form = DateRangeForm(request.POST)
|
form = DateRangeForm(request.POST)
|
||||||
modalityform = TrendFlexModalForm(request.POST)
|
modalityform = TrendFlexModalForm(request.POST)
|
||||||
|
histoform = HistoForm(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
startdate = form.cleaned_data['startdate']
|
startdate = form.cleaned_data['startdate']
|
||||||
enddate = form.cleaned_data['enddate']
|
enddate = form.cleaned_data['enddate']
|
||||||
@@ -110,6 +117,11 @@ def histo(request,theuser=0,
|
|||||||
'startdate': startdate,
|
'startdate': startdate,
|
||||||
'enddate': enddate,
|
'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:
|
else:
|
||||||
form = DateRangeForm(initial={
|
form = DateRangeForm(initial={
|
||||||
'startdate': startdate,
|
'startdate': startdate,
|
||||||
@@ -125,6 +137,10 @@ def histo(request,theuser=0,
|
|||||||
'rankingonly':rankingonly,
|
'rankingonly':rankingonly,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
histoform = HistoForm(initial={
|
||||||
|
'includereststrokes':False,
|
||||||
|
'histoparam':histoparam
|
||||||
|
})
|
||||||
|
|
||||||
negtypes = []
|
negtypes = []
|
||||||
for b in mytypes.boattypes:
|
for b in mytypes.boattypes:
|
||||||
@@ -149,6 +165,7 @@ def histo(request,theuser=0,
|
|||||||
'enddatestring':enddatestring,
|
'enddatestring':enddatestring,
|
||||||
'rankingonly':rankingonly,
|
'rankingonly':rankingonly,
|
||||||
'includereststrokes':includereststrokes,
|
'includereststrokes':includereststrokes,
|
||||||
|
'histoparam':histoparam,
|
||||||
}
|
}
|
||||||
|
|
||||||
request.session['options'] = options
|
request.session['options'] = options
|
||||||
@@ -163,9 +180,21 @@ def histo(request,theuser=0,
|
|||||||
|
|
||||||
request.session['options'] = options
|
request.session['options'] = options
|
||||||
|
|
||||||
|
breadcrumbs = [
|
||||||
|
{
|
||||||
|
'url':'/rowers/analysis',
|
||||||
|
'name':'Analysis'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'url':reverse('histo'),
|
||||||
|
'name': 'Histogram'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
return render(request, 'histo.html',
|
return render(request, 'histo.html',
|
||||||
{'interactiveplot':script,
|
{'interactiveplot':script,
|
||||||
'the_div':div,
|
'the_div':div,
|
||||||
|
'breadcrumbs':breadcrumbs,
|
||||||
'id':theuser,
|
'id':theuser,
|
||||||
'active':'nav-analysis',
|
'active':'nav-analysis',
|
||||||
'theuser':theuser,
|
'theuser':theuser,
|
||||||
@@ -174,6 +203,7 @@ def histo(request,theuser=0,
|
|||||||
'enddate':enddate,
|
'enddate':enddate,
|
||||||
'form':form,
|
'form':form,
|
||||||
'optionsform':modalityform,
|
'optionsform':modalityform,
|
||||||
|
'histoform':histoform,
|
||||||
'teams':get_my_teams(request.user),
|
'teams':get_my_teams(request.user),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -295,6 +325,7 @@ def histo_data(
|
|||||||
'enddatestring':timezone.now().strftime("%Y-%m-%d"),
|
'enddatestring':timezone.now().strftime("%Y-%m-%d"),
|
||||||
'startdatestring':(timezone.now()-datetime.timedelta(days=30)).strftime("%Y-%m-%d"),
|
'startdatestring':(timezone.now()-datetime.timedelta(days=30)).strftime("%Y-%m-%d"),
|
||||||
'deltadays':-1,
|
'deltadays':-1,
|
||||||
|
'histoparam':'power',
|
||||||
}):
|
}):
|
||||||
|
|
||||||
def_options = options
|
def_options = options
|
||||||
@@ -311,6 +342,7 @@ def histo_data(
|
|||||||
theuser = keyvalue_get_default('theuser',options,def_options)
|
theuser = keyvalue_get_default('theuser',options,def_options)
|
||||||
startdatestring = keyvalue_get_default('startdatestring',options,def_options)
|
startdatestring = keyvalue_get_default('startdatestring',options,def_options)
|
||||||
enddatestring = keyvalue_get_default('enddatestring',options,def_options)
|
enddatestring = keyvalue_get_default('enddatestring',options,def_options)
|
||||||
|
histoparam = keyvalue_get_default('histoparam',options,def_options)
|
||||||
|
|
||||||
if modality == 'all':
|
if modality == 'all':
|
||||||
modalities = [m[0] for m in mytypes.workouttypes]
|
modalities = [m[0] for m in mytypes.workouttypes]
|
||||||
@@ -358,7 +390,7 @@ def histo_data(
|
|||||||
rankingpiece__in=rankingpiece)
|
rankingpiece__in=rankingpiece)
|
||||||
|
|
||||||
if allworkouts:
|
if allworkouts:
|
||||||
res = interactive_histoall(allworkouts)
|
res = interactive_histoall(allworkouts,histoparam,includereststrokes)
|
||||||
script = res[0]
|
script = res[0]
|
||||||
div = res[1]
|
div = res[1]
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ from django.http import (
|
|||||||
)
|
)
|
||||||
from django.contrib.auth import authenticate, login, logout
|
from django.contrib.auth import authenticate, login, logout
|
||||||
from rowers.forms import (
|
from rowers.forms import (
|
||||||
ForceCurveOptionsForm,
|
ForceCurveOptionsForm,HistoForm,
|
||||||
LoginForm,DocumentsForm,UploadOptionsForm,ImageForm,CourseForm,
|
LoginForm,DocumentsForm,UploadOptionsForm,ImageForm,CourseForm,
|
||||||
TeamUploadOptionsForm,WorkFlowLeftPanelForm,WorkFlowMiddlePanelForm,
|
TeamUploadOptionsForm,WorkFlowLeftPanelForm,WorkFlowMiddlePanelForm,
|
||||||
WorkFlowLeftPanelElement,WorkFlowMiddlePanelElement,
|
WorkFlowLeftPanelElement,WorkFlowMiddlePanelElement,
|
||||||
|
|||||||
Reference in New Issue
Block a user