Private
Public Access
1
0

Merge branch 'feature/forcecurve' into develop

This commit is contained in:
Sander Roosendaal
2019-04-02 19:07:23 +02:00
6 changed files with 324 additions and 81 deletions
+13 -1
View File
@@ -723,6 +723,7 @@ class TrendFlexModalForm(forms.Form):
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,9 +1182,20 @@ 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(
+271 -47
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
@@ -64,6 +65,7 @@ activate(settings.TIME_ZONE)
thetimezone = get_current_timezone() thetimezone = get_current_timezone()
from scipy.stats import linregress,percentileofscore from scipy.stats import linregress,percentileofscore
from scipy.spatial import ConvexHull,Delaunay
from scipy import optimize from scipy import optimize
from scipy.signal import savgol_filter from scipy.signal import savgol_filter
from scipy.interpolate import griddata from scipy.interpolate import griddata
@@ -373,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]
@@ -407,96 +409,222 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
# quick linear regression # quick linear regression
# peakforce = slope*peakforceangle + intercept # peakforce = slope*peakforceangle + intercept
slope, intercept, r,p,stderr = linregress(rowdata['peakforceangle'],rowdata['peakforce']) slope, intercept, r,p,stderr = linregress(rowdata['peakforceangle'],rowdata['peakforce'])
theta = np.arctan(slope)
a = rowdata['peakforceangle']-rowdata['peakforceangle'].mean() covariancematrix = np.cov(rowdata['peakforceangle'],y=rowdata['peakforce'])
F = rowdata['peakforce']-rowdata['peakforce'].mean() eig_vals, eig_vecs = np.linalg.eig(covariancematrix)
R = np.array([[np.cos(theta),np.sin(theta)], a = rowdata['peakforceangle']-rowdata['peakforceangle'].median()
[-np.sin(theta),np.cos(theta)]]) F = rowdata['peakforce']-rowdata['peakforce'].median()
Rinv = np.array([[np.cos(theta),np.sin(theta)],
[-np.sin(theta),np.cos(theta)]]) Rinv = eig_vecs
R = np.linalg.inv(Rinv)
x = R[0,0]*a+R[0,1]*F x = R[0,0]*a+R[0,1]*F
y = R[1,0]*a+R[1,1]*F y = R[1,0]*a+R[1,1]*F
x05 = x.quantile(q=0.05) x05 = x.quantile(q=0.01)
x25 = x.quantile(q=0.25) x25 = x.quantile(q=0.15)
x75 = x.quantile(q=0.75) x75 = x.quantile(q=0.85)
x95 = x.quantile(q=0.95) x95 = x.quantile(q=0.99)
y05 = y.quantile(q=0.01)
y25 = y.quantile(q=0.15)
y75 = y.quantile(q=0.85)
y95 = y.quantile(q=0.99)
a25 = Rinv[0,0]*x25 + rowdata['peakforceangle'].median()
F25 = Rinv[1,0]*x25 + rowdata['peakforce'].median()
a25b = Rinv[0,1]*y25 + rowdata['peakforceangle'].median()
F25b = Rinv[1,1]*y25 + rowdata['peakforce'].median()
a75 = Rinv[0,0]*x75 + rowdata['peakforceangle'].median()
F75 = Rinv[1,0]*x75 + rowdata['peakforce'].median()
a75b = Rinv[0,1]*y75 + rowdata['peakforceangle'].median()
F75b = Rinv[1,1]*y75 + rowdata['peakforce'].median()
a05 = Rinv[0,0]*x05 + rowdata['peakforceangle'].median()
F05 = Rinv[1,0]*x05 + rowdata['peakforce'].median()
a05b = Rinv[0,1]*y05 + rowdata['peakforceangle'].median()
F05b = Rinv[1,1]*y05 + rowdata['peakforce'].median()
a95 = Rinv[0,0]*x95 + rowdata['peakforceangle'].median()
F95 = Rinv[1,0]*x95 + rowdata['peakforce'].median()
a95b = Rinv[0,1]*y95 + rowdata['peakforceangle'].median()
F95b = Rinv[1,1]*y95 + rowdata['peakforce'].median()
y05 = y.quantile(q=0.05)
y25 = y.quantile(q=0.25)
y75 = y.quantile(q=0.75)
y95 = y.quantile(q=0.95)
try: try:
catchav = rowdata['catch'].mean() catchav = rowdata['catch'].median()
catch25 = rowdata['catch'].quantile(q=0.25)
catch75 = rowdata['catch'].quantile(q=0.75)
catch05 = rowdata['catch'].quantile(q=0.05)
catch95 = rowdata['catch'].quantile(q=0.95)
except KeyError: except KeyError:
catchav = 0 catchav = 0
catch25 = 0
catch75 = 0
catch05 = 0
catch95 = 0
try: try:
finishav = rowdata['finish'].mean() finishav = rowdata['finish'].median()
finish25 = rowdata['finish'].quantile(q=0.25)
finish75 = rowdata['finish'].quantile(q=0.75)
finish05 = rowdata['finish'].quantile(q=0.05)
finish95 = rowdata['finish'].quantile(q=0.95)
except KeyError: except KeyError:
finishav = 0 finishav = 0
finish25 = 0
finish75 = 0
finish05 = 0
finish95 = 0
try: try:
washav = rowdata['wash'].mean() washav = (rowdata['finish']-rowdata['wash']).median()
wash25 = (rowdata['finish']-rowdata['wash']).quantile(q=0.25)
wash75 = (rowdata['finish']-rowdata['wash']).quantile(q=0.75)
wash05 = (rowdata['finish']-rowdata['wash']).quantile(q=0.05)
wash95 = (rowdata['finish']-rowdata['wash']).quantile(q=0.95)
except KeyError: except KeyError:
washav = 0 washav = 0
wash25 = 0
wash75 = 0
wash05 = 0
wash95 = 0
try: try:
slipav = rowdata['slip'].mean() slipav = (rowdata['slip']+rowdata['catch']).median()
slip25 = (rowdata['slip']+rowdata['catch']).quantile(q=0.25)
slip75 = (rowdata['slip']+rowdata['catch']).quantile(q=0.75)
slip05 = (rowdata['slip']+rowdata['catch']).quantile(q=0.05)
slip95 = (rowdata['slip']+rowdata['catch']).quantile(q=0.95)
except KeyError: except KeyError:
slipav = 0 slipav = 0
slip25 = 0
slip75 = 0
slip05 = 0
slip95 = 0
try: try:
peakforceav = rowdata['peakforce'].mean() peakforceav = rowdata['peakforce'].median()
peakforce25 = rowdata['peakforce'].quantile(q=0.25)
peakforce75 = rowdata['peakforce'].quantile(q=0.75)
peakforce05 = rowdata['peakforce'].quantile(q=0.05)
peakforce95 = rowdata['peakforce'].quantile(q=0.95)
except KeyError: except KeyError:
peakforceav = 0 peakforceav = 0
peakforce25 = 0
peakforce75 = 0
peakforce05 = 0
peakforce95 = 0
try: try:
averageforceav = rowdata['averageforce'].mean() averageforceav = rowdata['averageforce'].median()
except KeyError: except KeyError:
averageforceav = 0 averageforceav = 0
try: try:
peakforceangleav = rowdata['peakforceangle'].mean() peakforceangleav = rowdata['peakforceangle'].median()
peakforceangle05 = rowdata['peakforceangle'].quantile(q=0.05)
peakforceangle25 = rowdata['peakforceangle'].quantile(q=0.25)
peakforceangle75 = rowdata['peakforceangle'].quantile(q=0.75)
peakforceangle95 = rowdata['peakforceangle'].quantile(q=0.95)
except KeyError: except KeyError:
peakforceangleav = 0 peakforceangleav = 0
peakforceangle25 = 0
peakforceangle75 = 0
peakforceangle05 = 0
peakforceangle95 = 0
peakforceangle05 = rowdata['peakforceangle'].quantile(q=0.05)
peakforce05 = rowdata['peakforce'].quantile(q=0.05)
peakforceangle25 = rowdata['peakforceangle'].quantile(q=0.25) #thresholdforce /= 4.45 # N to lbs
peakforce25 = rowdata['peakforce'].quantile(q=0.25) thresholdforce = 100 if 'x' in boattype else 200
points2575 = [
(catch25,0), #0
(slip25,thresholdforce), #1
(a75,F75),#4
(a25b,F25b), #9
(a25,F25), #2
(wash75,thresholdforce), #5
(finish75,0), #6
(finish25,0), #7
(wash25,thresholdforce), #8
(a75b,F75b), #3
(slip75,thresholdforce), #10
(catch75,0), #11
]
points0595 = [
(catch05,0), #0
(slip05,thresholdforce), #1
(a95,F95),#4
(a05b,F05b), #9
(a05,F05), #2
(wash95,thresholdforce), #5
(finish95,0), #6
(finish05,0), #7
(wash05,thresholdforce), #8
(a95b,F95b), #3
(slip95,thresholdforce), #10
(catch95,0), #11
]
hull2575 = ConvexHull(points2575)
angles2575 = []
forces2575 = []
for x,y in points2575:
angles2575.append(x)
forces2575.append(y)
angles0595 = []
forces0595 = []
for x,y in points0595:
angles0595.append(x)
forces0595.append(y)
peakforceangle75 = rowdata['peakforceangle'].quantile(q=0.75)
peakforce75 = rowdata['peakforce'].quantile(q=0.75)
peakforceangle95 = rowdata['peakforceangle'].quantile(q=0.95)
peakforce95 = rowdata['peakforce'].quantile(q=0.95)
x = [catchav, x = [catchav,
catchav+slipav, slipav,
peakforceangleav, peakforceangleav,
finishav-washav, washav,
finishav] finishav]
thresholdforce = 100 if 'x' in boattype else 200
#thresholdforce /= 4.45 # N to lbs
y = [0,thresholdforce, y = [0,thresholdforce,
peakforceav, peakforceav,
thresholdforce,0] thresholdforce,0]
source = ColumnDataSource( source = ColumnDataSource(
data = dict( data = dict(
x = x, x = x,
y = y, y = y,
)) ))
sourceslipwash = ColumnDataSource(
data = dict(
xslip = [slipav,washav],
yslip = [thresholdforce,thresholdforce]
)
)
sourcetrend = ColumnDataSource( sourcetrend = ColumnDataSource(
data = dict( data = dict(
x = [peakforceangle25,peakforceangle75], x = [peakforceangle25,peakforceangle75],
@@ -506,8 +634,8 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
sourcefit = ColumnDataSource( sourcefit = ColumnDataSource(
data = dict( data = dict(
x = rowdata['peakforceangle'], x = np.array([peakforceangle25,peakforceangle75]),
y = slope*rowdata['peakforceangle']+intercept y = slope*np.array([peakforceangle25,peakforceangle75])+intercept
) )
) )
@@ -515,10 +643,27 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
rowdata rowdata
) )
sourcepoints = ColumnDataSource( if plottype == 'scatter':
sourcepoints = ColumnDataSource(
data = dict(
peakforceangle = rowdata['peakforceangle'],
peakforce = rowdata['peakforce']
)
)
else:
sourcepoints = ColumnDataSource(
data = dict(
peakforceangle = [],
peakforce = []
))
sourcerange = ColumnDataSource(
data = dict( data = dict(
peakforceangle = rowdata['peakforceangle'], x2575 = angles2575,
peakforce = rowdata['peakforce'] y2575 = forces2575,
x0595 = angles0595,
y0595 = forces0595,
) )
) )
@@ -555,10 +700,57 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
avf = Span(location=averageforceav,dimension='width',line_color='blue', avf = Span(location=averageforceav,dimension='width',line_color='blue',
line_dash=[6,6],line_width=2) line_dash=[6,6],line_width=2)
plot.circle('peakforceangle','peakforce',source=sourcepoints,color='cyan') plot.patch('x0595','y0595',source=sourcerange,color="red",alpha=0.05)
plot.patch('x2575','y2575',source=sourcerange,color="red",alpha=0.2)
plot.line('x','y',source=source,color="red")
plot.circle('xslip','yslip',source=sourceslipwash,color="red")
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.line('x','y',source=sourcetrend,color="blue")
plot.line('x','y',source=sourcefit,color="green")
plot.add_layout(avf) plot.add_layout(avf)
@@ -598,14 +790,14 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
) )
sliplabel = Label(x=370,y=280,x_units='screen',y_units='screen', sliplabel = Label(x=370,y=280,x_units='screen',y_units='screen',
text="Slip: {slipav:6.2f}".format(slipav=slipav), text="Slip: {slipav:6.2f}".format(slipav=slipav-catchav),
background_fill_alpha=0.7, background_fill_alpha=0.7,
background_fill_color='white', background_fill_color='white',
text_color='red', text_color='red',
) )
washlabel = Label(x=360,y=250,x_units='screen',y_units='screen', washlabel = Label(x=360,y=250,x_units='screen',y_units='screen',
text="Wash: {washav:6.2f}".format(washav=washav), text="Wash: {washav:6.2f}".format(washav=finishav-washav),
background_fill_alpha=0.7, background_fill_alpha=0.7,
background_fill_color='white', background_fill_color='white',
text_color='red', text_color='red',
@@ -650,6 +842,7 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
callback = CustomJS(args = dict( callback = CustomJS(args = dict(
source=source, source=source,
source2=source2, source2=source2,
sourceslipwash=sourceslipwash,
sourcepoints=sourcepoints, sourcepoints=sourcepoints,
avf=avf, avf=avf,
avflabel=avflabel, avflabel=avflabel,
@@ -661,13 +854,26 @@ 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 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']
var xslip = dataslipwash['xslip']
var spm1 = data2['spm'] var spm1 = data2['spm']
var distance1 = data2['distance'] var distance1 = data2['distance']
var driveenergy1 = data2['driveenergy'] var driveenergy1 = data2['driveenergy']
@@ -682,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
@@ -705,13 +914,23 @@ 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') {
xs = [c[i],slip[i],peakforceangle[i],wash[i],finish[i]]
ys = [0,thresholdforce,peakforce[i],thresholdforce,finish[i]]
multilines['xs'].push(xs)
multilines['ys'].push(ys)
}
catchav += c[i] catchav += c[i]
finishav += finish[i] finishav += finish[i]
slipav += slip[i] slipav += slip[i]
@@ -736,6 +955,9 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
data['x'] = [catchav,catchav+slipav,peakforceangleav,finishav-washav,finishav] data['x'] = [catchav,catchav+slipav,peakforceangleav,finishav-washav,finishav]
data['y'] = [0,thresholdforce,peakforceav,thresholdforce,0] data['y'] = [0,thresholdforce,peakforceav,thresholdforce,0]
dataslipwash['xslip'] = [catchav+slipav,finishav-washav]
dataslipwash['yslip'] = [thresholdforce,thresholdforce]
avf.location = averageforceav avf.location = averageforceav
avflabel.text = 'Favg: '+averageforceav.toFixed(2) avflabel.text = 'Favg: '+averageforceav.toFixed(2)
catchlabel.text = 'Catch: '+catchav.toFixed(2) catchlabel.text = 'Catch: '+catchav.toFixed(2)
@@ -748,7 +970,9 @@ def interactive_forcecurve(theworkouts,workstrokesonly=False):
// source.trigger('change'); // source.trigger('change');
source.change.emit(); source.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="",
+12 -15
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>
Binary file not shown.
+1
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,
+17 -8
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 = [
{ {
@@ -59,6 +68,7 @@ def workout_forcecurve_view(request,id=0,workstrokesonly=False):
{ {
'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),
}) })