Private
Public Access
1
0

force curve with lines

This commit is contained in:
Sander Roosendaal
2019-04-02 19:00:00 +02:00
parent e735d98dcf
commit d251b1ddd4
5 changed files with 127 additions and 34 deletions

View File

@@ -722,7 +722,8 @@ class TrendFlexModalForm(forms.Form):
label='Only Ranking Pieces', label='Only Ranking Pieces',
required=False) required=False)
# This form sets options for the summary stats page # This form sets options for the summary stats page
class StatsOptionsForm(forms.Form): class StatsOptionsForm(forms.Form):
includereststrokes = forms.BooleanField(initial=False,label='Include Rest Strokes',required=False) includereststrokes = forms.BooleanField(initial=False,label='Include Rest Strokes',required=False)
@@ -1181,10 +1182,21 @@ class FlexOptionsForm(forms.Form):
('line','Line Plot'), ('line','Line Plot'),
('scatter','Scatter Plot'), ('scatter','Scatter Plot'),
) )
plottype = forms.ChoiceField(choices=plotchoices,initial='scatter', plottype = forms.ChoiceField(choices=plotchoices,initial='line',
label='Chart Type') label='Chart Type')
class ForceCurveOptionsForm(forms.Form):
includereststrokes = forms.BooleanField(initial=False, required = False,
label='Include Rest Strokes')
plotchoices = (
('line','Force Curve Collection Plot'),
('scatter','Peak Force Scatter Plot'),
('none','Only aggregrate data')
)
plottype = forms.ChoiceField(choices=plotchoices,initial='scatter',
label='Individual Stroke Chart Type')
class FlexAxesForm(forms.Form): class FlexAxesForm(forms.Form):
axchoices = list( axchoices = list(
(ax[0],ax[1]) for ax in axes if ax[0] not in ['cumdist','None'] (ax[0],ax[1]) for ax in axes if ax[0] not in ['cumdist','None']

View File

@@ -17,6 +17,7 @@ from math import pi
from django.utils import timezone from django.utils import timezone
from bokeh.palettes import Dark2_8 as palette from bokeh.palettes import Dark2_8 as palette
from bokeh.models.glyphs import MultiLine
import itertools import itertools
from bokeh.plotting import figure, ColumnDataSource, Figure,curdoc from bokeh.plotting import figure, ColumnDataSource, Figure,curdoc
from bokeh.models import CustomJS,Slider, TextInput,BoxAnnotation from bokeh.models import CustomJS,Slider, TextInput,BoxAnnotation
@@ -374,7 +375,7 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type'):
script,div = components(p) script,div = components(p)
return script,div return script,div
def interactive_forcecurve(theworkouts,workstrokesonly=False): def interactive_forcecurve(theworkouts,workstrokesonly=True,plottype='scatter'):
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]
@@ -642,12 +643,20 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
rowdata rowdata
) )
sourcepoints = ColumnDataSource( if plottype == 'scatter':
data = dict( sourcepoints = ColumnDataSource(
peakforceangle = rowdata['peakforceangle'], data = dict(
peakforce = rowdata['peakforce'] peakforceangle = rowdata['peakforceangle'],
peakforce = rowdata['peakforce']
) )
) )
else:
sourcepoints = ColumnDataSource(
data = dict(
peakforceangle = [],
peakforce = []
))
sourcerange = ColumnDataSource( sourcerange = ColumnDataSource(
data = dict( data = dict(
@@ -697,6 +706,50 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
plot.circle('xslip','yslip',source=sourceslipwash,color="red") plot.circle('xslip','yslip',source=sourceslipwash,color="red")
plot.circle('peakforceangle','peakforce',source=sourcepoints,color='black',alpha=0.1) plot.circle('peakforceangle','peakforce',source=sourcepoints,color='black',alpha=0.1)
if plottype == 'line':
multilinedatax = []
multilinedatay = []
for i in range(len(rowdata)):
x = [
rowdata['catch'].values[i],
rowdata['slip'].values[i]+rowdata['catch'].values[i],
rowdata['peakforceangle'].values[i],
rowdata['finish'].values[i]-rowdata['wash'].values[i],
rowdata['finish'].values[i]
]
y = [
0,
thresholdforce,
rowdata['peakforce'].values[i],
thresholdforce,
0]
multilinedatax.append(x)
multilinedatay.append(y)
sourcemultiline = ColumnDataSource(dict(
x=multilinedatax,
y=multilinedatay,
))
sourcemultiline2 = ColumnDataSource(dict(
x=multilinedatax,
y=multilinedatay,
))
glyph = MultiLine(xs='x',ys='y',line_color='black',line_alpha=0.05)
plot.add_glyph(sourcemultiline,glyph)
else:
sourcemultiline = ColumnDataSource(dict(
x=[],y=[]))
sourcemultiline2 = ColumnDataSource(dict(
x=[],y=[]))
plot.line('x','y',source=source,color="red") plot.line('x','y',source=source,color="red")
plot.add_layout(avf) plot.add_layout(avf)
@@ -801,11 +854,20 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
peakforceanglelabel=peakforceanglelabel, peakforceanglelabel=peakforceanglelabel,
annolabel=annolabel, annolabel=annolabel,
sliderlabel=sliderlabel, sliderlabel=sliderlabel,
plottype=plottype,
sourcemultiline=sourcemultiline,
sourcemultiline2=sourcemultiline2
), code=""" ), code="""
var data = source.data var data = source.data
var data2 = source2.data var data2 = source2.data
var dataslipwash = sourceslipwash.data var dataslipwash = sourceslipwash.data
var datapoints = sourcepoints.data var datapoints = sourcepoints.data
var multilines = sourcemultiline.data
var multilines2 = sourcemultiline2.data
var plottype = plottype
var multilinesx = multilines['xs']
var multilinesy = multilines['ys']
var x = data['x'] var x = data['x']
var y = data['y'] var y = data['y']
@@ -826,6 +888,9 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
var peakforce = data2['peakforce'] var peakforce = data2['peakforce']
var averageforce = data2['averageforce'] var averageforce = data2['averageforce']
var peakforcepoints = datapoints['peakforce']
var peakforceanglepoints = datapoints['peakforceangle']
var annotation = annotation.value var annotation = annotation.value
var minspm = minspm.value var minspm = minspm.value
var maxspm = maxspm.value var maxspm = maxspm.value
@@ -849,13 +914,21 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
datapoints['peakforceangle'] = [] datapoints['peakforceangle'] = []
datapoints['peakforce'] = [] datapoints['peakforce'] = []
multilines['xs'] = []
multilines['ys'] = []
for (i=0; i<c.length; i++) { for (i=0; i<c.length; i++) {
if (spm1[i]>=minspm && spm1[i]<=maxspm) { if (spm1[i]>=minspm && spm1[i]<=maxspm) {
if (distance1[i]>=mindist && distance1[i]<=maxdist) { if (distance1[i]>=mindist && distance1[i]<=maxdist) {
if (driveenergy1[i]>=minwork && driveenergy1[i]<=maxwork) { if (driveenergy1[i]>=minwork && driveenergy1[i]<=maxwork) {
datapoints['peakforceangle'].push(peakforceangle[i]) if (plottype=='scatter') {
datapoints['peakforce'].push(peakforce[i]) datapoints['peakforceangle'].push(peakforceangle[i])
datapoints['peakforce'].push(peakforce[i])
}
if (plottype=='line') {
multilines['xs'].push(multilinesx[i])
multilines['ys'].push(multilinesy[i])
}
catchav += c[i] catchav += c[i]
finishav += finish[i] finishav += finish[i]
slipav += slip[i] slipav += slip[i]
@@ -897,6 +970,7 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
source.change.emit(); source.change.emit();
sourceslipwash.change.emit() sourceslipwash.change.emit()
sourcepoints.change.emit(); sourcepoints.change.emit();
sourcemultiline.change.emit();
""") """)
annotation = TextInput(title="Type your plot notes here", value="", annotation = TextInput(title="Type your plot notes here", value="",

View File

@@ -22,27 +22,24 @@
<h1>Empower Force Curve</h1> <h1>Empower Force Curve</h1>
<ul class="main-content"> <ul class="main-content">
<li class="grid_4">
{% if user.is_authenticated and mayedit %}
<form enctype="multipart/form-data" action="{{ formloc }}" method="post">
{% csrf_token %}
{% if workstrokesonly %}
<input type="hidden" name="workstrokesonly" value="True">
<input class="button blue small" value="Remove Rest Strokes" type="Submit">
{% else %}
<input class="button blue small" type="hidden" name="workstrokesonly" value="False">
<input class="button blue small" value="Include Rest Strokes" type="Submit">
</form>
{% endif %}
<span class="tooltiptext">If your data source allows, this will show or hide strokes taken during rest intervals.</span>
{% endif %}
</li>
<li class="grid_4"> <li class="grid_4">
<div id="theplot" class="flexplot"> <div id="theplot" class="flexplot">
{{ the_div|safe }} {{ the_div|safe }}
</div> </div>
</li> </li>
<li class="grid_4">
<form enctype="multipart/form-data" action="" method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<p>
<input name="chartform" type="submit"
value="Update Chart">
</p>
</form>
</li>
</ul> </ul>

View File

@@ -48,6 +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,
LoginForm,DocumentsForm,UploadOptionsForm,ImageForm,CourseForm, LoginForm,DocumentsForm,UploadOptionsForm,ImageForm,CourseForm,
TeamUploadOptionsForm,WorkFlowLeftPanelForm,WorkFlowMiddlePanelForm, TeamUploadOptionsForm,WorkFlowLeftPanelForm,WorkFlowMiddlePanelForm,
WorkFlowLeftPanelElement,WorkFlowMiddlePanelElement, WorkFlowLeftPanelElement,WorkFlowMiddlePanelElement,

View File

@@ -26,15 +26,24 @@ def workout_forcecurve_view(request,id=0,workstrokesonly=False):
if not promember: if not promember:
return HttpResponseRedirect("/rowers/about/") return HttpResponseRedirect("/rowers/about/")
if request.method == 'POST' and 'workstrokesonly' in request.POST: if request.method == 'POST':
workstrokesonly = request.POST['workstrokesonly'] form = ForceCurveOptionsForm(request.POST)
if workstrokesonly == 'True': if form.is_valid():
workstrokesonly = True includereststrokes = form.cleaned_data['includereststrokes']
plottype = form.cleaned_data['plottype']
workstrokesonly = not includereststrokes
else: else:
workstrokesonly = False workstrokesonly = True
plottype = 'line'
else:
form = ForceCurveOptionsForm()
plottype = 'line'
script,div,js_resources,css_resources = interactive_forcecurve([row], script,div,js_resources,css_resources = interactive_forcecurve(
workstrokesonly=workstrokesonly) [row],
workstrokesonly=workstrokesonly,
plottype=plottype,
)
breadcrumbs = [ breadcrumbs = [
{ {
@@ -53,12 +62,13 @@ def workout_forcecurve_view(request,id=0,workstrokesonly=False):
] ]
r = getrower(request.user) r = getrower(request.user)
return render(request, return render(request,
'forcecurve_single.html', 'forcecurve_single.html',
{ {
'the_script':script, 'the_script':script,
'rower':r, 'rower':r,
'form':form,
'workout':row, 'workout':row,
'breadcrumbs':breadcrumbs, 'breadcrumbs':breadcrumbs,
'active':'nav-workouts', 'active':'nav-workouts',
@@ -67,7 +77,6 @@ def workout_forcecurve_view(request,id=0,workstrokesonly=False):
'css_res':css_resources, 'css_res':css_resources,
'id':id, 'id':id,
'mayedit':mayedit, 'mayedit':mayedit,
'workstrokesonly': not workstrokesonly,
'teams':get_my_teams(request.user), 'teams':get_my_teams(request.user),
}) })